diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 36705e7997..c5e59913a2 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -25,6 +25,7 @@ /packages/jellyfish-transaction/src/script/defi/ @fuxingloh @canonbrother @ivan-zynesis @monstrobishi /packages/jellyfish-transaction-builder/ @fuxingloh @ivan-zynesis @monstrobishi +/packages/jellyfish-transaction-signature/ @fuxingloh @ivan-zynesis /packages/jellyfish-wallet/ @fuxingloh @ivan-zynesis /packages/jellyfish-wallet-mnemonic/ @fuxingloh @ivan-zynesis /packages/testcontainers/ @fuxingloh diff --git a/.github/governance.yml b/.github/governance.yml index 4c857ca686..653e95b06a 100644 --- a/.github/governance.yml +++ b/.github/governance.yml @@ -42,6 +42,7 @@ issue: - jellyfish-network - jellyfish-transaction - jellyfish-transaction-builder + - jellyfish-transaction-signature - jellyfish-wallet - jellyfish-wallet-mnemonic - testcontainers diff --git a/.github/labeler.yml b/.github/labeler.yml index 29a6d22d8e..00ed34f481 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -56,6 +56,11 @@ labels: matcher: files: "packages/jellyfish-transaction-builder/**" + - label: area/jellyfish-transaction-signature + sync: true + matcher: + files: "packages/jellyfish-transaction-signature/**" + - label: area/jellyfish-wallet-mnemonic sync: true matcher: diff --git a/.github/labels.yml b/.github/labels.yml index ab6c0d09a2..f0709f48c1 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -74,6 +74,8 @@ name: area/jellyfish-transaction - color: fbca04 name: area/jellyfish-transaction-builder +- color: fbca04 + name: area/jellyfish-transaction-signature - color: fbca04 name: area/jellyfish-wallet - color: fbca04 diff --git a/jest.config.js b/jest.config.js index 6e891d4b4f..9a5779d0c1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,10 +8,11 @@ module.exports = { '@defichain/jellyfish-crypto': '/packages/jellyfish-crypto/src', '@defichain/jellyfish-json': '/packages/jellyfish-json/src', '@defichain/jellyfish-network': '/packages/jellyfish-network/src', - '@defichain/jellyfish-transaction': '/packages/jellyfish-transaction/src', + '@defichain/jellyfish-transaction-signature': '/packages/jellyfish-transaction-signature/src', '@defichain/jellyfish-transaction-builder': '/packages/jellyfish-transaction-builder/src', - '@defichain/jellyfish-wallet': '/packages/jellyfish-wallet/src', + '@defichain/jellyfish-transaction': '/packages/jellyfish-transaction/src', '@defichain/jellyfish-wallet-mnemonic': '/packages/jellyfish-wallet-mnemonic/src', + '@defichain/jellyfish-wallet': '/packages/jellyfish-wallet/src', '@defichain/testcontainers': '/packages/testcontainers/src', '@defichain/testing': '/packages/testing/src' }, diff --git a/package-lock.json b/package-lock.json index b1da52c3b8..e46412743d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1516,6 +1516,10 @@ "resolved": "packages/jellyfish-transaction-builder", "link": true }, + "node_modules/@defichain/jellyfish-transaction-signature": { + "resolved": "packages/jellyfish-transaction-signature", + "link": true + }, "node_modules/@defichain/jellyfish-wallet": { "resolved": "packages/jellyfish-wallet", "link": true @@ -29434,7 +29438,8 @@ "license": "MIT", "dependencies": { "@defichain/jellyfish-crypto": "0.0.0", - "@defichain/jellyfish-transaction": "0.0.0" + "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/jellyfish-transaction-signature": "0.0.0" }, "devDependencies": { "@defichain/jellyfish-api-jsonrpc": "0.0.0", @@ -29445,6 +29450,24 @@ "bignumber.js": "^9.0.1" } }, + "packages/jellyfish-transaction-signature": { + "name": "@defichain/jellyfish-transaction-signature", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@defichain/jellyfish-crypto": "0.0.0", + "@defichain/jellyfish-transaction": "0.0.0", + "smart-buffer": "^4.1.0" + }, + "devDependencies": { + "@defichain/jellyfish-api-core": "0.0.0", + "@defichain/jellyfish-api-jsonrpc": "0.0.0", + "@defichain/testcontainers": "0.0.0" + }, + "peerDependencies": { + "bignumber.js": "^9.0.1" + } + }, "packages/jellyfish-wallet": { "name": "@defichain/jellyfish-wallet", "version": "0.0.0", @@ -30721,10 +30744,22 @@ "@defichain/jellyfish-api-jsonrpc": "0.0.0", "@defichain/jellyfish-crypto": "0.0.0", "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/jellyfish-transaction-signature": "0.0.0", "@defichain/testcontainers": "0.0.0", "@defichain/testing": "0.0.0" } }, + "@defichain/jellyfish-transaction-signature": { + "version": "file:packages/jellyfish-transaction-signature", + "requires": { + "@defichain/jellyfish-api-core": "0.0.0", + "@defichain/jellyfish-api-jsonrpc": "0.0.0", + "@defichain/jellyfish-crypto": "0.0.0", + "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/testcontainers": "0.0.0", + "smart-buffer": "^4.1.0" + } + }, "@defichain/jellyfish-wallet": { "version": "file:packages/jellyfish-wallet", "requires": { diff --git a/packages/jellyfish-transaction-builder/__tests__/raw_crafting.ts b/packages/jellyfish-transaction-builder/__tests__/raw_crafting.ts index 0c74236892..312e36f0b6 100644 --- a/packages/jellyfish-transaction-builder/__tests__/raw_crafting.ts +++ b/packages/jellyfish-transaction-builder/__tests__/raw_crafting.ts @@ -5,9 +5,9 @@ import { CTransactionSegWit, DeFiTransactionConstants, Transaction, - TransactionSigner, OP_CODES } from '@defichain/jellyfish-transaction' +import { TransactionSigner } from '@defichain/jellyfish-transaction-signature' import { WIF, HASH160 } from '@defichain/jellyfish-crypto' import { SmartBuffer } from 'smart-buffer' diff --git a/packages/jellyfish-transaction-builder/package.json b/packages/jellyfish-transaction-builder/package.json index 6fa402e2fd..4843eba19b 100644 --- a/packages/jellyfish-transaction-builder/package.json +++ b/packages/jellyfish-transaction-builder/package.json @@ -39,7 +39,8 @@ }, "dependencies": { "@defichain/jellyfish-crypto": "0.0.0", - "@defichain/jellyfish-transaction": "0.0.0" + "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/jellyfish-transaction-signature": "0.0.0" }, "devDependencies": { "@defichain/jellyfish-api-jsonrpc": "0.0.0", diff --git a/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts b/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts index cfcd0a8796..0efdc20adc 100644 --- a/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts +++ b/packages/jellyfish-transaction-builder/src/txn/txn_builder.ts @@ -1,11 +1,11 @@ import { DeFiTransactionConstants, OP_CODES, Script, - SignInputOption, Transaction, TransactionSegWit, - TransactionSigner, Vin, Vout, OP_DEFI_TX + Vin, Vout, OP_DEFI_TX } from '@defichain/jellyfish-transaction' +import { TransactionSigner, SignInputOption } from '@defichain/jellyfish-transaction-signature' import { BigNumber } from 'bignumber.js' import { EllipticPairProvider, FeeRateProvider, Prevout, PrevoutProvider } from '../provider' import { calculateFeeP2WPKH } from './txn_fee' diff --git a/packages/jellyfish-transaction-signature/README.md b/packages/jellyfish-transaction-signature/README.md new file mode 100644 index 0000000000..653c916d2a --- /dev/null +++ b/packages/jellyfish-transaction-signature/README.md @@ -0,0 +1,12 @@ +[![npm](https://img.shields.io/npm/v/@defichain/jellyfish-transaction-signature)](https://www.npmjs.com/package/@defichain/jellyfish-transaction-signature/v/latest) +[![npm@next](https://img.shields.io/npm/v/@defichain/jellyfish-transaction-signature/next)](https://www.npmjs.com/package/@defichain/jellyfish-transaction-signature/v/next) + +# @defichain/jellyfish-transaction-signature + +Stateless utility library to perform transaction signing. + +## Prior-art + +- https://github.com/ilyavf/tx-builder +- https://github.com/bitpay/bitcore +- https://github.com/bitcoinjs/bitcoinjs-lib \ No newline at end of file diff --git a/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_1.test.ts b/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_1.test.ts new file mode 100644 index 0000000000..702ff3e434 --- /dev/null +++ b/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_1.test.ts @@ -0,0 +1,40 @@ +import BigNumber from 'bignumber.js' +import { SmartBuffer } from 'smart-buffer' +import { Bech32, WIF } from '@defichain/jellyfish-crypto' +import { OP_CODES, CTransaction, CTransactionSegWit } from '@defichain/jellyfish-transaction' +import { SignInputOption, TransactionSigner } from '../../src' + +// From Address P2WPKH +const input = { + bech32: 'bcrt1qykj5fsrne09yazx4n72ue4fwtpx8u65zac9zhn', + privKey: 'cQSsfYvYkK5tx3u1ByK2ywTTc9xJrREc1dd67ZrJqJUEMwgktPWN' +} + +const unsigned = '0400000001346faf87ccf6fe45463831a23054780d78e4a6decab10575aba212d2e087eb3d0000000000ffffffff010065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340000000000' +const signed = '04000000000101346faf87ccf6fe45463831a23054780d78e4a6decab10575aba212d2e087eb3d0000000000ffffffff010065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b0803400024730440220691a0adc945ae033716e7025235b19618a579545874521d3d70faffcbe95971602200dd1886fe71ab5ab447077680bf891c8faeede9c52e15c0b3789e128899b320e012103987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe8100000000' + +it('sign transaction', async () => { + const txUnsigned = new CTransaction( + SmartBuffer.fromBuffer(Buffer.from(unsigned, 'hex')) + ) + + const inputs: SignInputOption[] = [{ + prevout: { + script: { + stack: [ + OP_CODES.OP_0, + OP_CODES.OP_PUSHDATA(Bech32.toHash160(input.bech32, 'bcrt', 0x00), 'little') + ] + }, + value: new BigNumber('10'), + tokenId: 0 + }, + ellipticPair: WIF.asEllipticPair(input.privKey) + }] + const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) + + const toBuffer = new SmartBuffer() + txSigned.toBuffer(toBuffer) + + expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) +}) diff --git a/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_2.test.ts b/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_2.test.ts new file mode 100644 index 0000000000..14da8dc657 --- /dev/null +++ b/packages/jellyfish-transaction-signature/__tests__/tx/p2wpkh_1_to_2.test.ts @@ -0,0 +1,40 @@ +import BigNumber from 'bignumber.js' +import { SmartBuffer } from 'smart-buffer' +import { Bech32, WIF } from '@defichain/jellyfish-crypto' +import { OP_CODES, CTransaction, CTransactionSegWit } from '@defichain/jellyfish-transaction' +import { SignInputOption, TransactionSigner } from '../../src' + +// From Address P2WPKH +const input = { + bech32: 'bcrt1qykj5fsrne09yazx4n72ue4fwtpx8u65zac9zhn', + privKey: 'cQSsfYvYkK5tx3u1ByK2ywTTc9xJrREc1dd67ZrJqJUEMwgktPWN' +} + +const unsigned = '040000000193c90783761bf94838ced5a8313eb355c3bdd053cdbdbb3f9e0f3dbc3243609b0000000000ffffffff020065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340080ce341d0000000016001425a544c073cbca4e88d59f95ccd52e584c7e6a820000000000' +const signed = '0400000000010193c90783761bf94838ced5a8313eb355c3bdd053cdbdbb3f9e0f3dbc3243609b0000000000ffffffff020065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340080ce341d0000000016001425a544c073cbca4e88d59f95ccd52e584c7e6a82000247304402201142c461b7b52323654710b14074928dd8e623d75141f9eb8c2132b7cb2d47c202202883fde993e1ecf0cf3955235522e9fe948b523b568d0e6b427f83c6f1b3efd9012103987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe8100000000' + +it('sign transaction', async () => { + const txUnsigned = new CTransaction( + SmartBuffer.fromBuffer(Buffer.from(unsigned, 'hex')) + ) + + const inputs: SignInputOption[] = [{ + prevout: { + script: { + stack: [ + OP_CODES.OP_0, + OP_CODES.OP_PUSHDATA(Bech32.toHash160(input.bech32, 'bcrt', 0x00), 'little') + ] + }, + value: new BigNumber('10'), + tokenId: 0 + }, + ellipticPair: WIF.asEllipticPair(input.privKey) + }] + const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) + + const toBuffer = new SmartBuffer() + txSigned.toBuffer(toBuffer) + + expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) +}) diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts b/packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_input.test.ts similarity index 98% rename from packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts rename to packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_input.test.ts index 0c7f8bc2f8..e79da30be9 100644 --- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts +++ b/packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_input.test.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js' -import { OP_CODES, OP_PUSHDATA, SIGHASH, Transaction, TransactionSigner, Vout } from '../../src' - +import { OP_CODES, OP_PUSHDATA, SIGHASH, Transaction, Vout } from '@defichain/jellyfish-transaction' import { SHA256, HASH160, Elliptic } from '@defichain/jellyfish-crypto' +import { TransactionSigner } from '../../src' describe('sign single input', () => { const transaction: Transaction = { diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts b/packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_transaction.test.ts similarity index 97% rename from packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts rename to packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_transaction.test.ts index 2136031923..810080f74b 100644 --- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts +++ b/packages/jellyfish-transaction-signature/__tests__/tx_signature/sign_transaction.test.ts @@ -1,7 +1,7 @@ import BigNumber from 'bignumber.js' -import { OP_CODES, OP_PUSHDATA, DeFiTransactionConstants, SIGHASH, Transaction, TransactionSigner, Vout } from '../../src' - +import { OP_CODES, OP_PUSHDATA, DeFiTransactionConstants, SIGHASH, Transaction, Vout } from '@defichain/jellyfish-transaction' import { Elliptic } from '@defichain/jellyfish-crypto' +import { TransactionSigner } from '../../src' describe('sign transaction', () => { const transaction: Transaction = { diff --git a/packages/jellyfish-transaction-signature/jest.config.js b/packages/jellyfish-transaction-signature/jest.config.js new file mode 100644 index 0000000000..11d9802ff4 --- /dev/null +++ b/packages/jellyfish-transaction-signature/jest.config.js @@ -0,0 +1,12 @@ +module.exports = { + testEnvironment: 'node', + testMatch: [ + '**/__tests__/**/*.test.ts' + ], + transform: { + '^.+\\.ts$': 'ts-jest' + }, + verbose: true, + clearMocks: true, + testTimeout: 120000 +} diff --git a/packages/jellyfish-transaction-signature/package.json b/packages/jellyfish-transaction-signature/package.json new file mode 100644 index 0000000000..af4442b744 --- /dev/null +++ b/packages/jellyfish-transaction-signature/package.json @@ -0,0 +1,45 @@ +{ + "private": false, + "name": "@defichain/jellyfish-transaction-signature", + "version": "0.0.0", + "description": "A collection of TypeScript + JavaScript tools and libraries for DeFi Blockchain developers to build decentralized finance on Bitcoin", + "keywords": [ + "DeFiChain", + "DeFi", + "Blockchain", + "API", + "Bitcoin" + ], + "repository": "DeFiCh/jellyfish", + "bugs": "https://github.com/DeFiCh/jellyfish/issues", + "license": "MIT", + "contributors": [ + { + "name": "DeFiChain Foundation", + "email": "engineering@defichain.com", + "url": "https://defichain.com/" + }, + { + "name": "DeFi Blockchain Contributors" + }, + { + "name": "DeFi Jellyfish Contributors" + } + ], + "main": "dist", + "types": "dist", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc -b ./tsconfig.build.json" + }, + "peerDependencies": { + "bignumber.js": "^9.0.1" + }, + "dependencies": { + "@defichain/jellyfish-crypto": "0.0.0", + "@defichain/jellyfish-transaction": "0.0.0", + "smart-buffer": "^4.1.0" + } +} diff --git a/packages/jellyfish-transaction-signature/src/index.ts b/packages/jellyfish-transaction-signature/src/index.ts new file mode 100644 index 0000000000..d65cfcaa85 --- /dev/null +++ b/packages/jellyfish-transaction-signature/src/index.ts @@ -0,0 +1 @@ +export * from './tx_signature' diff --git a/packages/jellyfish-transaction/src/tx_signature.ts b/packages/jellyfish-transaction-signature/src/tx_signature.ts similarity index 88% rename from packages/jellyfish-transaction/src/tx_signature.ts rename to packages/jellyfish-transaction-signature/src/tx_signature.ts index b669b8d461..45ad913c4a 100644 --- a/packages/jellyfish-transaction/src/tx_signature.ts +++ b/packages/jellyfish-transaction-signature/src/tx_signature.ts @@ -1,21 +1,20 @@ import { EllipticPair, dSHA256, HASH160 } from '@defichain/jellyfish-crypto' import { SmartBuffer } from 'smart-buffer' -import { Script, Transaction, TransactionSegWit, Vin, Vout, Witness } from './tx' -import { OP_CODES, OP_PUSHDATA } from './script' -import { CWitnessProgram, WitnessProgram } from './tx_segwit' -import { DeFiTransactionConstants } from './index' -import { writeVarUInt } from './buffer/buffer_varuint' -import { ONE_HUNDRED_MILLION, writeBigNumberUInt64 } from './buffer/buffer_bignumber' - -export enum SIGHASH { - ALL = 0x01, - NONE = 0x02, - SINGLE = 0x03, - ANYONECANPAY = 0x80, - ALL_ANYONECANPAY = SIGHASH.ALL | SIGHASH.ANYONECANPAY, - NONE_ANYONECANPAY = SIGHASH.NONE | SIGHASH.ANYONECANPAY, - SINGLE_ANYONECANPAY = SIGHASH.SINGLE | SIGHASH.ANYONECANPAY, -} +import { + Script, + Transaction, + TransactionSegWit, + Vin, + Vout, + Witness, + OP_CODES, + OP_PUSHDATA, + CWitnessProgram, + WitnessProgram, + DeFiTransactionConstants, + SIGHASH, + CVoutV4 +} from '@defichain/jellyfish-transaction' export interface SignInputOption { /** @@ -73,12 +72,7 @@ function hashOutputs (transaction: Transaction, sigHashType: SIGHASH): string { } const buffer = new SmartBuffer() - for (const vout of transaction.vout) { - const satoshi = vout.value.multipliedBy(ONE_HUNDRED_MILLION) - writeBigNumberUInt64(satoshi, buffer) - OP_CODES.toBuffer(vout.script.stack, buffer) - writeVarUInt(vout.tokenId, buffer) - } + transaction.vout.forEach(vout => (new CVoutV4(vout)).toBuffer(buffer)) return dSHA256(buffer.toBuffer()).toString('hex') } diff --git a/packages/jellyfish-transaction-signature/tsconfig.build.json b/packages/jellyfish-transaction-signature/tsconfig.build.json new file mode 100644 index 0000000000..8c0dad4ff7 --- /dev/null +++ b/packages/jellyfish-transaction-signature/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.build.json", + "include": [ + "./src/**/*" + ], + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + }, + "references": [ + {"path": "../jellyfish-transaction/tsconfig.build.json"} + ] +} diff --git a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts index 4b744cd82c..c8a1fb6b65 100644 --- a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_1.test.ts @@ -1,13 +1,5 @@ -import BigNumber from 'bignumber.js' import { SmartBuffer } from 'smart-buffer' -import { Bech32, WIF } from '@defichain/jellyfish-crypto' -import { OP_CODES, CTransaction, CTransactionSegWit, SignInputOption, TransactionSigner } from '../../src' - -// From Address P2WPKH -const input = { - bech32: 'bcrt1qykj5fsrne09yazx4n72ue4fwtpx8u65zac9zhn', - privKey: 'cQSsfYvYkK5tx3u1ByK2ywTTc9xJrREc1dd67ZrJqJUEMwgktPWN' -} +import { CTransaction, CTransactionSegWit } from '../../src' const unsigned = '0400000001346faf87ccf6fe45463831a23054780d78e4a6decab10575aba212d2e087eb3d0000000000ffffffff010065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340000000000' const signed = '04000000000101346faf87ccf6fe45463831a23054780d78e4a6decab10575aba212d2e087eb3d0000000000ffffffff010065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b0803400024730440220691a0adc945ae033716e7025235b19618a579545874521d3d70faffcbe95971602200dd1886fe71ab5ab447077680bf891c8faeede9c52e15c0b3789e128899b320e012103987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe8100000000' @@ -30,29 +22,3 @@ it('bi-directional signed buffer', () => { expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) }) - -it('sign transaction', async () => { - const txUnsigned = new CTransaction( - SmartBuffer.fromBuffer(Buffer.from(unsigned, 'hex')) - ) - - const inputs: SignInputOption[] = [{ - prevout: { - script: { - stack: [ - OP_CODES.OP_0, - OP_CODES.OP_PUSHDATA(Bech32.toHash160(input.bech32, 'bcrt', 0x00), 'little') - ] - }, - value: new BigNumber('10'), - tokenId: 0 - }, - ellipticPair: WIF.asEllipticPair(input.privKey) - }] - const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) - - const toBuffer = new SmartBuffer() - txSigned.toBuffer(toBuffer) - - expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) -}) diff --git a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts index 9759213a5c..1cfa32dce0 100644 --- a/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts +++ b/packages/jellyfish-transaction/__tests__/tx/p2wpkh_1_to_2.test.ts @@ -1,13 +1,5 @@ -import BigNumber from 'bignumber.js' import { SmartBuffer } from 'smart-buffer' -import { Bech32, WIF } from '@defichain/jellyfish-crypto' -import { OP_CODES, CTransaction, CTransactionSegWit, SignInputOption, TransactionSigner } from '../../src' - -// From Address P2WPKH -const input = { - bech32: 'bcrt1qykj5fsrne09yazx4n72ue4fwtpx8u65zac9zhn', - privKey: 'cQSsfYvYkK5tx3u1ByK2ywTTc9xJrREc1dd67ZrJqJUEMwgktPWN' -} +import { CTransaction, CTransactionSegWit } from '../../src' const unsigned = '040000000193c90783761bf94838ced5a8313eb355c3bdd053cdbdbb3f9e0f3dbc3243609b0000000000ffffffff020065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340080ce341d0000000016001425a544c073cbca4e88d59f95ccd52e584c7e6a820000000000' const signed = '0400000000010193c90783761bf94838ced5a8313eb355c3bdd053cdbdbb3f9e0f3dbc3243609b0000000000ffffffff020065cd1d000000001600144ab4391ce5a732e36139e72d79a28e01b7b080340080ce341d0000000016001425a544c073cbca4e88d59f95ccd52e584c7e6a82000247304402201142c461b7b52323654710b14074928dd8e623d75141f9eb8c2132b7cb2d47c202202883fde993e1ecf0cf3955235522e9fe948b523b568d0e6b427f83c6f1b3efd9012103987aec2e508e124468f0f07a836d185b329026e7aaf75be48cf12be8f18cbe8100000000' @@ -30,29 +22,3 @@ it('bi-directional signed buffer', () => { expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) }) - -it('sign transaction', async () => { - const txUnsigned = new CTransaction( - SmartBuffer.fromBuffer(Buffer.from(unsigned, 'hex')) - ) - - const inputs: SignInputOption[] = [{ - prevout: { - script: { - stack: [ - OP_CODES.OP_0, - OP_CODES.OP_PUSHDATA(Bech32.toHash160(input.bech32, 'bcrt', 0x00), 'little') - ] - }, - value: new BigNumber('10'), - tokenId: 0 - }, - ellipticPair: WIF.asEllipticPair(input.privKey) - }] - const txSigned = new CTransactionSegWit(await TransactionSigner.sign(txUnsigned, inputs)) - - const toBuffer = new SmartBuffer() - txSigned.toBuffer(toBuffer) - - expect(toBuffer.toBuffer().toString('hex')).toStrictEqual(signed) -}) diff --git a/packages/jellyfish-transaction/package.json b/packages/jellyfish-transaction/package.json index 0814ca783d..9ec0437927 100644 --- a/packages/jellyfish-transaction/package.json +++ b/packages/jellyfish-transaction/package.json @@ -38,12 +38,6 @@ "bignumber.js": "^9.0.1" }, "dependencies": { - "@defichain/jellyfish-crypto": "0.0.0", "smart-buffer": "^4.1.0" - }, - "devDependencies": { - "@defichain/jellyfish-api-core": "0.0.0", - "@defichain/jellyfish-api-jsonrpc": "0.0.0", - "@defichain/testcontainers": "0.0.0" } } diff --git a/packages/jellyfish-transaction/src/index.ts b/packages/jellyfish-transaction/src/index.ts index 2730613658..b61deb652f 100644 --- a/packages/jellyfish-transaction/src/index.ts +++ b/packages/jellyfish-transaction/src/index.ts @@ -12,4 +12,3 @@ export * from './script' export * from './tx' export * from './tx_composer' export * from './tx_segwit' -export * from './tx_signature' diff --git a/packages/jellyfish-transaction/src/tx.ts b/packages/jellyfish-transaction/src/tx.ts index 0dcc5741d3..da22fd95ea 100644 --- a/packages/jellyfish-transaction/src/tx.ts +++ b/packages/jellyfish-transaction/src/tx.ts @@ -1,6 +1,16 @@ import BigNumber from 'bignumber.js' import { OPCode } from './script' +export enum SIGHASH { + ALL = 0x01, + NONE = 0x02, + SINGLE = 0x03, + ANYONECANPAY = 0x80, + ALL_ANYONECANPAY = SIGHASH.ALL | SIGHASH.ANYONECANPAY, + NONE_ANYONECANPAY = SIGHASH.NONE | SIGHASH.ANYONECANPAY, + SINGLE_ANYONECANPAY = SIGHASH.SINGLE | SIGHASH.ANYONECANPAY, +} + /** * A transaction is a transfer of DeFi values that is broadcast to the DeFi network and collected into blocks. * The transfer of value in DeFi includes unspent, account token, liquidity, masternode creation, etc... diff --git a/packages/jellyfish-transaction/src/tx_segwit.ts b/packages/jellyfish-transaction/src/tx_segwit.ts index 792efd1178..291b511dd1 100644 --- a/packages/jellyfish-transaction/src/tx_segwit.ts +++ b/packages/jellyfish-transaction/src/tx_segwit.ts @@ -1,7 +1,6 @@ import BigNumber from 'bignumber.js' import { SmartBuffer } from 'smart-buffer' -import { Script } from './tx' -import { SIGHASH } from './tx_signature' +import { Script, SIGHASH } from './tx' import { BufferComposer, ComposableBuffer } from './buffer/buffer_composer' import { CScript } from './tx_composer' diff --git a/packages/jellyfish-transaction/tsconfig.build.json b/packages/jellyfish-transaction/tsconfig.build.json index 1976a96d6d..e04e74398d 100644 --- a/packages/jellyfish-transaction/tsconfig.build.json +++ b/packages/jellyfish-transaction/tsconfig.build.json @@ -6,10 +6,5 @@ "compilerOptions": { "outDir": "./dist", "rootDir": "./src", - }, - "references": [ - {"path": "../jellyfish-api-core/tsconfig.build.json"}, - {"path": "../jellyfish-api-jsonrpc/tsconfig.build.json"}, - {"path": "../testcontainers/tsconfig.build.json"} - ] + } } diff --git a/packages/jellyfish-wallet-mnemonic/package.json b/packages/jellyfish-wallet-mnemonic/package.json index 54dfcf5f67..a4d2ca1e0c 100644 --- a/packages/jellyfish-wallet-mnemonic/package.json +++ b/packages/jellyfish-wallet-mnemonic/package.json @@ -37,6 +37,7 @@ "dependencies": { "@defichain/jellyfish-wallet": "0.0.0", "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/jellyfish-transaction-signature": "0.0.0", "bip32": "^2.0.6", "bip39": "^3.0.3" } diff --git a/packages/jellyfish-wallet-mnemonic/src/mnemonic.ts b/packages/jellyfish-wallet-mnemonic/src/mnemonic.ts index f91361c6ea..404e99adff 100644 --- a/packages/jellyfish-wallet-mnemonic/src/mnemonic.ts +++ b/packages/jellyfish-wallet-mnemonic/src/mnemonic.ts @@ -4,9 +4,9 @@ import { Transaction, Vout, TransactionSegWit, - TransactionSigner, - SignInputOption, SIGHASH + SIGHASH } from '@defichain/jellyfish-transaction' +import { SignInputOption, TransactionSigner } from '@defichain/jellyfish-transaction-signature' import * as bip32 from 'bip32' import * as bip39 from 'bip39' diff --git a/packages/jellyfish-wallet/__tests__/node.mock.ts b/packages/jellyfish-wallet/__tests__/node.mock.ts index ddfc74455a..07b9ac1914 100644 --- a/packages/jellyfish-wallet/__tests__/node.mock.ts +++ b/packages/jellyfish-wallet/__tests__/node.mock.ts @@ -1,11 +1,10 @@ import { WalletHdNode, WalletHdNodeProvider } from '../src' import { - SignInputOption, Transaction, TransactionSegWit, - TransactionSigner, Vout } from '@defichain/jellyfish-transaction' +import { SignInputOption, TransactionSigner } from '@defichain/jellyfish-transaction-signature' import { EllipticPair, Elliptic } from '@defichain/jellyfish-crypto' /** diff --git a/packages/jellyfish-wallet/package.json b/packages/jellyfish-wallet/package.json index 8f0383289b..30d53ff9c3 100644 --- a/packages/jellyfish-wallet/package.json +++ b/packages/jellyfish-wallet/package.json @@ -40,6 +40,7 @@ "dependencies": { "@defichain/jellyfish-address": "0.0.0", "@defichain/jellyfish-crypto": "0.0.0", - "@defichain/jellyfish-transaction": "0.0.0" + "@defichain/jellyfish-transaction": "0.0.0", + "@defichain/jellyfish-transaction-signature": "0.0.0" } } diff --git a/tsconfig.build.json b/tsconfig.build.json index 7d090a6dd6..63d7bb7c5c 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -16,6 +16,7 @@ {"path": "./packages/jellyfish-network/tsconfig.build.json"}, {"path": "./packages/jellyfish-transaction/tsconfig.build.json"}, {"path": "./packages/jellyfish-transaction-builder/tsconfig.build.json"}, + {"path": "./packages/jellyfish-transaction-signature/tsconfig.build.json"}, {"path": "./packages/jellyfish-wallet/tsconfig.build.json"}, {"path": "./packages/jellyfish-wallet-mnemonic/tsconfig.build.json"}, {"path": "./packages/testcontainers/tsconfig.build.json"}, diff --git a/tsconfig.json b/tsconfig.json index 14e45cd2c2..d5e7562dc0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "@defichain/jellyfish-network": ["jellyfish-network/src"], "@defichain/jellyfish-transaction": ["jellyfish-transaction/src"], "@defichain/jellyfish-transaction-builder": ["jellyfish-transaction-builder/src"], + "@defichain/jellyfish-transaction-signature": ["jellyfish-transaction-signature/src"], "@defichain/jellyfish-wallet": ["jellyfish-wallet/src"], "@defichain/jellyfish-wallet-mnemonic": ["jellyfish-wallet-mnemonic/src"], "@defichain/testcontainers": ["testcontainers/src"], @@ -24,6 +25,7 @@ "@defichain/jellyfish-network/*": ["jellyfish-network/src/*"], "@defichain/jellyfish-transaction/*": ["jellyfish-transaction/src/*"], "@defichain/jellyfish-transaction-builder/*": ["jellyfish-transaction-builder/src/*"], + "@defichain/jellyfish-transaction-signature/*": ["jellyfish-transaction-signature/src/*"], "@defichain/jellyfish-wallet/*": ["jellyfish-wallet/src/*"], "@defichain/jellyfish-wallet-mnemonic/*": ["jellyfish-wallet-mnemonic/src/*"], "@defichain/testcontainers/*": ["testcontainers/src/*"], diff --git a/website/docs/introduction.md b/website/docs/introduction.md index 3ef1edec66..8712dc4165 100644 --- a/website/docs/introduction.md +++ b/website/docs/introduction.md @@ -36,6 +36,7 @@ Package | Description `@defichain/jellyfish-network` | Contains DeFi blockchain various network configuration for mainnet, testnet and regtest. `@defichain/jellyfish-transaction` | Dead simple modern stateless raw transaction composer for the DeFi Blockchain. `@defichain/jellyfish-transaction-builder` | Provides a high-high level abstraction for constructing transaction ready to be broadcast for DeFi Blockchain. +`@defichain/jellyfish-transaction-signature` | Stateless utility library to perform transaction signing. `@defichain/jellyfish-wallet` | Jellyfish wallet is a managed wallet, where account can get discovered from an HD seed. `@defichain/jellyfish-wallet-mnemonic` | MnemonicHdNode implements the WalletHdNode from jellyfish-wallet; a CoinType-agnostic HD Wallet for noncustodial DeFi. `@defichain/testcontainers` | Provides a lightweight, throw away instances for DeFiD node provisioned automatically in a Docker container.