diff --git a/.idea/dictionaries/fuxing.xml b/.idea/dictionaries/fuxing.xml
index 2b5e0706a9..070bc95cfb 100644
--- a/.idea/dictionaries/fuxing.xml
+++ b/.idea/dictionaries/fuxing.xml
@@ -85,6 +85,7 @@
isvalid
iswatchonly
iswitness
+ jingyi
jsonrpc
keyhash
keypoololdest
@@ -188,4 +189,4 @@
wtxid
-
+
\ No newline at end of file
diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts b/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts
index 70ea6c5b9d..b0bd769f02 100644
--- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts
+++ b/packages/jellyfish-transaction/__tests__/tx_signature/sign_input.test.ts
@@ -149,6 +149,24 @@ describe('sign single input', () => {
.rejects.toThrow('witnessScript required, only P2WPKH can be guessed')
})
+ it('should fail as isV0P2WPKH cannot match provided prevout ', async () => {
+ return await expect(TransactionSigner.signInput(transaction, 1, {
+ prevout: {
+ script: {
+ stack: [
+ OP_CODES.OP_0,
+ // hash is invalid
+ OP_CODES.OP_PUSHDATA(Buffer.from('1d0f172a0ecb48aee1be1f2687d2963ae33f71a0', 'hex'), 'little')
+ ]
+ },
+ value: new BigNumber('6'),
+ dct_id: 0x00
+ },
+ ellipticPair: keyPair
+ }, SIGHASH.ALL))
+ .rejects.toThrow('invalid input option - attempting to sign a mismatch vout and elliptic pair is not allowed')
+ })
+
describe('SIGHASH for consistency should err-out as they are not implemented', () => {
it('should err SIGHASH.NONE', async () => {
return await expect(TransactionSigner.signInput(transaction, 1, {
diff --git a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts b/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts
index e745736c4f..00adba9ee5 100644
--- a/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts
+++ b/packages/jellyfish-transaction/__tests__/tx_signature/sign_transaction.test.ts
@@ -68,11 +68,37 @@ describe('sign transaction', () => {
expect(signed.lockTime).toBe(0x00000000)
})
- describe('validate', () => {
+ describe('validation', () => {
+ it('should fail as vin.length == 0', async () => {
+ const txn: Transaction = {
+ ...transaction,
+ vin: []
+ }
+ return await expect(TransactionSigner.sign(txn, []))
+ .rejects.toThrow('vin.length = 0 - attempting to sign transaction without vin is not allowed')
+ })
+
+ it('should fail as provided prevout and ellipticPair is mismatched', async () => {
+ const input = {
+ prevout: {
+ script: {
+ stack: [
+ OP_CODES.OP_0,
+ OP_CODES.OP_PUSHDATA(Buffer.from('1d0f172a0ecb48aee1be1f2687d2963ae33f71a0', 'hex'), 'little')
+ ]
+ },
+ value: new BigNumber('1000'),
+ dct_id: 0x00
+ },
+ ellipticPair: keyPair
+ }
+ return await expect(TransactionSigner.sign(transaction, [input]))
+ .rejects.toThrow('invalid input option - attempting to sign a mismatch vout and elliptic pair is not allowed')
+ })
+
it('should fail as vin.length != inputOptions.length', async () => {
- return await expect(TransactionSigner.sign(transaction, [inputOption, inputOption], {
- sigHashType: SIGHASH.NONE
- })).rejects.toThrow('vin.length and inputOptions.length must match')
+ return await expect(TransactionSigner.sign(transaction, [inputOption, inputOption]))
+ .rejects.toThrow('vin.length and inputOptions.length must match')
})
it('should fail if version is different from DeFiTransactionConstants.Version', async () => {
diff --git a/packages/jellyfish-transaction/src/tx_signature.ts b/packages/jellyfish-transaction/src/tx_signature.ts
index 544ba8426d..2e6b47cc36 100644
--- a/packages/jellyfish-transaction/src/tx_signature.ts
+++ b/packages/jellyfish-transaction/src/tx_signature.ts
@@ -81,6 +81,32 @@ function hashOutputs (transaction: Transaction, sigHashType: SIGHASH): string {
return dSHA256(buffer.toBuffer()).toString('hex')
}
+/**
+ *
+ * The witness must consist of exactly 2 items.
+ * The '0' in scriptPubKey indicates the following push is a version 0 witness program.
+ * The length of 20 indicates that it is a P2WPKH type.
+ *
+ * @param {SignInputOption} signInputOption to check is is V0 P2WPKH
+ */
+async function isV0P2WPKH (signInputOption: SignInputOption): Promise {
+ const stack = signInputOption.prevout.script.stack
+
+ if (stack.length === 2 && stack[1] instanceof OP_PUSHDATA && (stack[1] as OP_PUSHDATA).length() === 20) {
+ const pubkey: Buffer = await signInputOption.ellipticPair.publicKey()
+ const pubkeyHashHex = HASH160(pubkey).toString('hex')
+ const pushDataHex = (stack[1] as OP_PUSHDATA).hex
+
+ if (pubkeyHashHex === pushDataHex) {
+ return true
+ }
+
+ throw new Error('invalid input option - attempting to sign a mismatch vout and elliptic pair is not allowed')
+ }
+
+ return false
+}
+
/**
* If script is not provided, it needs to be guessed
*
@@ -88,16 +114,11 @@ function hashOutputs (transaction: Transaction, sigHashType: SIGHASH): string {
* @param {SignInputOption} signInputOption to sign the vin
*/
async function getScriptCode (vin: Vin, signInputOption: SignInputOption): Promise