Svarog 37fbdcb453
[NOD-1526] Restore txscript tests (#1019)
* [NOD-1526] Fix compilation errors

* [NOD-1526] Make MsgTx.PayloadHash non-pointer

* [NOD-1526] Fixed many tests

* [NOD-1526] Fix reference_test.go

* [NOD-1526] Removed last instances of appmessage in consensus

* [NOD-1526] No need to check for subnetwork
2020-11-12 10:22:17 +02:00

1102 lines
27 KiB
Go

// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package txscript
import (
"fmt"
"testing"
"github.com/kaspanet/go-secp256k1"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/pkg/errors"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
)
type addressToKey struct {
key *secp256k1.PrivateKey
compressed bool
}
func mkGetKey(keys map[string]addressToKey) KeyDB {
if keys == nil {
return KeyClosure(func(addr util.Address) (*secp256k1.PrivateKey,
bool, error) {
return nil, false, errors.New("nope")
})
}
return KeyClosure(func(addr util.Address) (*secp256k1.PrivateKey,
bool, error) {
a2k, ok := keys[addr.EncodeAddress()]
if !ok {
return nil, false, errors.New("nope")
}
return a2k.key, a2k.compressed, nil
})
}
func mkGetScript(scripts map[string][]byte) ScriptDB {
if scripts == nil {
return ScriptClosure(func(addr util.Address) ([]byte, error) {
return nil, errors.New("nope")
})
}
return ScriptClosure(func(addr util.Address) ([]byte, error) {
script, ok := scripts[addr.EncodeAddress()]
if !ok {
return nil, errors.New("nope")
}
return script, nil
})
}
func checkScripts(msg string, tx *externalapi.DomainTransaction, idx int, sigScript, scriptPubKey []byte) error {
tx.Inputs[idx].SignatureScript = sigScript
var flags ScriptFlags
vm, err := NewEngine(scriptPubKey, tx, idx,
flags, nil)
if err != nil {
return errors.Errorf("failed to make script engine for %s: %v",
msg, err)
}
err = vm.Execute()
if err != nil {
return errors.Errorf("invalid script signature for %s: %v", msg,
err)
}
return nil
}
func signAndCheck(msg string, tx *externalapi.DomainTransaction, idx int, scriptPubKey []byte,
hashType SigHashType, kdb KeyDB, sdb ScriptDB,
previousScript []byte) error {
sigScript, err := SignTxOutput(&dagconfig.TestnetParams, tx, idx,
scriptPubKey, hashType, kdb, sdb, nil)
if err != nil {
return errors.Errorf("failed to sign output %s: %v", msg, err)
}
return checkScripts(msg, tx, idx, sigScript, scriptPubKey)
}
func TestSignTxOutput(t *testing.T) {
t.Parallel()
// make key
// make script based on key.
// sign with magic pixie dust.
hashTypes := []SigHashType{
SigHashAll,
SigHashNone,
SigHashSingle,
SigHashAll | SigHashAnyOneCanPay,
SigHashNone | SigHashAnyOneCanPay,
SigHashSingle | SigHashAnyOneCanPay,
}
inputs := []*externalapi.DomainTransactionInput{
{
PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: externalapi.DomainTransactionID{},
Index: 0,
},
Sequence: 4294967295,
},
{
PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: externalapi.DomainTransactionID{},
Index: 1,
},
Sequence: 4294967295,
},
{
PreviousOutpoint: externalapi.DomainOutpoint{
TransactionID: externalapi.DomainTransactionID{},
Index: 2,
},
Sequence: 4294967295,
},
}
outputs := []*externalapi.DomainTransactionOutput{
{
Value: 1,
},
{
Value: 2,
},
{
Value: 3,
},
}
tx := &externalapi.DomainTransaction{
Version: 1,
Inputs: inputs,
Outputs: outputs,
}
// Pay to Pubkey Hash (uncompressed)
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
uncompressedPubKey, err := pubKey.SerializeUncompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
if err := signAndCheck(msg, tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(nil), nil); err != nil {
t.Error(err)
break
}
}
}
// Pay to Pubkey Hash (uncompressed) (merging with correct)
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
uncompressedPubKey, err := pubKey.SerializeUncompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
sigScript, err := SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(nil), nil)
if err != nil {
t.Errorf("failed to sign output %s: %v", msg,
err)
break
}
// by the above loop, this should be valid, now sign
// again and merge.
sigScript, err = SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(nil), sigScript)
if err != nil {
t.Errorf("failed to sign output %s a "+
"second time: %v", msg, err)
break
}
err = checkScripts(msg, tx, i, sigScript, scriptPubKey)
if err != nil {
t.Errorf("twice signed script invalid for "+
"%s: %v", msg, err)
break
}
}
}
// Pay to Pubkey Hash (compressed)
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
compressedPubKey, err := pubKey.SerializeCompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
if err := signAndCheck(msg, tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(nil), nil); err != nil {
t.Error(err)
break
}
}
}
// Pay to Pubkey Hash (compressed) with duplicate merge
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
compressedPubKey, err := pubKey.SerializeCompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
sigScript, err := SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(nil), nil)
if err != nil {
t.Errorf("failed to sign output %s: %v", msg,
err)
break
}
// by the above loop, this should be valid, now sign
// again and merge.
sigScript, err = SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(nil), sigScript)
if err != nil {
t.Errorf("failed to sign output %s a "+
"second time: %v", msg, err)
break
}
err = checkScripts(msg, tx, i, sigScript, scriptPubKey)
if err != nil {
t.Errorf("twice signed script invalid for "+
"%s: %v", msg, err)
break
}
}
}
// As before, but with p2sh now.
// Pay to Pubkey Hash (uncompressed)
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
uncompressedPubKey, err := pubKey.SerializeUncompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
break
}
scriptAddr, err := util.NewAddressScriptHash(
scriptPubKey, util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v",
msg, err)
break
}
scriptScriptPubKey, err := PayToAddrScript(
scriptAddr)
if err != nil {
t.Errorf("failed to make script scriptPubKey for "+
"%s: %v", msg, err)
break
}
if err := signAndCheck(msg, tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil); err != nil {
t.Error(err)
break
}
}
}
// Pay to Pubkey Hash (uncompressed) with duplicate merge
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
uncompressedPubKey, err := pubKey.SerializeUncompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(uncompressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
break
}
scriptAddr, err := util.NewAddressScriptHash(
scriptPubKey, util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v",
msg, err)
break
}
scriptScriptPubKey, err := PayToAddrScript(
scriptAddr)
if err != nil {
t.Errorf("failed to make script scriptPubKey for "+
"%s: %v", msg, err)
break
}
_, err = SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil)
if err != nil {
t.Errorf("failed to sign output %s: %v", msg,
err)
break
}
// by the above loop, this should be valid, now sign
// again and merge.
sigScript, err := SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, false},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil)
if err != nil {
t.Errorf("failed to sign output %s a "+
"second time: %v", msg, err)
break
}
err = checkScripts(msg, tx, i, sigScript, scriptScriptPubKey)
if err != nil {
t.Errorf("twice signed script invalid for "+
"%s: %v", msg, err)
break
}
}
}
// Pay to Pubkey Hash (compressed)
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
compressedPubKey, err := pubKey.SerializeCompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
scriptAddr, err := util.NewAddressScriptHash(
scriptPubKey, util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v",
msg, err)
break
}
scriptScriptPubKey, err := PayToAddrScript(
scriptAddr)
if err != nil {
t.Errorf("failed to make script scriptPubKey for "+
"%s: %v", msg, err)
break
}
if err := signAndCheck(msg, tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil); err != nil {
t.Error(err)
break
}
}
}
// Pay to Pubkey Hash (compressed) with duplicate merge
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
key, err := secp256k1.GeneratePrivateKey()
if err != nil {
t.Errorf("failed to make privKey for %s: %s",
msg, err)
break
}
pubKey, err := key.SchnorrPublicKey()
if err != nil {
t.Errorf("failed to make a publickey for %s: %s",
key, err)
break
}
compressedPubKey, err := pubKey.SerializeCompressed()
if err != nil {
t.Errorf("failed to make a pubkey for %s: %s",
key, err)
break
}
address, err := util.NewAddressPubKeyHash(
util.Hash160(compressedPubKey), util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
break
}
scriptPubKey, err := PayToAddrScript(address)
if err != nil {
t.Errorf("failed to make scriptPubKey "+
"for %s: %v", msg, err)
}
scriptAddr, err := util.NewAddressScriptHash(
scriptPubKey, util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make p2sh addr for %s: %v",
msg, err)
break
}
scriptScriptPubKey, err := PayToAddrScript(
scriptAddr)
if err != nil {
t.Errorf("failed to make script scriptPubKey for "+
"%s: %v", msg, err)
break
}
_, err = SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil)
if err != nil {
t.Errorf("failed to sign output %s: %v", msg,
err)
break
}
// by the above loop, this should be valid, now sign
// again and merge.
sigScript, err := SignTxOutput(&dagconfig.TestnetParams,
tx, i, scriptScriptPubKey, hashType,
mkGetKey(map[string]addressToKey{
address.EncodeAddress(): {key, true},
}), mkGetScript(map[string][]byte{
scriptAddr.EncodeAddress(): scriptPubKey,
}), nil)
if err != nil {
t.Errorf("failed to sign output %s a "+
"second time: %v", msg, err)
break
}
err = checkScripts(msg, tx, i, sigScript, scriptScriptPubKey)
if err != nil {
t.Errorf("twice signed script invalid for "+
"%s: %v", msg, err)
break
}
}
}
}
type tstInput struct {
txout *externalapi.DomainTransactionOutput
sigscriptGenerates bool
inputValidates bool
indexOutOfRange bool
}
type tstSigScript struct {
name string
inputs []tstInput
hashType SigHashType
compress bool
scriptAtWrongIndex bool
}
var coinbaseOutpoint = &externalapi.DomainOutpoint{
Index: (1 << 32) - 1,
}
// Pregenerated private key, with associated public key and scriptPubKeys
// for the uncompressed and compressed hash160.
var (
privKeyD = secp256k1.SerializedPrivateKey{0x6b, 0x0f, 0xd8, 0xda, 0x54, 0x22, 0xd0, 0xb7,
0xb4, 0xfc, 0x4e, 0x55, 0xd4, 0x88, 0x42, 0xb3, 0xa1, 0x65,
0xac, 0x70, 0x7f, 0x3d, 0xa4, 0x39, 0x5e, 0xcb, 0x3b, 0xb0,
0xd6, 0x0e, 0x06, 0x92}
uncompressedScriptPubKey = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
0x53, 0x90, 0x0e, 0x0a, 0x86, 0xc9, 0xfa, 0x88, 0xac}
compressedScriptPubKey = []byte{0x76, 0xa9, 0x14, 0x27, 0x4d, 0x9f, 0x7f,
0x61, 0x7e, 0x7c, 0x7a, 0x1c, 0x1f, 0xb2, 0x75, 0x79, 0x10,
0x43, 0x65, 0x68, 0x27, 0x9d, 0x86, 0x88, 0xac}
shortScriptPubKey = []byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
0x53, 0x90, 0x0e, 0x0a, 0x88, 0xac}
)
// Pretend output amounts.
const coinbaseVal = 2500000000
const fee = 5000000
var sigScriptTests = []tstSigScript{
{
name: "one input uncompressed",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "two inputs uncompressed",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "one input compressed",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: compressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: true,
scriptAtWrongIndex: false,
},
{
name: "two inputs compressed",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: compressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: compressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: true,
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashNone",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashNone,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashSingle",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashSingle,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashAll | SigHashAnyoneCanPay",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll | SigHashAnyOneCanPay,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType SigHashAnyoneCanPay",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: false,
indexOutOfRange: false,
},
},
hashType: SigHashAnyOneCanPay,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "hashType non-exist",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: false,
indexOutOfRange: false,
},
},
hashType: 0x04,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "invalid compression",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: false,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: true,
scriptAtWrongIndex: false,
},
{
name: "short ScriptPubKey",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: shortScriptPubKey,
},
sigscriptGenerates: false,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: false,
scriptAtWrongIndex: false,
},
{
name: "valid script at wrong index",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: false,
scriptAtWrongIndex: true,
},
{
name: "index out of range",
inputs: []tstInput{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: uncompressedScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
indexOutOfRange: false,
},
},
hashType: SigHashAll,
compress: false,
scriptAtWrongIndex: true,
},
}
// Test the sigscript generation for valid and invalid inputs, all
// hashTypes, and with and without compression. This test creates
// sigscripts to spend fake coinbase inputs, as sigscripts cannot be
// created for the DomainTransactions in txTests, since they come from the blockDAG
// and we don't have the private keys.
func TestSignatureScript(t *testing.T) {
t.Parallel()
privKey, _ := secp256k1.DeserializePrivateKey(&privKeyD)
nexttest:
for i := range sigScriptTests {
outputs := []*externalapi.DomainTransactionOutput{
{Value: 500, ScriptPublicKey: []byte{OpReturn}},
}
inputs := []*externalapi.DomainTransactionInput{}
for range sigScriptTests[i].inputs {
inputs = append(inputs, &externalapi.DomainTransactionInput{
PreviousOutpoint: *coinbaseOutpoint,
})
}
tx := &externalapi.DomainTransaction{
Version: 1,
Inputs: inputs,
Outputs: outputs,
}
var script []byte
var err error
for j := range tx.Inputs {
var idx int
if sigScriptTests[i].inputs[j].indexOutOfRange {
t.Errorf("at test %v", sigScriptTests[i].name)
idx = len(sigScriptTests[i].inputs)
} else {
idx = j
}
script, err = SignatureScript(tx, idx,
sigScriptTests[i].inputs[j].txout.ScriptPublicKey,
sigScriptTests[i].hashType, privKey,
sigScriptTests[i].compress)
if (err == nil) != sigScriptTests[i].inputs[j].sigscriptGenerates {
if err == nil {
t.Errorf("passed test '%v' incorrectly",
sigScriptTests[i].name)
} else {
t.Errorf("failed test '%v': %v",
sigScriptTests[i].name, err)
}
continue nexttest
}
if !sigScriptTests[i].inputs[j].sigscriptGenerates {
// done with this test
continue nexttest
}
tx.Inputs[j].SignatureScript = script
}
// If testing using a correct sigscript but for an incorrect
// index, use last input script for first input. Requires > 0
// inputs for test.
if sigScriptTests[i].scriptAtWrongIndex {
tx.Inputs[0].SignatureScript = script
sigScriptTests[i].inputs[0].inputValidates = false
}
// Validate tx input scripts
var scriptFlags ScriptFlags
for j := range tx.Inputs {
vm, err := NewEngine(sigScriptTests[i].
inputs[j].txout.ScriptPublicKey, tx, j, scriptFlags, nil)
if err != nil {
t.Errorf("cannot create script vm for test %v: %v",
sigScriptTests[i].name, err)
continue nexttest
}
err = vm.Execute()
if (err == nil) != sigScriptTests[i].inputs[j].inputValidates {
if err == nil {
t.Errorf("passed test '%v' validation incorrectly: %v",
sigScriptTests[i].name, err)
} else {
t.Errorf("failed test '%v' validation: %v",
sigScriptTests[i].name, err)
}
continue nexttest
}
}
}
}