This adds the dupword linter to the list of linters and addresses a few false positives it complains about.
1646 lines
57 KiB
Go
1646 lines
57 KiB
Go
// Copyright (c) 2021-2023 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package stdscript
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/decred/dcrd/dcrec"
|
|
)
|
|
|
|
// hexToBytes converts the passed hex string into bytes and will panic if there
|
|
// is an error. This is only provided for the hard-coded constants so errors in
|
|
// the source code can be detected. It will only (and must only) be called with
|
|
// hard-coded values.
|
|
func hexToBytes(s string) []byte {
|
|
b, err := hex.DecodeString(s)
|
|
if err != nil {
|
|
panic("invalid hex in source file: " + s)
|
|
}
|
|
return b
|
|
}
|
|
|
|
// scriptV0Tests houses several version 0 test scripts used to ensure various
|
|
// script types and data extraction is working as expected. It's defined as a
|
|
// test global versus inside a specific test function scope since it spans
|
|
// multiple tests and benchmarks.
|
|
var scriptV0Tests = func() []scriptTest {
|
|
// Convenience function that combines fmt.Sprintf with mustParseShortForm
|
|
// to create more compact tests.
|
|
p := func(format string, a ...interface{}) []byte {
|
|
const scriptVersion = 0
|
|
return mustParseShortForm(scriptVersion, fmt.Sprintf(format, a...))
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Define some data shared in the tests for convenience.
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Uncompressed and compressed/hybrid even/odd secp256k1 public keys along
|
|
// with hash160s of the compressed even ones.
|
|
pkUE := "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817" +
|
|
"98483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"
|
|
pkUO := "04fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975" +
|
|
"56ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297"
|
|
pkCE := "02" + pkUE[2:66]
|
|
h160CE := "e280cb6e66b96679aec288b1fbdbd4db08077a1b"
|
|
pkCE2 := "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9"
|
|
h160CE2 := "01557763e0252dc0ff9e0996ad1d04b167bb993c"
|
|
pkCO := "03" + pkUO[2:66]
|
|
pkHE := "05" + pkUE[2:]
|
|
pkHO := "06" + pkUO[2:]
|
|
|
|
// Ed25519 public key and hash.
|
|
pkEd := "cecc1507dc1ddd7295951c290888f095adb9044d1b73d696e6df065d683bd4fc"
|
|
h160Ed := "456d8ee57a4b9121987b4ecab8c3bcb5797e8a53"
|
|
|
|
// Script hash for a 2-of-3 multisig composed of pkCE, pkCE2, and pkCO.
|
|
p2sh := "f86b5a7c6d32566aa4dccc04d1533530b4d64cf3"
|
|
|
|
return []scriptTest{{
|
|
// ---------------------------------------------------------------------
|
|
// Misc negative tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "malformed v0 script that does not parse",
|
|
script: p("DATA_5 0x01020304"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "empty v0 script",
|
|
script: nil,
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PK ECDSA secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-ecdsa-secp256k1 hybrid odd",
|
|
script: p("DATA_33 0x%s CHECKSIG", pkHO),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "v0 p2pk-ecdsa-secp256k1 hybrid even",
|
|
script: p("DATA_33 0x%s CHECKSIG", pkHE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-ecdsa-secp256k1 -- trailing opcode",
|
|
script: p("DATA_33 0x%s CHECKSIG TRUE", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-ecdsa-secp256k1 -- pubkey not pushed",
|
|
script: p("0x%s CHECKSIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-ecdsa-secp256k1 -- malformed pubkey prefix",
|
|
script: p("DATA_33 0x08%s CHECKSIG", pkCE[2:]),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PK ECDSA secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-ecdsa-secp256k1 uncompressed",
|
|
script: p("DATA_65 0x%s CHECKSIG", pkUE),
|
|
wantType: STPubKeyEcdsaSecp256k1,
|
|
wantData: hexToBytes(pkUE),
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 p2pk-ecdsa-secp256k1 compressed even",
|
|
script: p("DATA_33 0x%s CHECKSIG", pkCE),
|
|
wantType: STPubKeyEcdsaSecp256k1,
|
|
wantData: hexToBytes(pkCE),
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 p2pk-ecdsa-secp256k1 compressed odd",
|
|
script: p("DATA_33 0x%s CHECKSIG", pkCO),
|
|
wantType: STPubKeyEcdsaSecp256k1,
|
|
wantData: hexToBytes(pkCO),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PK Alt tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-alt unsupported signature type 0",
|
|
script: p("DATA_33 0x%s 0 CHECKSIGALT", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "v0 p2pk-alt unsupported signature type 3",
|
|
script: p("DATA_33 0x%s 3 CHECKSIGALT", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-alt -- signature type not small int",
|
|
script: p("DATA_33 0x%s DATA_1 2 CHECKSIGALT", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-alt -- NOP for signature type",
|
|
script: p("DATA_33 0x%s NOP CHECKSIGALT", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PK Ed25519 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 p2pk-ed25519 -- trailing opcode",
|
|
script: p("DATA_32 0x%s 1 CHECKSIGALT TRUE", pkEd),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-ed25519 -- pubkey not pushed",
|
|
script: p("0x%s 1 CHECKSIGALT", pkEd),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-ed25519 -- wrong signature type",
|
|
script: p("DATA_32 0x%s 2 CHECKSIGALT", pkEd),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PK Ed25519 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-ed25519",
|
|
script: p("DATA_32 0x%s 1 CHECKSIGALT", pkEd),
|
|
wantType: STPubKeyEd25519,
|
|
wantData: hexToBytes(pkEd),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PK Schnorr secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-schnorr-secp256k1 uncompressed",
|
|
script: p("DATA_65 0x%s 2 CHECKSIGALT", pkUE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "v0 p2pk-schnorr-secp256k1 hybrid odd",
|
|
script: p("DATA_65 0x%s 2 CHECKSIGALT", pkHO),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "v0 p2pk-schnorr-secp256k1 hybrid even",
|
|
script: p("DATA_65 0x%s 2 CHECKSIGALT", pkHE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-schnorr-secp256k1 -- trailing opcode",
|
|
script: p("DATA_33 0x%s 2 CHECKSIGALT TRUE", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-schnorr-secp256k1 -- pubkey not pushed",
|
|
script: p("0x%s 2 CHECKSIGALT", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pk-schnorr-secp256k1 -- malformed pubkey prefix",
|
|
script: p("DATA_33 0x08%s 2 CHECKSIGALT", pkCE[2:]),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PK Schnorr secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pk-schnorr-secp256k1 compressed even",
|
|
script: p("DATA_33 0x%s 2 CHECKSIGALT", pkCE),
|
|
wantType: STPubKeySchnorrSecp256k1,
|
|
wantData: hexToBytes(pkCE),
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 p2pk-schnorr-secp256k1 compressed odd",
|
|
script: p("DATA_33 0x%s 2 CHECKSIGALT", pkCO),
|
|
wantType: STPubKeySchnorrSecp256k1,
|
|
wantData: hexToBytes(pkCO),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PKH ECDSA secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG", h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PKH ECDSA secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pkh-ecdsa-secp256k1",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG", h160CE),
|
|
wantType: STPubKeyHashEcdsaSecp256k1,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PKH Alt tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pkh-alt unsupported signature type 0",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY 0 CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "v0 p2pkh-alt unsupported signature type 3",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY 3 CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pkh-alt -- signature type not a small int",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY DATA_1 2 CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2pkh-alt -- NOP for signature type",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY NOP CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PKH Ed25519 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 p2pkh-ed25519 -- wrong hash length",
|
|
script: p("DUP HASH160 DATA_21 0x00%s EQUALVERIFY 1 CHECKSIGALT",
|
|
h160Ed),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PKH Ed25519 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pkh-ed25519",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY 1 CHECKSIGALT",
|
|
h160Ed),
|
|
wantType: STPubKeyHashEd25519,
|
|
wantData: hexToBytes(h160Ed),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2PKH Schnorr secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 p2pkh-schnorr-secp256k1 -- wrong hash length",
|
|
script: p("DUP HASH160 DATA_21 0x00%s EQUALVERIFY 2 CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2PKH Schnorr secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2pkh-schnorr-secp256k1",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY 2 CHECKSIGALT",
|
|
h160CE),
|
|
wantType: STPubKeyHashSchnorrSecp256k1,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 p2pkh-schnorr-secp256k1 2",
|
|
script: p("DUP HASH160 DATA_20 0x%s EQUALVERIFY 2 CHECKSIGALT",
|
|
h160CE2),
|
|
wantType: STPubKeyHashSchnorrSecp256k1,
|
|
wantData: hexToBytes(h160CE2),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 p2sh -- wrong hash length",
|
|
script: p("HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 p2sh -- trailing opcode",
|
|
script: p("HASH160 DATA_20 0x%s EQUAL TRUE", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 p2sh",
|
|
script: p("HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative ECDSA multisig secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 multisig 1-of-2 -- mixed (un)compressed pubkeys",
|
|
script: p("1 DATA_65 0x%s DATA_33 0x%s 2 CHECKMULTISIG", pkUE, pkCO),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- no req sigs",
|
|
script: p("0 0 CHECKMULTISIG"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- invalid pubkey",
|
|
script: p("1 DATA_32 0x%s 1 CHECKMULTISIG", pkCE[2:]),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- hybrid pubkey",
|
|
script: p("1 DATA_65 0x%s 1 CHECKMULTISIG", pkHO),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- invalid number of signatures",
|
|
script: p("DUP DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- ends with CHECKSIG instead",
|
|
script: p("1 DATA_33 0x%s 1 CHECKSIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- num required sigs not small int",
|
|
script: p("DATA_1 1 DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- num public keys not small int",
|
|
script: p("1 DATA_33 0x%s DATA_1 1 CHECKMULTISIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- missing num public keys",
|
|
script: p("1 DATA_33 0x%s CHECKMULTISIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- num pubkeys does not match given keys",
|
|
script: p("2 DATA_33 0x%s DATA_33 0x%s 3 CHECKMULTISIG", pkCE, pkCO),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- fewer pubkeys than num required sigs",
|
|
script: p("1 0 CHECKMULTISIG"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- CHECKMULTISIGVERIFY",
|
|
script: p("1 DATA_33 0x%s 1 CHECKMULTISIGVERIFY", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- extra NOP prior to final opcode",
|
|
script: p("1 DATA_33 0x%s 1 NOP CHECKMULTISIG", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- trailing opcode",
|
|
script: p("1 DATA_33 0x%s 1 CHECKMULTISIG TRUE", pkCE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig -- no pubkeys specified",
|
|
script: p("1 CHECKMULTISIG"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive ECDSA multisig secp256k1 tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 multisig 1-of-1 compressed pubkey",
|
|
script: p("1 DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
wantType: STMultiSig,
|
|
wantData: MultiSigDetailsV0{
|
|
RequiredSigs: 1,
|
|
NumPubKeys: 1,
|
|
PubKeys: [][]byte{hexToBytes(pkCE)},
|
|
Valid: true,
|
|
},
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 multisig 1-of-2 compressed pubkeys",
|
|
script: p("1 DATA_33 0x%s DATA_33 0x%s 2 CHECKMULTISIG", pkCE, pkCE2),
|
|
wantType: STMultiSig,
|
|
wantData: MultiSigDetailsV0{
|
|
RequiredSigs: 1,
|
|
NumPubKeys: 2,
|
|
PubKeys: [][]byte{hexToBytes(pkCE), hexToBytes(pkCE2)},
|
|
Valid: true,
|
|
},
|
|
wantSigs: 1,
|
|
}, {
|
|
name: "v0 multisig 2-of-3 compressed pubkeys",
|
|
script: p("2 DATA_33 0x%s DATA_33 0x%s DATA_33 0x%s 3 CHECKMULTISIG",
|
|
pkCE, pkCE2, pkCO),
|
|
wantType: STMultiSig,
|
|
wantData: MultiSigDetailsV0{
|
|
RequiredSigs: 2,
|
|
NumPubKeys: 3,
|
|
PubKeys: [][]byte{
|
|
hexToBytes(pkCE), hexToBytes(pkCE2), hexToBytes(pkCO),
|
|
},
|
|
Valid: true,
|
|
},
|
|
wantSigs: 2,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative ECDSA multisig secp256k1 redeem script tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 multisig redeem script -- no req sigs",
|
|
script: p("DATA_3 0 0 CHECKMULTISIG"),
|
|
isSig: true,
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig 1-of-1 redeem script -- trailing opcode",
|
|
script: p("DATA_38 1 DATA_33 0x%s 1 CHECKMULTISIG TRUE", pkCE),
|
|
isSig: true,
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 multisig 1-of-1 redeem script -- parse error",
|
|
script: p("DATA_38 1 DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
isSig: true,
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive ECDSA multisig secp256k1 redeem script tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 multisig 1-of-1 compressed pubkey redeem script",
|
|
script: p("DATA_37 1 DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
isSig: true,
|
|
wantType: STMultiSig,
|
|
wantData: p("1 DATA_33 0x%s 1 CHECKMULTISIG", pkCE),
|
|
}, {
|
|
name: "v0 multisig 1-of-2 compressed pubkeys redeem script",
|
|
script: p("DATA_71 1 DATA_33 0x%s DATA_33 0x%s 2 CHECKMULTISIG", pkCE,
|
|
pkCE2),
|
|
isSig: true,
|
|
wantType: STMultiSig,
|
|
wantData: p("1 DATA_33 0x%s DATA_33 0x%s 2 CHECKMULTISIG", pkCE, pkCE2),
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative nulldata tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 nulldata -- NOP instead of data push",
|
|
script: p("RETURN NOP"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- non-canonical small int push (DATA_1 vs 12)",
|
|
script: p("RETURN DATA_1 0x0c"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- non-canonical small int push (PUSHDATA1 vs 12)",
|
|
script: p("RETURN PUSHDATA1 0x01 0x0c"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- non-canonical 60-byte push (PUSHDATA1 vs DATA_60)",
|
|
script: p("RETURN PUSHDATA1 0x3c 0x046708afdb0fe5548271967f1a67130b7105" +
|
|
"cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3046708afdb0fe5548271" +
|
|
"967f1a67130b7105cd6a"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- non-canonical 12-byte push (PUSHDATA2)",
|
|
script: p("RETURN PUSHDATA2 0x0c00 0x046708afdb0fe5548271967f"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- non-canonical 12-byte push (PUSHDATA4)",
|
|
script: p("RETURN PUSHDATA4 0x0c000000 0x046708afdb0fe5548271967f"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- exceeds max standard push",
|
|
script: p("RETURN PUSHDATA2 0x0101 0x01{257}"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 nulldata -- trailing opcode",
|
|
script: p("RETURN 4 TRUE"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive nulldata tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 nulldata no data push",
|
|
script: p("RETURN"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata single zero push",
|
|
script: p("RETURN 0"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata small int push",
|
|
script: p("RETURN 1"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata max small int push",
|
|
script: p("RETURN 16"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata small data push",
|
|
script: p("RETURN DATA_8 0x046708afdb0fe554"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata 60-byte push",
|
|
script: p("RETURN 0x3c 0x046708afdb0fe5548271967f1a67130b7105cd6a828e03" +
|
|
"909a67962e0ea1f61deb649f6bc3f4cef3046708afdb0fe5548271967f1a6713" +
|
|
"0b7105cd6a"),
|
|
wantType: STNullData,
|
|
}, {
|
|
name: "v0 nulldata max standard push",
|
|
script: p("RETURN PUSHDATA2 0x0001 0x01{256}"),
|
|
wantType: STNullData,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake sub p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("SSTX DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake submission p2pkh-ecdsa-secp256k1",
|
|
script: p("SSTX DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG", h160CE),
|
|
wantType: STStakeSubmissionPubKeyHash,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake submission p2sh -- wrong hash length",
|
|
script: p("SSTX HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake submission p2sh",
|
|
script: p("SSTX HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STStakeSubmissionScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission generation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake gen p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("SSGEN DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission generation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake gen p2pkh-ecdsa-secp256k1",
|
|
script: p("SSGEN DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STStakeGenPubKeyHash,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission generation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake gen p2sh -- wrong hash length",
|
|
script: p("SSGEN HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission generation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake gen p2sh",
|
|
script: p("SSGEN HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STStakeGenScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission revocation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake revoke p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("SSRTX DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission revocation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake revoke p2pkh-ecdsa-secp256k1",
|
|
script: p("SSRTX DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STStakeRevocationPubKeyHash,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission revocation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake revoke p2sh -- wrong hash length",
|
|
script: p("SSRTX HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission revocation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake revoke p2sh",
|
|
script: p("SSRTX HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STStakeRevocationScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission change P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake change p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("SSTXCHANGE DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission change P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake change p2pkh-ecdsa-secp256k1",
|
|
script: p("SSTXCHANGE DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STStakeChangePubKeyHash,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative stake submission change P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 stake change p2sh -- wrong hash length",
|
|
script: p("SSTXCHANGE HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive stake submission change P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 stake change p2sh",
|
|
script: p("SSTXCHANGE HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STStakeChangeScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative treasury add tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 treasury add -- trailing opcode",
|
|
script: p("TADD TRUE"),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
name: "almost v0 treasury add -- two TADD",
|
|
script: p("TADD TADD"), // nolint: dupword
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive treasury add tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 treasury add",
|
|
script: p("TADD"),
|
|
wantType: STTreasuryAdd,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative treasury generation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 trsy gen p2pkh-ecdsa-secp256k1 -- wrong hash length",
|
|
script: p("TGEN DUP HASH160 DATA_21 0x00%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive treasury generation P2PKH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 treasury generation p2pkh-ecdsa-secp256k1",
|
|
script: p("TGEN DUP HASH160 DATA_20 0x%s EQUALVERIFY CHECKSIG",
|
|
h160CE),
|
|
wantType: STTreasuryGenPubKeyHash,
|
|
wantData: hexToBytes(h160CE),
|
|
wantSigs: 1,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Negative treasury generation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "almost v0 treasury generation p2sh -- wrong hash length",
|
|
script: p("TGEN HASH160 DATA_21 0x00%s EQUAL", p2sh),
|
|
wantType: STNonStandard,
|
|
}, {
|
|
// ---------------------------------------------------------------------
|
|
// Positive treasury generation P2SH tests.
|
|
// ---------------------------------------------------------------------
|
|
|
|
name: "v0 treasury generation p2sh",
|
|
script: p("TGEN HASH160 DATA_20 0x%s EQUAL", p2sh),
|
|
wantType: STTreasuryGenScriptHash,
|
|
wantData: hexToBytes(p2sh),
|
|
wantSigs: 1,
|
|
}}
|
|
}()
|
|
|
|
// asByteSlice attempts to convert the data associated with the passed script
|
|
// test to a byte slice or causes a fatal test error.
|
|
func asByteSlice(t *testing.T, test scriptTest) []byte {
|
|
t.Helper()
|
|
|
|
want, ok := test.wantData.([]byte)
|
|
if !ok {
|
|
t.Fatalf("%q: unexpected want data type -- got %T", test.name,
|
|
test.wantData)
|
|
}
|
|
return want
|
|
}
|
|
|
|
// TestExtractPubKeysV0 ensures that extracting a public key from the various
|
|
// version 0 pay-to-pubkey-ecdsa-secp256k1 style scripts works as intended
|
|
// for all of the version 0 test scripts.
|
|
func TestExtractPubKeysV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want, wantCompressed, wantUncompressed []byte
|
|
if test.wantType == STPubKeyEcdsaSecp256k1 {
|
|
want = asByteSlice(t, test)
|
|
if len(want) == 33 {
|
|
wantCompressed = want
|
|
} else if len(want) == 65 {
|
|
wantUncompressed = want
|
|
}
|
|
}
|
|
|
|
testExtract := func(fn func(script []byte) []byte, want []byte) {
|
|
t.Helper()
|
|
|
|
got := fn(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey -- got %x, want %x (script %x)",
|
|
test.name, got, want, test.script)
|
|
}
|
|
}
|
|
testExtract(ExtractPubKeyV0, want)
|
|
testExtract(ExtractCompressedPubKeyV0, wantCompressed)
|
|
testExtract(ExtractUncompressedPubKeyV0, wantUncompressed)
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyAltDetailsV0 ensures that extracting a public key and
|
|
// signature type from the various version 0 pay-to-alt-pubkey style scripts
|
|
// works as intended for all of the version 0 test scripts.
|
|
func TestExtractPubKeyAltDetailsV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var wantBytes []byte
|
|
var wantSigType dcrec.SignatureType
|
|
switch test.wantType {
|
|
case STPubKeyEd25519:
|
|
wantBytes = asByteSlice(t, test)
|
|
wantSigType = dcrec.STEd25519
|
|
|
|
case STPubKeySchnorrSecp256k1:
|
|
wantBytes = asByteSlice(t, test)
|
|
wantSigType = dcrec.STSchnorrSecp256k1
|
|
}
|
|
|
|
gotBytes, gotSigType := ExtractPubKeyAltDetailsV0(test.script)
|
|
if !bytes.Equal(gotBytes, wantBytes) {
|
|
t.Errorf("%q: unexpected pubkey -- got %x, want %x", test.name,
|
|
gotBytes, wantBytes)
|
|
continue
|
|
}
|
|
if gotBytes != nil && gotSigType != wantSigType {
|
|
t.Errorf("%q: unexpected sig type -- got %d, want %d", test.name,
|
|
gotSigType, wantSigType)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyEd25519V0 ensures that extracting a public key from the
|
|
// various version 0 pay-to-pubkey-ed25519 scripts works as intended for all of
|
|
// the version 0 test scripts.
|
|
func TestExtractPubKeyEd25519V0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STPubKeyEd25519 {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractPubKeyEd25519V0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeySchnorrSecp256k1V0 ensures that extracting a public key from
|
|
// the various version 0 pay-to-pubkey-schnorr-secp256k1 scripts works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractPubKeySchnorrSecp256k1V0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STPubKeySchnorrSecp256k1 {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractPubKeySchnorrSecp256k1V0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyHashV0 ensures that extracting a public key hash from the
|
|
// various version 0 pay-to-pubkey-hash-ecdsa-secp256k1 scripts works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractPubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STPubKeyHashEcdsaSecp256k1 {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractPubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyHashAltDetailsV0 ensures that extracting a public key hash
|
|
// and signature type from the version 0 pay-to-alt-pubkey-hash style scripts
|
|
// works as intended for all of the version 0 test scripts.
|
|
func TestExtractPubKeyHashAltDetailsV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var wantBytes []byte
|
|
var wantSigType dcrec.SignatureType
|
|
switch test.wantType {
|
|
case STPubKeyHashEd25519:
|
|
wantBytes = asByteSlice(t, test)
|
|
wantSigType = dcrec.STEd25519
|
|
|
|
case STPubKeyHashSchnorrSecp256k1:
|
|
wantBytes = asByteSlice(t, test)
|
|
wantSigType = dcrec.STSchnorrSecp256k1
|
|
}
|
|
|
|
gotBytes, gotSigType := ExtractPubKeyHashAltDetailsV0(test.script)
|
|
if !bytes.Equal(gotBytes, wantBytes) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
gotBytes, wantBytes)
|
|
continue
|
|
}
|
|
if gotBytes != nil && gotSigType != wantSigType {
|
|
t.Errorf("%q: unexpected sig type -- got %d, want %d", test.name,
|
|
gotSigType, wantSigType)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyHashEd25519V0 ensures that extracting a public key hash from
|
|
// version 0 pay-to-pubkey-hash-ed25519 scripts works as intended for all of the
|
|
// version 0 test scripts.
|
|
func TestExtractPubKeyHashEd25519V0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STPubKeyHashEd25519 {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractPubKeyHashEd25519V0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractPubKeyHashSchnorrSecp256k1V0 ensures that extracting a public key
|
|
// hash from version 0 pay-to-pubkey-hash-schnor-secp256k1 scripts works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractPubKeyHashSchnorrSecp256k1V0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STPubKeyHashSchnorrSecp256k1 {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractPubKeyHashSchnorrSecp256k1V0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractScriptHashV0 ensures that extracting a script hash from the
|
|
// various version 0 pay-to-script-hash scripts works as intended for all of the
|
|
// version 0 test scripts.
|
|
func TestExtractScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractMultiSigScriptDetailsV0 ensures that extracting details about a
|
|
// version 0 ECDSA multisignature script works as intended for all of the
|
|
// version 0 test scripts.
|
|
func TestExtractMultiSigScriptDetailsV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want MultiSigDetailsV0
|
|
if test.wantType == STMultiSig && !test.isSig {
|
|
var ok bool
|
|
want, ok = test.wantData.(MultiSigDetailsV0)
|
|
if !ok {
|
|
t.Fatalf("%q: unexpected want data type -- got %T", test.name,
|
|
test.wantData)
|
|
}
|
|
}
|
|
|
|
// Attempt to extract the multisig data from the script and ensure
|
|
// the individual fields of the extracted data is accurate.
|
|
got := ExtractMultiSigScriptDetailsV0(test.script, true)
|
|
if got.Valid != want.Valid {
|
|
t.Errorf("%q: unexpected validity -- got %v, want %v", test.name,
|
|
got.Valid, want.Valid)
|
|
continue
|
|
}
|
|
if got.RequiredSigs != want.RequiredSigs {
|
|
t.Errorf("%q: unexpected required sigs -- got %d, want %d",
|
|
test.name, got.RequiredSigs, want.RequiredSigs)
|
|
continue
|
|
}
|
|
if got.NumPubKeys != want.NumPubKeys {
|
|
t.Errorf("%q: unexpected num public keys -- got %d, want %d",
|
|
test.name, got.NumPubKeys, want.NumPubKeys)
|
|
continue
|
|
}
|
|
if !reflect.DeepEqual(got.PubKeys, want.PubKeys) {
|
|
t.Errorf("%q: unexpected extracted pubkeys -- got %x, want %x",
|
|
test.name, got.PubKeys, want.PubKeys)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestMultiSigRedeemScriptFromScriptSigV0 ensures extracting a version 0 ECDSA
|
|
// multisignature redeem script returns the expected scripts for the version 0
|
|
// test scripts that are actually multisignature redeem scripts.
|
|
func TestMultiSigRedeemScriptFromScriptSigV0(t *testing.T) {
|
|
// Add an additional test to ensure empty redeem scripts are handled
|
|
// correctly.
|
|
tests := []scriptTest{{
|
|
name: "v0 empty script",
|
|
script: nil,
|
|
isSig: true,
|
|
wantData: []byte(nil),
|
|
}}
|
|
for _, test := range scriptV0Tests {
|
|
// Per the documentation, unlike most of the extraction funcs, the
|
|
// multisig redeem script extraction function is only valid for scripts
|
|
// that have already been determined to be of the correct form.
|
|
if test.wantType != STMultiSig || !test.isSig {
|
|
continue
|
|
}
|
|
|
|
tests = append(tests, test)
|
|
}
|
|
|
|
for _, test := range tests {
|
|
want := asByteSlice(t, test)
|
|
got := MultiSigRedeemScriptFromScriptSigV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected redeem script -- got %x, want %x",
|
|
test.name, got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestMultiSigScriptV0 ensures the version 0 ECDSA multisignature script
|
|
// creation function returns the expected scripts and errors.
|
|
func TestMultiSigScriptV0(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
|
|
p2pkCompressedMain := hexToBytes("02192d74d0cb94344c9569c2e77901573d8d790" +
|
|
"3c3ebec3a957724895dca52c6b4")
|
|
p2pkCompressed2Main := hexToBytes("03b0bd634234abbb1ba1e986e884185c61cf43" +
|
|
"e001f9137f23c2c409273eb16e65")
|
|
p2pkUncompressedMain := hexToBytes("0411db93e1dcdb8a016b49840f8c53bc1eb68" +
|
|
"a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f" +
|
|
"9d4c03f999b8643f656b412a3")
|
|
|
|
tests := []struct {
|
|
name string
|
|
threshold int
|
|
pubKeys [][]byte
|
|
expected string
|
|
err error
|
|
}{{
|
|
name: "normal 1-of-2",
|
|
threshold: 1,
|
|
pubKeys: [][]byte{p2pkCompressedMain, p2pkCompressed2Main},
|
|
expected: fmt.Sprintf("1 DATA_%d 0x%x DATA_%d 0x%x 2 CHECKMULTISIG",
|
|
len(p2pkCompressedMain), p2pkCompressedMain,
|
|
len(p2pkCompressed2Main), p2pkCompressed2Main),
|
|
}, {
|
|
name: "normal 2-of-2",
|
|
threshold: 2,
|
|
pubKeys: [][]byte{p2pkCompressedMain, p2pkCompressed2Main},
|
|
expected: fmt.Sprintf("2 DATA_%d 0x%x DATA_%d 0x%x 2 CHECKMULTISIG",
|
|
len(p2pkCompressedMain), p2pkCompressedMain,
|
|
len(p2pkCompressed2Main), p2pkCompressed2Main),
|
|
}, {
|
|
name: "threshold 3 > 2 pubkeys",
|
|
pubKeys: [][]byte{p2pkCompressedMain, p2pkCompressed2Main},
|
|
threshold: 3,
|
|
expected: "",
|
|
err: ErrTooManyRequiredSigs,
|
|
}, {
|
|
name: "threshold 2 > 1 pubkey",
|
|
pubKeys: [][]byte{p2pkCompressedMain},
|
|
threshold: 2,
|
|
expected: "",
|
|
err: ErrTooManyRequiredSigs,
|
|
}, {
|
|
name: "reject uncompressed pubkeys",
|
|
pubKeys: [][]byte{p2pkUncompressedMain},
|
|
threshold: 1,
|
|
expected: "",
|
|
err: ErrPubKeyType,
|
|
}, {
|
|
name: "reject negative threshold",
|
|
pubKeys: [][]byte{p2pkUncompressedMain},
|
|
threshold: -1,
|
|
expected: "",
|
|
err: ErrNegativeRequiredSigs,
|
|
}}
|
|
|
|
for _, test := range tests {
|
|
script, err := MultiSigScriptV0(test.threshold, test.pubKeys...)
|
|
if !errors.Is(err, test.err) {
|
|
t.Errorf("%q: unexpected error - got %v, want %v", test.name, err,
|
|
test.err)
|
|
continue
|
|
}
|
|
|
|
const scriptVer = 0
|
|
expected := mustParseShortForm(scriptVer, test.expected)
|
|
if !bytes.Equal(script, expected) {
|
|
t.Errorf("%q: unexpected result -- got: %x\nwant: %x", test.name,
|
|
script, expected)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeSubmissionPubKeyHashV0 ensures that extracting a public key
|
|
// hash from a version 0 stake submission pay-to-pubkey-hash script works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractStakeSubmissionPubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeSubmissionPubKeyHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeSubmissionPubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeSubmissionScriptHashV0 ensures that extracting a script hash
|
|
// from a version 0 stake submission pay-to-script-hash script works as intended
|
|
// for all of the version 0 test scripts.
|
|
func TestExtractStakeSubmissionScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeSubmissionScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeSubmissionScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeGenPubKeyHashV0 ensures that extracting a public key
|
|
// hash from a version 0 stake generation pay-to-pubkey-hash script works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractStakeGenPubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeGenPubKeyHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeGenPubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeGenScriptHashV0 ensures that extracting a script hash
|
|
// from a version 0 stake generation pay-to-script-hash script works as intended
|
|
// for all of the version 0 test scripts.
|
|
func TestExtractStakeGenScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeGenScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeGenScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeRevocationPubKeyHashV0 ensures that extracting a public key
|
|
// hash from a version 0 stake revocation pay-to-pubkey-hash script works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractStakeRevocationPubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeRevocationPubKeyHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeRevocationPubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeRevocationScriptHashV0 ensures that extracting a script hash
|
|
// from a version 0 stake revocation pay-to-script-hash script works as intended
|
|
// for all of the version 0 test scripts.
|
|
func TestExtractStakeRevocationScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeRevocationScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeRevocationScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeChangePubKeyHashV0 ensures that extracting a public key hash
|
|
// from a version 0 stake change pay-to-pubkey-hash script works as intended for
|
|
// all of the version 0 test scripts.
|
|
func TestExtractStakeChangePubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeChangePubKeyHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeChangePubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeChangeScriptHashV0 ensures that extracting a script hash from
|
|
// a version 0 stake change pay-to-script-hash script works as intended for all
|
|
// of the version 0 test scripts.
|
|
func TestExtractStakeChangeScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STStakeChangeScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeChangeScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractTreasuryGenPubKeyHashV0 ensures that extracting a public key hash
|
|
// from a version 0 treasury generation pay-to-pubkey-hash script works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractTreasuryGenPubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STTreasuryGenPubKeyHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractTreasuryGenPubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected pubkey hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractTreasuryGenScriptHashV0 ensures that extracting a script hash from
|
|
// a version 0 treasury generation pay-to-script-hash script works as intended
|
|
// for all of the version 0 test scripts.
|
|
func TestExtractTreasuryGenScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
if test.wantType == STTreasuryGenScriptHash {
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractTreasuryGenScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakePubKeyHashV0 ensures that extracting a public key hash from
|
|
// the supported standard version 0 stake-tagged pay-to-pubkey-hash scripts
|
|
// works as intended for all of the version 0 test scripts.
|
|
func TestExtractStakePubKeyHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
switch test.wantType {
|
|
case STStakeSubmissionPubKeyHash, STStakeGenPubKeyHash,
|
|
STStakeRevocationPubKeyHash, STStakeChangePubKeyHash,
|
|
STTreasuryGenPubKeyHash:
|
|
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakePubKeyHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractStakeScriptHashV0 ensures that extracting a script hash from the
|
|
// supported standard version 0 stake-tagged pay-to-script-hash scripts works as
|
|
// intended for all of the version 0 test scripts.
|
|
func TestExtractStakeScriptHashV0(t *testing.T) {
|
|
for _, test := range scriptV0Tests {
|
|
// Determine the expected data based on the expected script type and
|
|
// data specified in the test.
|
|
var want []byte
|
|
switch test.wantType {
|
|
case STStakeSubmissionScriptHash, STStakeGenScriptHash,
|
|
STStakeRevocationScriptHash, STStakeChangeScriptHash,
|
|
STTreasuryGenScriptHash:
|
|
|
|
want = asByteSlice(t, test)
|
|
}
|
|
|
|
got := ExtractStakeScriptHashV0(test.script)
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("%q: unexpected script hash -- got %x, want %x", test.name,
|
|
got, want)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestProvablyPruneableScriptV0 ensures generating a version 0
|
|
// provably-pruneable nulldata script works as intended.
|
|
func TestProvablyPruneableScriptV0(t *testing.T) {
|
|
// Convenience function that closes over the script version and invokes
|
|
// mustParseShortForm to create more compact tests.
|
|
const scriptVersion = 0
|
|
p := func(format string, a ...interface{}) []byte {
|
|
return mustParseShortForm(scriptVersion, fmt.Sprintf(format, a...))
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
data []byte
|
|
expected []byte
|
|
err error
|
|
typ ScriptType
|
|
}{{
|
|
name: "small int",
|
|
data: hexToBytes("01"),
|
|
expected: p("RETURN 1"),
|
|
err: nil,
|
|
typ: STNullData,
|
|
}, {
|
|
name: "max small int",
|
|
data: hexToBytes("10"),
|
|
expected: p("RETURN 16"),
|
|
err: nil,
|
|
typ: STNullData,
|
|
}, {
|
|
name: "data of size before OP_PUSHDATA1 is needed",
|
|
data: bytes.Repeat(hexToBytes("00"), 75),
|
|
expected: p("RETURN DATA_75 0x00{75}"),
|
|
err: nil,
|
|
typ: STNullData,
|
|
}, {
|
|
name: "one less than max allowed size",
|
|
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0-1),
|
|
expected: p("RETURN PUSHDATA1 0xff 0x00{255}"),
|
|
err: nil,
|
|
typ: STNullData,
|
|
}, {
|
|
name: "max allowed size",
|
|
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0),
|
|
expected: p("RETURN PUSHDATA2 0x0001 0x00{256}"),
|
|
err: nil,
|
|
typ: STNullData,
|
|
}, {
|
|
name: "too big",
|
|
data: bytes.Repeat(hexToBytes("00"), MaxDataCarrierSizeV0+1),
|
|
expected: nil,
|
|
err: ErrTooMuchNullData,
|
|
typ: STNonStandard,
|
|
}}
|
|
|
|
for _, test := range tests {
|
|
script, err := ProvablyPruneableScriptV0(test.data)
|
|
if !errors.Is(err, test.err) {
|
|
t.Errorf("%q: unexpected error - got %v, want %v", test.name, err,
|
|
test.err)
|
|
continue
|
|
}
|
|
|
|
// Ensure the expected script was generated.
|
|
if !bytes.Equal(script, test.expected) {
|
|
t.Errorf("%q: unexpected script -- got: %x, want: %x", test.name,
|
|
script, test.expected)
|
|
continue
|
|
}
|
|
|
|
// Ensure the script has the correct type.
|
|
scriptType := DetermineScriptType(scriptVersion, script)
|
|
if scriptType != test.typ {
|
|
t.Errorf("%q: unexpected script type -- got: %v, want: %v",
|
|
test.name, scriptType, test.typ)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// expectedAtomicSwapDataV0 is a convenience function that converts the passed
|
|
// parameters into an expected version 0 atomic swap data pushes structure.
|
|
func expectedAtomicSwapDataV0(recipientHash, refundHash, secretHash string, secretSize, lockTime int64) *AtomicSwapDataPushesV0 {
|
|
result := &AtomicSwapDataPushesV0{
|
|
SecretSize: secretSize,
|
|
LockTime: lockTime,
|
|
}
|
|
copy(result.RecipientHash160[:], hexToBytes(recipientHash))
|
|
copy(result.RefundHash160[:], hexToBytes(refundHash))
|
|
copy(result.SecretHash[:], hexToBytes(secretHash))
|
|
return result
|
|
}
|
|
|
|
// TestExtractAtomicSwapDataPushesV0 ensures version 0 atomic swap scripts are
|
|
// recognized properly and the correct information is extracted from them.
|
|
func TestExtractAtomicSwapDataPushesV0(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Define some values shared in the tests for convenience.
|
|
secret := "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
|
|
recipient := "0000000000000000000000000000000000000001"
|
|
refund := "0000000000000000000000000000000000000002"
|
|
|
|
tests := []struct {
|
|
name string // test description
|
|
script string // script to analyze
|
|
data *AtomicSwapDataPushesV0 // expected data pushes
|
|
}{{
|
|
name: "normal valid atomic swap",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund),
|
|
data: expectedAtomicSwapDataV0(recipient, refund, secret, 32, 300000),
|
|
}, {
|
|
name: "atomic swap with mismatched smallint secret size",
|
|
script: fmt.Sprintf("IF SIZE 16 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund),
|
|
data: expectedAtomicSwapDataV0(recipient, refund, secret, 16, 300000),
|
|
}, {
|
|
name: "atomic swap with smallint locktime",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 10 CHECKLOCKTIMEVERIFY "+
|
|
"DROP DUP HASH160 DATA_20 0x%s ENDIF EQUALVERIFY CHECKSIG", secret,
|
|
recipient, refund),
|
|
data: expectedAtomicSwapDataV0(recipient, refund, secret, 32,
|
|
10),
|
|
}, {
|
|
name: "almost valid, but too many bytes for sha256 size",
|
|
script: fmt.Sprintf("IF SIZE 2147483649 EQUALVERIFY SHA256 DATA_32 "+
|
|
"0x%s EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but NOP for secret size",
|
|
script: fmt.Sprintf("IF SIZE NOP EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but NOP for locktime",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE NOP CHECKLOCKTIMEVERIFY "+
|
|
"DROP DUP HASH160 DATA_20 0x%s ENDIF EQUALVERIFY CHECKSIG", secret,
|
|
recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but wrong sha256 secret size",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_31 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret[:len(secret)-2], recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but wrong recipient hash size",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_19 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient[:len(recipient)-2],
|
|
refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but wrong refund hash size",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_19 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund[:len(refund)-2]),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but missing final CHECKSIG",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY", secret, recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but additional opcode at end",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG NOP", secret, recipient, refund),
|
|
data: nil,
|
|
}, {
|
|
name: "almost valid, but parse error",
|
|
script: fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 DATA_32 0x%s "+
|
|
"EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+
|
|
"CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_24 0x%s ENDIF "+
|
|
"EQUALVERIFY CHECKSIG", secret, recipient, refund),
|
|
data: nil,
|
|
}}
|
|
|
|
const scriptVersion = 0
|
|
for _, test := range tests {
|
|
script := mustParseShortForm(scriptVersion, test.script)
|
|
|
|
// Attempt to extract the atomic swap data from the script and ensure
|
|
// there is either extracted data or not as expected.
|
|
data := ExtractAtomicSwapDataPushesV0(script)
|
|
switch {
|
|
case test.data == nil && data != nil:
|
|
t.Errorf("%q: unexpected extracted data", test.name)
|
|
continue
|
|
|
|
case test.data != nil && data == nil:
|
|
t.Errorf("%q: failed to extract expected data", test.name)
|
|
continue
|
|
|
|
case data == nil:
|
|
continue
|
|
}
|
|
|
|
// Ensure the individual fields of the extracted data is accurate. The
|
|
// two structs could be directly compared, but testing them individually
|
|
// allows nicer error reporting in the case of failure.
|
|
if data.RecipientHash160 != test.data.RecipientHash160 {
|
|
t.Errorf("%q: unexpected recipient hash -- got %x, want %x",
|
|
test.name, data.RecipientHash160, test.data.RecipientHash160)
|
|
continue
|
|
}
|
|
if data.RefundHash160 != test.data.RefundHash160 {
|
|
t.Errorf("%q: unexpected refund hash -- got %x, want %x", test.name,
|
|
data.RefundHash160, test.data.RefundHash160)
|
|
continue
|
|
}
|
|
if data.SecretHash != test.data.SecretHash {
|
|
t.Errorf("%q: unexpected secret hash -- got %x, want %x", test.name,
|
|
data.SecretHash, test.data.SecretHash)
|
|
continue
|
|
}
|
|
if data.SecretSize != test.data.SecretSize {
|
|
t.Errorf("%q: unexpected secret size -- got %d, want %d", test.name,
|
|
data.SecretSize, test.data.SecretSize)
|
|
continue
|
|
}
|
|
if data.LockTime != test.data.LockTime {
|
|
t.Errorf("%q: unexpected locktime -- got %d, want %d", test.name,
|
|
data.LockTime, test.data.LockTime)
|
|
continue
|
|
}
|
|
}
|
|
}
|