-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TransactionBuilder.fromTransaction (Transaction.fromHex ()) and segwit input signing #901
Comments
Can you provide a complete test fixture? Aka, a |
I create a full example reproducing my problem; the script sign correctly with the first privkey, but fail trying to sign after serialize/parse (toHex -> fromHex) procedure var bitcoin = require('bitcoinjs-lib')
// Bitcoin address : mhqo9zJRm4gBYFmBD6kCVCfZL3JS5UqLmj
var key1 = {
priv: 'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
pub: '03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877'
};
// Bitcoin address : mpSAvmKXAE8B6H6bgLnGBG8iyC6tQgEy9D
var key2 = {
priv: 'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
pub: '020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0'
};
// Bitcoin address : mq1HD5wiNLCNQv8u9wdwLvRH5JiMbxJHR4
var key3 = {
priv: 'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF',
pub: '02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149'
};
var keyPairs = [
'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF'
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet) })
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
var witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
var witnessScriptHash = bitcoin.crypto.sha256(witnessScript)
var redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)
console.log(P2SHaddress)
console.log (scriptPubKey)
// 2Mv8kEd3D7PaYciMYMgQU3zGTv5RgsYDUDy
var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)
txb.addInput('f3e785dff9694a463f5f17570c2940aa8e65117ae69184e5fa8de69ac4ae3481', 1);
txb.addOutput (scriptPubKey, (1000000 - 10000) / 2);
txb.addOutput ("n2iptWzMeDb35222vkp3SA9ytsac3skwjU", (1000000 - 10000) / 2);
txb.sign(0, keyPairs[0], redeemScript, null, 1000000, witnessScript)
var txhex = txb.buildIncomplete ().toHex ();
var txb = new bitcoin.TransactionBuilder.fromTransaction (
bitcoin.Transaction.fromHex (txhex), bitcoin.networks.testnet);
var witnessScript = bitcoin.script.multisig.output.encode (2, pubKeys);
var redeemScript = bitcoin.script.witnessScriptHash.output.encode (bitcoin.crypto.sha256(witnessScript));
var scriptPubKey = bitcoin.script.scriptHash.output.encode (bitcoin.crypto.hash160(redeemScript));
var address = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet);
txb.sign (0, keyPairs[1], redeemScript, null, 1000000, witnessScript);
var tx = txb.build ();
var txhex = tx.toHex ();
console.log (txhex); Also, this is the previous example without toHex fromHex, and it works: var bitcoin = require('bitcoinjs-lib')
// Bitcoin address : mhqo9zJRm4gBYFmBD6kCVCfZL3JS5UqLmj
var key1 = {
priv: 'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
pub: '03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877'
};
// Bitcoin address : mpSAvmKXAE8B6H6bgLnGBG8iyC6tQgEy9D
var key2 = {
priv: 'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
pub: '020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0'
};
// Bitcoin address : mq1HD5wiNLCNQv8u9wdwLvRH5JiMbxJHR4
var key3 = {
priv: 'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF',
pub: '02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149'
};
var keyPairs = [
'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF'
].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet) })
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
var witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
var witnessScriptHash = bitcoin.crypto.sha256(witnessScript)
var redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
var scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
var P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)
console.log(P2SHaddress)
console.log (scriptPubKey)
// 2Mv8kEd3D7PaYciMYMgQU3zGTv5RgsYDUDy
var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)
txb.addInput('f3e785dff9694a463f5f17570c2940aa8e65117ae69184e5fa8de69ac4ae3481', 1);
txb.addOutput (scriptPubKey, (1000000 - 10000) / 2);
txb.addOutput ("n2iptWzMeDb35222vkp3SA9ytsac3skwjU", (1000000 - 10000) / 2);
txb.sign(0, keyPairs[0], redeemScript, null, 1000000, witnessScript)
var witnessScript = bitcoin.script.multisig.output.encode (2, pubKeys);
var redeemScript = bitcoin.script.witnessScriptHash.output.encode (bitcoin.crypto.sha256(witnessScript));
var scriptPubKey = bitcoin.script.scriptHash.output.encode (bitcoin.crypto.hash160(redeemScript));
var address = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet);
txb.sign (0, keyPairs[1], redeemScript, null, 1000000, witnessScript);
var tx = txb.build ();
var txhex = tx.toHex ();
console.log (txhex); |
Reproduced with // Bitcoin address : mhqo9zJRm4gBYFmBD6kCVCfZL3JS5UqLmj
let key1 = {
priv: 'cUxccFVBdJRq6HnyxiFMd8Z15GLThXaNLcnPBgoXLEv9iX6wuV2b',
pub: '03c411cf39aca4395c81c35921dc832a0d1585d652ab1b52ccc619ff9fbbc57877'
}
// Bitcoin address : mpSAvmKXAE8B6H6bgLnGBG8iyC6tQgEy9D
let key2 = {
priv: 'cVSNe9ZdZRsRvEBL8YRR7YiZmH4cLsf5FthgERWkZezJVrGseaXy',
pub: '020636d944458a4663b75a912c37dc1cd59b11f9a00106783a65ba230d929b96b0'
}
// Bitcoin address : mq1HD5wiNLCNQv8u9wdwLvRH5JiMbxJHR4
let key3 = {
priv: 'cQqbmgCQroize8cD1484C5243Q7twmHq5YjN3fYFayApcfoZykcF',
pub: '02d1448cbf19528a1a27e5958ba73d930b5b3facdbe5c30c7094951a287fcc9149'
}
let bitcoin = require('./')
let keyPairs = [key1.priv, key2.priv, key3.priv].map(function (wif) {
return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.testnet)
})
let pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
let itxhex
{
let witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
let witnessScriptHash = bitcoin.crypto.sha256(witnessScript)
let redeemScript = bitcoin.script.witnessScriptHash.output.encode(witnessScriptHash)
let redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
let scriptPubKey = bitcoin.script.scriptHash.output.encode(redeemScriptHash)
let P2SHaddress = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)
console.log(P2SHaddress)
console.log(scriptPubKey)
// 2Mv8kEd3D7PaYciMYMgQU3zGTv5RgsYDUDy
let txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet)
txb.addInput('f3e785dff9694a463f5f17570c2940aa8e65117ae69184e5fa8de69ac4ae3481', 1)
txb.addOutput(scriptPubKey, (1000000 - 10000) / 2)
txb.addOutput('n2iptWzMeDb35222vkp3SA9ytsac3skwjU', (1000000 - 10000) / 2)
txb.sign(0, keyPairs[0], redeemScript, null, 1000000, witnessScript)
itxhex = txb.buildIncomplete().toHex()
}
{
let txb = bitcoin.TransactionBuilder.fromTransaction(bitcoin.Transaction.fromHex(itxhex), bitcoin.networks.testnet)
let witnessScript = bitcoin.script.multisig.output.encode(2, pubKeys)
let redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
// let scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
// let address = bitcoin.address.fromOutputScript(scriptPubKey, bitcoin.networks.testnet)
txb.sign(0, keyPairs[1], redeemScript, null, 1000000, witnessScript)
let tx = txb.build()
let txhex = tx.toHex()
console.log(txhex)
} Which isolates the variables with block scoping. Will investigate. |
Closing in favour of #908 |
This isn't over yet... the witness is malformed (missing key1 signature). |
See #910 |
* add testnet bip49 example * Should be able to deal with incomplete P2SH/P2WSH inputs when allowIncomplete is set * remove redundant baddress.toOutputScript call from tests * set p2sh=true only if redeemScriptType is set * testing/integration/examples: isolate to addresses/transactions examples, use public broadcast endpoints * tests/integration: add BIP32 serialization and multi-child examples * README: re-generate examples list * README: drop Contributors * README: add bech32 * README: move BCoin to Alternative * README: drop insight * README: add helperbit * LICENSE: 2017 too * add from/toBech32 * add Bech32 support to toOutputScript/fromOutputScript * README/tests: add BIP173/BIP16 SegWit address examples * tests: add P2WPK, P2WSH spend example * tests: resist txn-mempool-conflicts * tests/txb: add P2WSH(multisig), incomplete fixture * txbuilder: refactor branches for readability * add witnessPubKeyHash compressed policy * templates/pubkey: only canonical pubkeys to encode * TxBuilder: restrict uncompressed keyPairs for P2WPK and P2WSH * script: use asMinimalOP for ASM/decompile * Fix the integration url's to latest version also some of the urls were broken * add bech32 fixture * Fixed Segwit links The links were redirecting to 404 - I've modified them so they adhere to the beginning of the respective Segwit unit tests. * Fixed some README links Found some more links that were displaced by the Segwit unit tests and fixed them * typescript instructions on README closes: bitcoinjs#815 * README: cleanup typescript help * Add witness is true to signing * Add test for witness = true edge case during multisigning * TransactionBuilder: collect witnessValue as input.value, and match it * Fix txb.__overMaximumFees for segwit * Add test case * Fix absurd fee in fixture * buildstack - don't return op_0 * multisig.input.encodestack - replace OP_0 (permitted by partialSignature) with EMPTY_BUFFER * update CHANGELOG * 3.2.0 * tests: script tests can validate template fixtures too * match scriptHash types 1 for 1, ignore classify order * add fixture to verify input type classification (cherry picked from commit 8f9d8b7) * respond to Jonathan Underwood's comments (cherry picked from commit 8126ca2) * tests/fixtures: amend truncated outputHex * README: add notes about ES5, Node LTS feature tracking * package: rm contributors field, outdated, update wallet estimate * rm bscript circular dependencies * txbuilder: fix canSign returning true for missing witness value * address/txbuilder: require templates to prevent undefined exports * tests: add passing and failing tests for witness*.input.encode/decode * witnessScriptHash: fixed implementation * tests: add failing staged transaction building example bitcoinjs#901 * txbuilder: apply input.value before prepareInput * s/checkP2shInput/checkP2SHInput * 3.2.1 * ECSignature: add toRSBuffer/fromRSBuffer * TxBuilder: add support for RSBuffer type keyPairs and .publicKey * 3.3.0 * tests: txb for TxBuilder, Tx for Transaction * increase max feerate sanity check from 1000 to 2500 * 3.3.1 * opt-in bitcoin-cash support in transaction_builder * TransactionBuilder.fromTransaction & Bitcoin Cash Adds an extra parameter to fromTransaction, which tells the library to expect a value property to be added on each txin which uses bitcoin cash's sighashtype * bitcoin gold support * package: rename to bitcoinforksjs-lib
Version: Bitcoinjs-0.3.2 and also bitcoinjs/bitcoinjs-lib#fixes
I'm trying to integrate segwit in my walleting software, but I'm stuck in one problem. The flow is the following:
The program fail at txb.sign, with this error:
Then I jumped to bitcoinjs-lib/src/transaction_builder:692 and I found this:
Which is using input.value; so I guessed prepareInput should inject this field, and I've found that it injects input.value if witnessScript and reedemScript are not undefined; but they are defined in my example, right? I can't figure out what's the problem here
The text was updated successfully, but these errors were encountered: