mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-06 06:06:49 +00:00
[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:
parent
927b5ec4ec
commit
0acf0eb516
@ -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
@ -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"],
|
||||
|
@ -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"],
|
||||
|
@ -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
|
||||
|
@ -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++
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user