[DEV-56] Remove any occurance of OP_CODESEPARATOR

* [DEV-56] Remove any occurance of OP_CODESEPARATOR

* [DEV-56] Modified sighash tests to exclude OP_CODESEPARATOR

* [DEV-56] Fixed sighash.json to not include any codeseparators at all

* [DEV-56] Reformatted sighash.json

* [DEV-56] Rename any instance of subScript to script

* [DEV-56] Extracted check for opUnknown to separate function

* [DEV-58] Removed temporary code for test cleanup
This commit is contained in:
Svarog 2018-07-05 18:58:13 +03:00 committed by stasatdaglabs
parent 927b5ec4ec
commit 0acf0eb516
12 changed files with 546 additions and 711 deletions

View File

@ -439,7 +439,6 @@
["0", "SHA256", "P2SH,STRICTENC", "OK"],
["0", "HASH160", "P2SH,STRICTENC", "OK"],
["0", "HASH256", "P2SH,STRICTENC", "OK"],
["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],

File diff suppressed because it is too large Load Diff

View File

@ -64,17 +64,6 @@
[[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]],
"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"],
["Inverted versions of tx_valid CODESEPARATOR IF block tests"],
["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0151ffffffff010000000000000000016a00000000", "P2SH"],
["As above, with the IF block executed"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510100ffffffff010000000000000000016a00000000", "P2SH"],
["CHECKLOCKTIMEVERIFY tests"],
["By-height locks, with argument just beyond tx nLockTime"],

View File

@ -109,39 +109,10 @@
"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004a00483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"],
["OP_CODESEPARATOR tests"],
["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"],
[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"],
[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"],
["Hashed data starts at the CODESEPARATOR"],
[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]],
"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"],
["But only if execution has reached it"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"],
["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"],
["As above, with the IF block executed"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"],
["CHECKSIG is legal in scriptSigs"],
[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["Same semantics for OP_CODESEPARATOR"],
[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["CHECKLOCKTIMEVERIFY tests"],
["By-height locks, with argument == 0 and == tx nLockTime"],

View File

@ -88,7 +88,6 @@ type Engine struct {
scripts [][]parsedOpcode
scriptIdx int
scriptOff int
lastCodeSep int
dstack stack // data stack
astack stack // alt stack
tx wire.MsgTx
@ -347,7 +346,6 @@ func (vm *Engine) Step() (done bool, err error) {
if vm.scriptIdx < len(vm.scripts) && vm.scriptOff >= len(vm.scripts[vm.scriptIdx]) {
vm.scriptIdx++
}
vm.lastCodeSep = 0
if vm.scriptIdx >= len(vm.scripts) {
return true, nil
}
@ -390,9 +388,9 @@ func (vm *Engine) Execute() (err error) {
return vm.CheckErrorCondition(true)
}
// subScript returns the script since the last OP_CODESEPARATOR.
func (vm *Engine) subScript() []parsedOpcode {
return vm.scripts[vm.scriptIdx][vm.lastCodeSep:]
// currentScript returns the script currently being processed.
func (vm *Engine) currentScript() []parsedOpcode {
return vm.scripts[vm.scriptIdx]
}
// checkHashTypeEncoding returns whether or not the passed hashtype adheres to

View File

@ -207,7 +207,7 @@ const (
OpSHA256 = 0xa8 // 168
OpHash160 = 0xa9 // 169
OpHash256 = 0xaa // 170
OpCodeSeparator = 0xab // 171
OpUnknown171 = 0xab // 171
OpCheckSig = 0xac // 172
OpCheckSigVerify = 0xad // 173
OpCheckMultiSig = 0xae // 174
@ -493,7 +493,6 @@ var opcodeArray = [256]opcode{
OpSHA256: {OpSHA256, "OP_SHA256", 1, opcodeSha256},
OpHash160: {OpHash160, "OP_HASH160", 1, opcodeHash160},
OpHash256: {OpHash256, "OP_HASH256", 1, opcodeHash256},
OpCodeSeparator: {OpCodeSeparator, "OP_CODESEPARATOR", 1, opcodeCodeSeparator},
OpCheckSig: {OpCheckSig, "OP_CHECKSIG", 1, opcodeCheckSig},
OpCheckSigVerify: {OpCheckSigVerify, "OP_CHECKSIGVERIFY", 1, opcodeCheckSigVerify},
OpCheckMultiSig: {OpCheckMultiSig, "OP_CHECKMULTISIG", 1, opcodeCheckMultiSig},
@ -510,6 +509,7 @@ var opcodeArray = [256]opcode{
OpNop10: {OpNop10, "OP_NOP10", 1, opcodeNop},
// Undefined opcodes.
OpUnknown171: {OpUnknown171, "OP_UNKNOWN171", 1, opcodeInvalid},
OpUnknown186: {OpUnknown186, "OP_UNKNOWN186", 1, opcodeInvalid},
OpUnknown187: {OpUnknown187, "OP_UNKNOWN187", 1, opcodeInvalid},
OpUnknown188: {OpUnknown188, "OP_UNKNOWN188", 1, opcodeInvalid},
@ -1979,15 +1979,6 @@ func opcodeHash256(op *parsedOpcode, vm *Engine) error {
return nil
}
// opcodeCodeSeparator stores the current script offset as the most recently
// seen OP_CODESEPARATOR which is used during signature checking.
//
// This opcode does not change the contents of the data stack.
func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error {
vm.lastCodeSep = vm.scriptOff
return nil
}
// opcodeCheckSig treats the top 2 items on the stack as a public key and a
// signature and replaces them with a bool which indicates if the signature was
// successfully verified.
@ -1995,10 +1986,8 @@ func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error {
// The process of verifying a signature requires calculating a signature hash in
// the same way the transaction signer did. It involves hashing portions of the
// transaction based on the hash type byte (which is the final byte of the
// signature) and the portion of the script starting from the most recent
// OP_CODESEPARATOR (or the beginning of the script if there are none) to the
// end of the script (with any other OP_CODESEPARATORs removed). Once this
// "script hash" is calculated, the signature is checked using standard
// signature) and the script.
// Once this "script hash" is calculated, the signature is checked using standard
// cryptographic methods against the provided public key.
//
// Stack transformation: [... signature pubkey] -> [... bool]
@ -2045,11 +2034,10 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error {
return err
}
// Get script starting from the most recent OP_CODESEPARATOR.
subScript := vm.subScript()
script := vm.currentScript()
// Generate the signature hash based on the signature hash type.
hash, err := calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx)
hash, err := calcSignatureHash(script, hashType, &vm.tx, vm.txIdx)
if err != nil {
vm.dstack.PushBool(false)
return nil
@ -2192,8 +2180,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error {
signatures = append(signatures, sigInfo)
}
// Get script starting from the most recent OP_CODESEPARATOR.
script := vm.subScript()
script := vm.currentScript()
success := true
numPubKeys++

View File

@ -72,7 +72,7 @@ func TestOpcodeDisasm(t *testing.T) {
0xa1: "OP_LESSTHANOREQUAL", 0xa2: "OP_GREATERTHANOREQUAL",
0xa3: "OP_MIN", 0xa4: "OP_MAX", 0xa5: "OP_WITHIN",
0xa6: "OP_RIPEMD160", 0xa7: "OP_SHA1", 0xa8: "OP_SHA256",
0xa9: "OP_HASH160", 0xaa: "OP_HASH256", 0xab: "OP_CODESEPARATOR",
0xa9: "OP_HASH160", 0xaa: "OP_HASH256",
0xac: "OP_CHECKSIG", 0xad: "OP_CHECKSIGVERIFY",
0xae: "OP_CHECKMULTISIG", 0xaf: "OP_CHECKMULTISIGVERIFY",
0xfa: "OP_SMALLINTEGER", 0xfb: "OP_PUBKEYS",
@ -123,7 +123,7 @@ func TestOpcodeDisasm(t *testing.T) {
}
// OP_UNKNOWN#.
case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc:
case isOpUnknown(opcodeVal):
expectedStr = "OP_UNKNOWN" + strconv.Itoa(int(opcodeVal))
}
@ -189,7 +189,7 @@ func TestOpcodeDisasm(t *testing.T) {
}
// OP_UNKNOWN#.
case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc:
case isOpUnknown(opcodeVal):
expectedStr = "OP_UNKNOWN" + strconv.Itoa(int(opcodeVal))
}
@ -203,3 +203,7 @@ func TestOpcodeDisasm(t *testing.T) {
}
}
}
func isOpUnknown(opcodeVal int) bool {
return opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc || opcodeVal == 0xab
}

View File

@ -726,11 +726,11 @@ func TestCalcSignatureHash(t *testing.T) {
continue
}
subScript, _ := hex.DecodeString(test[1].(string))
parsedScript, err := parseScript(subScript)
script, _ := hex.DecodeString(test[1].(string))
parsedScript, err := parseScript(script)
if err != nil {
t.Errorf("TestCalcSignatureHash failed test #%d: "+
"Failed to parse sub-script: %v", i, err)
"Failed to parse script: %v", i, err)
continue
}

View File

@ -227,18 +227,6 @@ func DisasmString(buf []byte) (string, error) {
return disbuf.String(), err
}
// removeOpcode will remove any opcode matching ``opcode'' from the opcode
// stream in pkscript
func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode {
retScript := make([]parsedOpcode, 0, len(pkscript))
for _, pop := range pkscript {
if pop.opcode.value != opcode {
retScript = append(retScript, pop)
}
}
return retScript
}
// canonicalPush returns true if the object is either not a push instruction
// or the push instruction contained wherein is matches the canonical form
// or using the smallest instruction to do the job. False otherwise.
@ -318,9 +306,6 @@ func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.Msg
return nil, scriptError(ErrInvalidSigHashSingleIndex, "sigHashSingle index out of bounds")
}
// Remove all instances of OP_CODESEPARATOR from the script.
script = removeOpcode(script, OpCodeSeparator)
// Make a shallow copy of the transaction, zeroing out the script for
// all inputs that are not currently being processed.
txCopy := shallowCopyTx(tx)

View File

@ -3378,22 +3378,6 @@ func TestUnparsingInvalidOpcodes(t *testing.T) {
},
expectedErr: scriptError(ErrInternal, ""),
},
{
name: "OP_CODESAPERATOR",
pop: &parsedOpcode{
opcode: &opcodeArray[OpCodeSeparator],
data: nil,
},
expectedErr: nil,
},
{
name: "OP_CODESEPARATOR long",
pop: &parsedOpcode{
opcode: &opcodeArray[OpCodeSeparator],
data: make([]byte, 1),
},
expectedErr: scriptError(ErrInternal, ""),
},
{
name: "OP_CHECKSIG",
pop: &parsedOpcode{
@ -3844,88 +3828,6 @@ func TestGetPreciseSigOps(t *testing.T) {
}
}
// TestRemoveOpcodes ensures that removing opcodes from scripts behaves as
// expected.
func TestRemoveOpcodes(t *testing.T) {
t.Parallel()
tests := []struct {
name string
before string
remove byte
err error
after string
}{
{
// Nothing to remove.
name: "nothing to remove",
before: "NOP",
remove: OpCodeSeparator,
after: "NOP",
},
{
// Test basic opcode removal.
name: "codeseparator 1",
before: "NOP CODESEPARATOR TRUE",
remove: OpCodeSeparator,
after: "NOP TRUE",
},
{
// The opcode in question is actually part of the data
// in a previous opcode.
name: "codeseparator by coincidence",
before: "NOP DATA_1 CODESEPARATOR TRUE",
remove: OpCodeSeparator,
after: "NOP DATA_1 CODESEPARATOR TRUE",
},
{
name: "invalid opcode",
before: "CAT",
remove: OpCodeSeparator,
after: "CAT",
},
{
name: "invalid length (instruction)",
before: "PUSHDATA1",
remove: OpCodeSeparator,
err: scriptError(ErrMalformedPush, ""),
},
{
name: "invalid length (data)",
before: "PUSHDATA1 0xff 0xfe",
remove: OpCodeSeparator,
err: scriptError(ErrMalformedPush, ""),
},
}
// tstRemoveOpcode is a convenience function to parse the provided
// raw script, remove the passed opcode, then unparse the result back
// into a raw script.
tstRemoveOpcode := func(script []byte, opcode byte) ([]byte, error) {
pops, err := parseScript(script)
if err != nil {
return nil, err
}
pops = removeOpcode(pops, opcode)
return unparseScript(pops)
}
for _, test := range tests {
before := mustParseShortForm(test.before)
after := mustParseShortForm(test.after)
result, err := tstRemoveOpcode(before, test.remove)
if e := tstCheckScriptError(err, test.err); e != nil {
t.Errorf("%s: %v", test.name, e)
continue
}
if !bytes.Equal(after, result) {
t.Errorf("%s: value does not equal expected: exp: %q"+
" got: %q", test.name, after, result)
}
}
}
// TestIsPayToScriptHash ensures the IsPayToScriptHash function returns the
// expected results for all the scripts in scriptClassTests.
func TestIsPayToScriptHash(t *testing.T) {

View File

@ -16,10 +16,10 @@ import (
// RawTxInSignature returns the serialized ECDSA signature for the input idx of
// the given transaction, with hashType appended to it.
func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte,
func RawTxInSignature(tx *wire.MsgTx, idx int, script []byte,
hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) {
hash, err := CalcSignatureHash(subScript, hashType, tx, idx)
hash, err := CalcSignatureHash(script, hashType, tx, idx)
if err != nil {
return nil, err
}
@ -35,12 +35,12 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte,
// from a previous output to the owner of privKey. tx must include all
// transaction inputs and outputs, however txin scripts are allowed to be filled
// or empty. The returned script is calculated to be used as the idx'th txin
// sigscript for tx. subscript is the PkScript of the previous output being used
// sigscript for tx. script is the PkScript of the previous output being used
// as the idx'th input. privKey is serialized in either a compressed or
// uncompressed format based on compress. This format must match the same format
// used to generate the payment address, or the script validation will fail.
func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey)
func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *btcec.PrivateKey, compress bool) ([]byte, error) {
sig, err := RawTxInSignature(tx, idx, script, hashType, privKey)
if err != nil {
return nil, err
}
@ -56,8 +56,8 @@ func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHash
return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
}
func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) {
sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey)
func p2pkSignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) {
sig, err := RawTxInSignature(tx, idx, script, hashType, privKey)
if err != nil {
return nil, err
}
@ -69,40 +69,40 @@ func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, hashType Sig
// possible. It returns the generated script and a boolean if the script fulfils
// the contract (i.e. nrequired signatures are provided). Since it is arguably
// legal to not be able to sign any of the outputs, no error is returned.
func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType,
func signMultiSig(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType,
addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
// We start with a single OP_FALSE to work around the (now standard)
// but in the reference implementation that causes a spurious pop at
// the end of OP_CHECKMULTISIG.
builder := NewScriptBuilder().AddOp(OpFalse)
signed := 0
signedCount := 0
for _, addr := range addresses {
key, _, err := kdb.GetKey(addr)
if err != nil {
continue
}
sig, err := RawTxInSignature(tx, idx, subScript, hashType, key)
sig, err := RawTxInSignature(tx, idx, script, hashType, key)
if err != nil {
continue
}
builder.AddData(sig)
signed++
if signed == nRequired {
signedCount++
if signedCount == nRequired {
break
}
}
script, _ := builder.Script()
return script, signed == nRequired
signedScript, _ := builder.Script()
return signedScript, signedCount == nRequired
}
func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
subScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte,
script []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte,
ScriptClass, []btcutil.Address, int, error) {
class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript,
class, addresses, nrequired, err := ExtractPkScriptAddrs(script,
chainParams)
if err != nil {
return nil, NonStandardTy, nil, 0, err
@ -116,13 +116,13 @@ func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
return nil, class, nil, 0, err
}
script, err := p2pkSignatureScript(tx, idx, subScript, hashType,
signedScript, err := p2pkSignatureScript(tx, idx, script, hashType,
key)
if err != nil {
return nil, class, nil, 0, err
}
return script, class, addresses, nrequired, nil
return signedScript, class, addresses, nrequired, nil
case PubKeyHashTy:
// look up key for address
key, compressed, err := kdb.GetKey(addresses[0])
@ -130,13 +130,13 @@ func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
return nil, class, nil, 0, err
}
script, err := SignatureScript(tx, idx, subScript, hashType,
signedScript, err := SignatureScript(tx, idx, script, hashType,
key, compressed)
if err != nil {
return nil, class, nil, 0, err
}
return script, class, addresses, nrequired, nil
return signedScript, class, addresses, nrequired, nil
case ScriptHashTy:
script, err := sdb.GetScript(addresses[0])
if err != nil {
@ -145,9 +145,9 @@ func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int,
return script, class, addresses, nrequired, nil
case MultiSigTy:
script, _ := signMultiSig(tx, idx, subScript, hashType,
signedScript, _ := signMultiSig(tx, idx, script, hashType,
addresses, nrequired, kdb)
return script, class, addresses, nrequired, nil
return signedScript, class, addresses, nrequired, nil
case NullDataTy:
return nil, class, nil, 0,
errors.New("can't sign NULLDATA transactions")

View File

@ -758,9 +758,9 @@ func TestCalcMultiSigStats(t *testing.T) {
script: "0 DATA_72 0x30450220106a3e4ef0b51b764a2887226" +
"2ffef55846514dacbdcbbdd652c849d395b4384022100" +
"e03ae554c3cbb40600d31dd46fc33f25e47bf8525b1fe" +
"07282e3b6ecb5f3bb2801 CODESEPARATOR 1 DATA_33 " +
"0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" +
"0357b3a7886211ab414d55a 1 CHECKMULTISIG",
"07282e3b6ecb5f3bb2801 1 DATA_33 0x0232abdc893e7f06" +
"31364d7fd01cb33d24da45329a00357b3a7886211ab414d55a" +
" 1 CHECKMULTISIG",
err: nil,
},
}