diff --git a/blockchain/chaingen/generator.go b/blockchain/chaingen/generator.go index 02c40df53c..bd9369fc25 100644 --- a/blockchain/chaingen/generator.go +++ b/blockchain/chaingen/generator.go @@ -19,6 +19,7 @@ import ( "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -620,7 +621,7 @@ func (g *Generator) CreateTreasuryTSpend(privKey []byte, payouts []AddressAmount }) // Calculate TSpend signature without SigHashType. - sigscript, err := txscript.TSpendSignatureScript(msgTx, privKey) + sigscript, err := sign.TSpendSignatureScript(msgTx, privKey) if err != nil { panic(err) } diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 77eada5544..d149e8806f 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -28,6 +28,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/lru" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/wire" ) @@ -345,7 +346,7 @@ func newFakeCreateTSpend(privKey []byte, payouts []dcrutil.Amount, fee dcrutil.A }) // Calculate TSpend signature without SigHashType. - sigscript, err := txscript.TSpendSignatureScript(msgTx, privKey) + sigscript, err := sign.TSpendSignatureScript(msgTx, privKey) if err != nil { panic(err) } diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 64ea868c2e..0790c9a285 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -20,6 +20,7 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -1561,9 +1562,8 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // associated p2sh output in bshso0. spend := chaingen.MakeSpendableOut(bshso0, uint32(i+2), 2) tx := g.CreateSpendTx(&spend, lowFee) - sig, err := txscript.RawTxInSignature(tx, 0, - redeemScript, txscript.SigHashAll, privKeyBytes, - dcrec.STEcdsaSecp256k1) + sig, err := sign.RawTxInSignature(tx, 0, redeemScript, + txscript.SigHashAll, privKeyBytes, dcrec.STEcdsaSecp256k1) if err != nil { panic(err) } @@ -1597,9 +1597,8 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // associated p2sh output in bshso0. spend := chaingen.MakeSpendableOut(bshso0, uint32(i+2), 2) tx := g.CreateSpendTx(&spend, lowFee) - sig, err := txscript.RawTxInSignature(tx, 0, - redeemScript, txscript.SigHashAll, privKeyBytes, - dcrec.STEcdsaSecp256k1) + sig, err := sign.RawTxInSignature(tx, 0, redeemScript, + txscript.SigHashAll, privKeyBytes, dcrec.STEcdsaSecp256k1) if err != nil { panic(err) } diff --git a/blockchain/treasury_test.go b/blockchain/treasury_test.go index 46b0305a87..b50293c74e 100644 --- a/blockchain/treasury_test.go +++ b/blockchain/treasury_test.go @@ -27,6 +27,7 @@ import ( "github.com/decred/dcrd/gcs/v3/blockcf2" "github.com/decred/dcrd/lru" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -2044,18 +2045,18 @@ func TestSpendableTreasuryTxs(t *testing.T) { }) // Generate the valid signature for the first input, which is a P2PKH. - sig, err := txscript.SignatureScript(tx, 0, tspend.TxOut[1].PkScript, - txscript.SigHashAll, spendPrivKey.Serialize(), - dcrec.STEcdsaSecp256k1, true) + sig, err := sign.SignatureScript(tx, 0, tspend.TxOut[1].PkScript, + txscript.SigHashAll, spendPrivKey.Serialize(), dcrec.STEcdsaSecp256k1, + true) if err != nil { t.Fatalf("unable to generate sig: %v", err) } tx.TxIn[0].SignatureScript = sig // Generate the valid signature for the third input, which is a P2PKH. - sig, err = txscript.SignatureScript(tx, 2, tadd1.TxOut[1].PkScript, - txscript.SigHashAll, addPrivKey.Serialize(), - dcrec.STEcdsaSecp256k1, true) + sig, err = sign.SignatureScript(tx, 2, tadd1.TxOut[1].PkScript, + txscript.SigHashAll, addPrivKey.Serialize(), dcrec.STEcdsaSecp256k1, + true) if err != nil { t.Fatalf("unable to generate sig: %v", err) } diff --git a/internal/mempool/mempool_test.go b/internal/mempool/mempool_test.go index 9d254e6bec..aa50f14569 100644 --- a/internal/mempool/mempool_test.go +++ b/internal/mempool/mempool_test.go @@ -26,6 +26,7 @@ import ( "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/internal/mining" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -464,9 +465,8 @@ func (p *poolHarness) CreateSignedTx(inputs []spendableOutput, numOutputs uint32 // Sign the new transaction. for i := range tx.TxIn { - sigScript, err := txscript.SignatureScript(tx, - i, p.payScript, txscript.SigHashAll, p.signKey, - dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, i, p.payScript, + txscript.SigHashAll, p.signKey, dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -501,9 +501,8 @@ func (p *poolHarness) CreateTxChain(firstOutput spendableOutput, numTxns uint32) }) // Sign the new transaction. - sigScript, err := txscript.SignatureScript(tx, 0, - p.payScript, txscript.SigHashAll, p.signKey, - dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, 0, p.payScript, + txscript.SigHashAll, p.signKey, dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -559,9 +558,9 @@ func (p *poolHarness) CreateTicketPurchase(sourceTx *dcrutil.Tx, cost int64) (*d tx.AddTxOut(newTxOut(change, changeScriptVer, changeScript)) // Sign the ticket purchase. - sigScript, err := txscript.SignatureScript(tx, 0, - sourceTx.MsgTx().TxOut[0].PkScript, txscript.SigHashAll, - p.signKey, dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, 0, + sourceTx.MsgTx().TxOut[0].PkScript, txscript.SigHashAll, p.signKey, + dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -655,9 +654,9 @@ func (p *poolHarness) CreateVote(ticket *dcrutil.Tx, mungers ...func(*wire.MsgTx // Sign the input. inputToSign := 1 redeemTicketScript := ticket.MsgTx().TxOut[0].PkScript - signedScript, err := txscript.SignTxOutput(p.chainParams, vote, inputToSign, - redeemTicketScript, txscript.SigHashAll, p, - p, vote.TxIn[inputToSign].SignatureScript, noTreasury) + signedScript, err := sign.SignTxOutput(p.chainParams, vote, inputToSign, + redeemTicketScript, txscript.SigHashAll, p, p, + vote.TxIn[inputToSign].SignatureScript, noTreasury) if err != nil { return nil, err } @@ -704,7 +703,7 @@ func (p *poolHarness) CreateRevocation(ticket *dcrutil.Tx) (*dcrutil.Tx, error) // Sign the input. inputToSign := 0 redeemTicketScript := ticket.MsgTx().TxOut[0].PkScript - signedScript, err := txscript.SignTxOutput(p.chainParams, revocation, + signedScript, err := sign.SignTxOutput(p.chainParams, revocation, inputToSign, redeemTicketScript, txscript.SigHashAll, p, p, revocation.TxIn[inputToSign].SignatureScript, noTreasury) if err != nil { @@ -2321,7 +2320,7 @@ func createTSpend(t *testing.T, expiry uint32, tspendAmount, tspendFee int64, pi }) // Calculate TSpend signature without SigHashType. - sigscript, err := txscript.TSpendSignatureScript(msgTx, piKey) + sigscript, err := sign.TSpendSignatureScript(msgTx, piKey) if err != nil { t.Fatalf("unable to sign tspend: %v", err) } @@ -2467,7 +2466,7 @@ func TestHandlesTSpends(t *testing.T) { // should fail. tx := tspends[1].MsgTx() tx.Expiry += 1 - tx.TxIn[0].SignatureScript, err = txscript.TSpendSignatureScript(tx, piKey) + tx.TxIn[0].SignatureScript, err = sign.TSpendSignatureScript(tx, piKey) if err != nil { t.Fatal(err) } @@ -2477,7 +2476,7 @@ func TestHandlesTSpends(t *testing.T) { // fail. tx = tspends[1].MsgTx() tx.Expiry = uint32(tvi) - tx.TxIn[0].SignatureScript, err = txscript.TSpendSignatureScript(tx, piKey) + tx.TxIn[0].SignatureScript, err = sign.TSpendSignatureScript(tx, piKey) if err != nil { t.Fatal(err) } @@ -2491,7 +2490,7 @@ func TestHandlesTSpends(t *testing.T) { // in the next block). tx = tspends[1].MsgTx() tx.Expiry = expiry + uint32(tvi*mul*2) - tx.TxIn[0].SignatureScript, err = txscript.TSpendSignatureScript(tx, piKey) + tx.TxIn[0].SignatureScript, err = sign.TSpendSignatureScript(tx, piKey) if err != nil { t.Fatal(err) } @@ -2511,7 +2510,7 @@ func TestHandlesTSpends(t *testing.T) { t.Fatal(err) } tx = tspends[3].MsgTx() - tx.TxIn[0].SignatureScript, err = txscript.TSpendSignatureScript(tx, nonPiKey) + tx.TxIn[0].SignatureScript, err = sign.TSpendSignatureScript(tx, nonPiKey) if err != nil { t.Fatal(err) } @@ -2579,9 +2578,8 @@ func createTAdd(t *testing.T, spend *spendableOutput, payScript, signKey []byte, } var err error - tx.TxIn[0].SignatureScript, err = txscript.SignatureScript(tx, - 0, payScript, txscript.SigHashAll, signKey, - dcrec.STEcdsaSecp256k1, true) + tx.TxIn[0].SignatureScript, err = sign.SignatureScript(tx, 0, payScript, + txscript.SigHashAll, signKey, dcrec.STEcdsaSecp256k1, true) if err != nil { t.Fatalf("Unable to sign tadd: %v", err) } diff --git a/internal/mining/mining_harness_test.go b/internal/mining/mining_harness_test.go index 9167bc4635..da8d29e38d 100644 --- a/internal/mining/mining_harness_test.go +++ b/internal/mining/mining_harness_test.go @@ -20,6 +20,7 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrutil/v4" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -1003,9 +1004,8 @@ func (m *miningHarness) CreateTxChain(firstOutput spendableOutput, numTxns uint3 m.payScript)) // Sign the new transaction. - sigScript, err := txscript.SignatureScript(tx, 0, - m.payScript, txscript.SigHashAll, m.signKey, - dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, 0, m.payScript, + txscript.SigHashAll, m.signKey, dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -1076,9 +1076,8 @@ func (m *miningHarness) CreateSignedTx(inputs []spendableOutput, numOutputs uint // Sign the new transaction. for i := range tx.TxIn { - sigScript, err := txscript.SignatureScript(tx, - i, m.payScript, txscript.SigHashAll, m.signKey, - dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, i, m.payScript, + txscript.SigHashAll, m.signKey, dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -1128,9 +1127,9 @@ func (m *miningHarness) CreateTicketPurchase(sourceTx *dcrutil.Tx, cost int64) ( tx.AddTxOut(newTxOut(change, changeScriptVer, changeScript)) // Sign the ticket purchase. - sigScript, err := txscript.SignatureScript(tx, 0, - sourceTx.MsgTx().TxOut[0].PkScript, txscript.SigHashAll, - m.signKey, dcrec.STEcdsaSecp256k1, true) + sigScript, err := sign.SignatureScript(tx, 0, + sourceTx.MsgTx().TxOut[0].PkScript, txscript.SigHashAll, m.signKey, + dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err } @@ -1215,7 +1214,7 @@ func (m *miningHarness) CreateVote(ticket *dcrutil.Tx, mungers ...func(*wire.Msg // Sign the input. inputToSign := 1 redeemTicketScript := ticket.MsgTx().TxOut[0].PkScript - signedScript, err := txscript.SignTxOutput(params, vote, inputToSign, + signedScript, err := sign.SignTxOutput(params, vote, inputToSign, redeemTicketScript, txscript.SigHashAll, m, m, vote.TxIn[inputToSign].SignatureScript, m.chain.isTreasuryAgendaActive) if err != nil { diff --git a/internal/rpcserver/treasury_test.go b/internal/rpcserver/treasury_test.go index 95ea68b6d1..57137c2f8a 100644 --- a/internal/rpcserver/treasury_test.go +++ b/internal/rpcserver/treasury_test.go @@ -24,6 +24,7 @@ import ( "github.com/decred/dcrd/rpcclient/v7" "github.com/decred/dcrd/rpctest" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -92,7 +93,7 @@ func createTSpend(privKey []byte, payouts []tspendPayout, fee dcrutil.Amount, ex }) // Calculate TSpend signature without SigHashType. - sigscript, err := txscript.TSpendSignatureScript(msgTx, privKey) + sigscript, err := sign.TSpendSignatureScript(msgTx, privKey) if err != nil { panic(err) } @@ -120,9 +121,8 @@ func createTAdd(t testing.TB, privKey []byte, prevOut *wire.OutPoint, pkScript [ } tx.Version = wire.TxVersionTreasury - sig, err := txscript.SignatureScript(tx, 0, pkScript, - txscript.SigHashAll, privKey, - dcrec.STEcdsaSecp256k1, true) + sig, err := sign.SignatureScript(tx, 0, pkScript, txscript.SigHashAll, + privKey, dcrec.STEcdsaSecp256k1, true) if err != nil { t.Fatalf("unable to generate sig: %v", err) } @@ -473,17 +473,15 @@ func TestTreasury(t *testing.T) { }) // Generate signatures for the P2PKH inputs. - sig, err := txscript.SignatureScript(tx, 0, tspendYes.TxOut[1].PkScript, - txscript.SigHashAll, privKey.Serialize(), - dcrec.STEcdsaSecp256k1, true) + sig, err := sign.SignatureScript(tx, 0, tspendYes.TxOut[1].PkScript, + txscript.SigHashAll, privKey.Serialize(), dcrec.STEcdsaSecp256k1, true) if err != nil { t.Fatalf("unable to generate sig: %v", err) } tx.TxIn[0].SignatureScript = sig - sig, err = txscript.SignatureScript(tx, 2, tadd1.TxOut[1].PkScript, - txscript.SigHashAll, privKey.Serialize(), - dcrec.STEcdsaSecp256k1, true) + sig, err = sign.SignatureScript(tx, 2, tadd1.TxOut[1].PkScript, + txscript.SigHashAll, privKey.Serialize(), dcrec.STEcdsaSecp256k1, true) if err != nil { t.Fatalf("unable to generate sig: %v", err) } diff --git a/rpctest/memwallet.go b/rpctest/memwallet.go index 594ead3418..27c8533312 100644 --- a/rpctest/memwallet.go +++ b/rpctest/memwallet.go @@ -22,6 +22,7 @@ import ( "github.com/decred/dcrd/hdkeychain/v3" "github.com/decred/dcrd/rpcclient/v7" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -529,7 +530,7 @@ func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, feeRate dcrutil.Amo return nil, err } - sigScript, err := txscript.SignatureScript(tx, i, utxo.pkScript, + sigScript, err := sign.SignatureScript(tx, i, utxo.pkScript, txscript.SigHashAll, privKey, dcrec.STEcdsaSecp256k1, true) if err != nil { return nil, err diff --git a/rpctest/votingwallet.go b/rpctest/votingwallet.go index 46d997f608..08af283ce3 100644 --- a/rpctest/votingwallet.go +++ b/rpctest/votingwallet.go @@ -21,6 +21,7 @@ import ( dcrdtypes "github.com/decred/dcrd/rpc/jsonrpc/types/v3" "github.com/decred/dcrd/rpcclient/v7" "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -456,7 +457,7 @@ func (w *VotingWallet) handleBlockConnectedNtfn(ntfn *blockConnectedNtfn) { prevScript = w.voteRetScript } - sig, err := txscript.SignatureScript(t, 0, prevScript, txscript.SigHashAll, + sig, err := sign.SignatureScript(t, 0, prevScript, txscript.SigHashAll, w.privateKey, dcrec.STEcdsaSecp256k1, true) if err != nil { w.logError(fmt.Errorf("failed to sign ticket tx: %v", err)) @@ -565,7 +566,7 @@ func (w *VotingWallet) handleWinningTicketsNtfn(ntfn *winningTicketsNtfn) { vote.Version = wire.TxVersionTreasury } - sig, err := txscript.SignatureScript(vote, 1, w.p2sstx, txscript.SigHashAll, + sig, err := sign.SignatureScript(vote, 1, w.p2sstx, txscript.SigHashAll, w.privateKey, dcrec.STEcdsaSecp256k1, true) if err != nil { w.logError(fmt.Errorf("failed to sign ticket tx: %v", err)) diff --git a/txscript/README.md b/txscript/README.md index cfe4524558..512a593652 100644 --- a/txscript/README.md +++ b/txscript/README.md @@ -32,9 +32,6 @@ the standard go tooling for working with modules to incorporate it. * [Extracting Details from Standard Scripts](https://pkg.go.dev/github.com/decred/dcrd/txscript/v4#example-ExtractPkScriptAddrs) Demonstrates extracting information from a standard public key script. -* [Manually Signing a Transaction Output](https://pkg.go.dev/github.com/decred/dcrd/txscript/v4#example-SignTxOutput) - Demonstrates manually creating and signing a redeem transaction. - * [Counting Opcodes in Scripts](https://pkg.go.dev/github.com/decred/dcrd/txscript/v4#example-ScriptTokenizer) Demonstrates creating a script tokenizer instance and using it to count the number of opcodes a script contains. diff --git a/txscript/bench_test.go b/txscript/bench_test.go index f1a230053a..fa7568ea74 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -13,6 +13,18 @@ import ( "github.com/decred/dcrd/wire" ) +const ( + // noTreasury signifies the treasury agenda should be treated as though + // it is inactive. It is used to increase the readability of the + // tests. + noTreasury = false + + // withTreasury signifies the treasury agenda should be treated as + // though it is active. It is used to increase the readability of + // the tests. + withTreasury = true +) + var ( // manyInputsBenchTx is a transaction that contains a lot of inputs which is // useful for benchmarking signature hash calculation. diff --git a/txscript/example_test.go b/txscript/example_test.go index 204d375ce9..7a941e542a 100644 --- a/txscript/example_test.go +++ b/txscript/example_test.go @@ -9,13 +9,9 @@ import ( "encoding/hex" "fmt" - "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/chaincfg/v3" - "github.com/decred/dcrd/dcrec" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/txscript/v4" "github.com/decred/dcrd/txscript/v4/stdaddr" - "github.com/decred/dcrd/wire" ) const ( @@ -55,106 +51,6 @@ func ExampleExtractPkScriptAddrs() { // Required Signatures: 1 } -// This example demonstrates manually creating and signing a redeem transaction. -func ExampleSignTxOutput() { - // Ordinarily the private key would come from whatever storage mechanism - // is being used, but for this example just hard code it. - privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" + - "d4f8720ee63e502ee2869afab7de234b80c") - if err != nil { - fmt.Println(err) - return - } - pubKey := secp256k1.PrivKeyFromBytes(privKeyBytes).PubKey() - pubKeyHash := stdaddr.Hash160(pubKey.SerializeCompressed()) - mainNetParams := chaincfg.MainNetParams() - addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pubKeyHash, - mainNetParams) - if err != nil { - fmt.Println(err) - return - } - - // For this example, create a fake transaction that represents what - // would ordinarily be the real transaction that is being spent. It - // contains a single output that pays to address in the amount of 1 DCR. - originTx := wire.NewMsgTx() - prevOut := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0), wire.TxTreeRegular) - txIn := wire.NewTxIn(prevOut, 100000000, []byte{txscript.OP_0, txscript.OP_0}) - originTx.AddTxIn(txIn) - pkScriptVer, pkScript := addr.PaymentScript() - txOut := wire.NewTxOut(100000000, pkScript) - txOut.Version = pkScriptVer - originTx.AddTxOut(txOut) - originTxHash := originTx.TxHash() - - // Create the transaction to redeem the fake transaction. - redeemTx := wire.NewMsgTx() - - // Add the input(s) the redeeming transaction will spend. There is no - // signature script at this point since it hasn't been created or signed - // yet, hence nil is provided for it. - prevOut = wire.NewOutPoint(&originTxHash, 0, wire.TxTreeRegular) - txIn = wire.NewTxIn(prevOut, 100000000, nil) - redeemTx.AddTxIn(txIn) - - // Ordinarily this would contain that actual destination of the funds, - // but for this example don't bother. - txOut = wire.NewTxOut(0, nil) - redeemTx.AddTxOut(txOut) - - // Sign the redeeming transaction. - sigType := dcrec.STEcdsaSecp256k1 - lookupKey := func(a stdaddr.Address) ([]byte, dcrec.SignatureType, bool, error) { - // Ordinarily this function would involve looking up the private - // key for the provided address, but since the only thing being - // signed in this example uses the address associated with the - // private key from above, simply return it with the compressed - // flag set since the address is using the associated compressed - // public key. - // - // NOTE: If you want to prove the code is actually signing the - // transaction properly, uncomment the following line which - // intentionally returns an invalid key to sign with, which in - // turn will result in a failure during the script execution - // when verifying the signature. - // - // privKey.D.SetInt64(12345) - // - return privKeyBytes, sigType, true, nil - } - // Notice that the script database parameter is nil here since it isn't - // used. It must be specified when pay-to-script-hash transactions are - // being signed. - sigScript, err := txscript.SignTxOutput(mainNetParams, redeemTx, 0, - originTx.TxOut[0].PkScript, txscript.SigHashAll, - txscript.KeyClosure(lookupKey), nil, nil, noTreasury) - if err != nil { - fmt.Println(err) - return - } - redeemTx.TxIn[0].SignatureScript = sigScript - - // Prove that the transaction has been validly signed by executing the - // script pair. - - flags := txscript.ScriptDiscourageUpgradableNops - vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, - flags, 0, nil) - if err != nil { - fmt.Println(err) - return - } - if err := vm.Execute(); err != nil { - fmt.Println(err) - return - } - fmt.Println("Transaction successfully signed") - - // Output: - // Transaction successfully signed -} - // This example demonstrates creating a script tokenizer instance and using it // to count the number of opcodes a script contains. func ExampleScriptTokenizer() { diff --git a/txscript/sign/example_test.go b/txscript/sign/example_test.go new file mode 100644 index 0000000000..f3f59815c7 --- /dev/null +++ b/txscript/sign/example_test.go @@ -0,0 +1,127 @@ +// Copyright (c) 2014-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package sign_test + +import ( + "encoding/hex" + "fmt" + + "github.com/decred/dcrd/chaincfg/chainhash" + "github.com/decred/dcrd/chaincfg/v3" + "github.com/decred/dcrd/dcrec" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/decred/dcrd/txscript/v4" + "github.com/decred/dcrd/txscript/v4/sign" + "github.com/decred/dcrd/txscript/v4/stdaddr" + "github.com/decred/dcrd/wire" +) + +const ( + // noTreasury signifies the treasury agenda should be treated as though + // it is inactive. It is used to increase the readability of the + // tests. + noTreasury = false +) + +// This example demonstrates manually creating and signing a redeem transaction. +func ExampleSignTxOutput() { + // Ordinarily the private key would come from whatever storage mechanism + // is being used, but for this example just hard code it. + privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" + + "d4f8720ee63e502ee2869afab7de234b80c") + if err != nil { + fmt.Println(err) + return + } + pubKey := secp256k1.PrivKeyFromBytes(privKeyBytes).PubKey() + pubKeyHash := stdaddr.Hash160(pubKey.SerializeCompressed()) + mainNetParams := chaincfg.MainNetParams() + addr, err := stdaddr.NewAddressPubKeyHashEcdsaSecp256k1V0(pubKeyHash, + mainNetParams) + if err != nil { + fmt.Println(err) + return + } + + // For this example, create a fake transaction that represents what + // would ordinarily be the real transaction that is being spent. It + // contains a single output that pays to address in the amount of 1 DCR. + originTx := wire.NewMsgTx() + prevOut := wire.NewOutPoint(&chainhash.Hash{}, ^uint32(0), wire.TxTreeRegular) + txIn := wire.NewTxIn(prevOut, 100000000, []byte{txscript.OP_0, txscript.OP_0}) + originTx.AddTxIn(txIn) + pkScriptVer, pkScript := addr.PaymentScript() + txOut := wire.NewTxOut(100000000, pkScript) + txOut.Version = pkScriptVer + originTx.AddTxOut(txOut) + originTxHash := originTx.TxHash() + + // Create the transaction to redeem the fake transaction. + redeemTx := wire.NewMsgTx() + + // Add the input(s) the redeeming transaction will spend. There is no + // signature script at this point since it hasn't been created or signed + // yet, hence nil is provided for it. + prevOut = wire.NewOutPoint(&originTxHash, 0, wire.TxTreeRegular) + txIn = wire.NewTxIn(prevOut, 100000000, nil) + redeemTx.AddTxIn(txIn) + + // Ordinarily this would contain that actual destination of the funds, + // but for this example don't bother. + txOut = wire.NewTxOut(0, nil) + redeemTx.AddTxOut(txOut) + + // Sign the redeeming transaction. + sigType := dcrec.STEcdsaSecp256k1 + lookupKey := func(a stdaddr.Address) ([]byte, dcrec.SignatureType, bool, error) { + // Ordinarily this function would involve looking up the private + // key for the provided address, but since the only thing being + // signed in this example uses the address associated with the + // private key from above, simply return it with the compressed + // flag set since the address is using the associated compressed + // public key. + // + // NOTE: If you want to prove the code is actually signing the + // transaction properly, uncomment the following line which + // intentionally returns an invalid key to sign with, which in + // turn will result in a failure during the script execution + // when verifying the signature. + // + // privKey.D.SetInt64(12345) + // + return privKeyBytes, sigType, true, nil + } + // Notice that the script database parameter is nil here since it isn't + // used. It must be specified when pay-to-script-hash transactions are + // being signed. + sigScript, err := sign.SignTxOutput(mainNetParams, redeemTx, 0, + originTx.TxOut[0].PkScript, txscript.SigHashAll, + sign.KeyClosure(lookupKey), nil, nil, noTreasury) + if err != nil { + fmt.Println(err) + return + } + redeemTx.TxIn[0].SignatureScript = sigScript + + // Prove that the transaction has been validly signed by executing the + // script pair. + + flags := txscript.ScriptDiscourageUpgradableNops + vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, + flags, 0, nil) + if err != nil { + fmt.Println(err) + return + } + if err := vm.Execute(); err != nil { + fmt.Println(err) + return + } + fmt.Println("Transaction successfully signed") + + // Output: + // Transaction successfully signed +} diff --git a/txscript/sign.go b/txscript/sign/sign.go similarity index 80% rename from txscript/sign.go rename to txscript/sign/sign.go index b9bf0120de..1490f49406 100644 --- a/txscript/sign.go +++ b/txscript/sign/sign.go @@ -3,7 +3,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package txscript +package sign import ( "errors" @@ -14,6 +14,7 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr" + "github.com/decred/dcrd/txscript/v4" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -25,9 +26,10 @@ import ( // does not accept a script version, the results are undefined for other script // versions. func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, - hashType SigHashType, key []byte, sigType dcrec.SignatureType) ([]byte, error) { + hashType txscript.SigHashType, key []byte, + sigType dcrec.SignatureType) ([]byte, error) { - hash, err := CalcSignatureHash(subScript, hashType, tx, idx, nil) + hash, err := txscript.CalcSignatureHash(subScript, hashType, tx, idx, nil) if err != nil { return nil, err } @@ -70,8 +72,9 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, // as the idx'th input. privKey is serialized in the respective format for the // ECDSA type. 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 []byte, sigType dcrec.SignatureType, compress bool) ([]byte, error) { +func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, + hashType txscript.SigHashType, privKey []byte, + sigType dcrec.SignatureType, compress bool) ([]byte, error) { sig, err := RawTxInSignature(tx, idx, subscript, hashType, privKey, sigType) if err != nil { @@ -97,19 +100,20 @@ func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHash return nil, fmt.Errorf("unsupported signature type '%v'", sigType) } - return NewScriptBuilder().AddData(sig).AddData(pkData).Script() + return txscript.NewScriptBuilder().AddData(sig).AddData(pkData).Script() } // p2pkSignatureScript constructs a pay-to-pubkey signature script. func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, - hashType SigHashType, privKey []byte, sigType dcrec.SignatureType) ([]byte, error) { + hashType txscript.SigHashType, privKey []byte, + sigType dcrec.SignatureType) ([]byte, error) { sig, err := RawTxInSignature(tx, idx, subScript, hashType, privKey, sigType) if err != nil { return nil, err } - return NewScriptBuilder().AddData(sig).Script() + return txscript.NewScriptBuilder().AddData(sig).Script() } // signMultiSig signs as many of the outputs in the provided multisig script as @@ -117,11 +121,12 @@ func p2pkSignatureScript(tx *wire.MsgTx, idx int, subScript []byte, // fulfills 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, - addresses []stdaddr.Address, nRequired int, kdb KeyDB) ([]byte, bool) { +func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, + hashType txscript.SigHashType, addresses []stdaddr.Address, + nRequired int, kdb KeyDB) ([]byte, bool) { // No need to add dummy in Decred. - builder := NewScriptBuilder() + builder := txscript.NewScriptBuilder() signed := 0 for _, addr := range addresses { key, sigType, _, err := kdb.GetKey(addr) @@ -148,13 +153,14 @@ func signMultiSig(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashTyp // handleStakeOutSign is a convenience function for reducing code clutter in // sign. It handles the signing of stake outputs. func handleStakeOutSign(tx *wire.MsgTx, idx int, subScript []byte, - hashType SigHashType, kdb KeyDB, sdb ScriptDB, - addresses []stdaddr.Address, class ScriptClass, subClass ScriptClass, - nrequired int) ([]byte, ScriptClass, []stdaddr.Address, int, error) { + hashType txscript.SigHashType, kdb KeyDB, sdb ScriptDB, + addresses []stdaddr.Address, class txscript.ScriptClass, + subClass txscript.ScriptClass, + nrequired int) ([]byte, txscript.ScriptClass, []stdaddr.Address, int, error) { // look up key for address switch subClass { - case PubKeyHashTy: + case txscript.PubKeyHashTy: key, sigType, compressed, err := kdb.GetKey(addresses[0]) if err != nil { return nil, class, nil, 0, err @@ -165,7 +171,7 @@ func handleStakeOutSign(tx *wire.MsgTx, idx int, subScript []byte, return nil, class, nil, 0, err } return txscript, class, addresses, nrequired, nil - case ScriptHashTy: + case txscript.ScriptHashTy: script, err := sdb.GetScript(addresses[0]) if err != nil { return nil, class, nil, 0, err @@ -182,23 +188,25 @@ func handleStakeOutSign(tx *wire.MsgTx, idx int, subScript []byte, // its input index, a database of keys, a database of scripts, and information // about the type of signature and returns a signature, script class, the // addresses involved, and the number of signatures required. -func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, isTreasuryEnabled bool) ([]byte, ScriptClass, []stdaddr.Address, int, error) { +func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, + subScript []byte, hashType txscript.SigHashType, kdb KeyDB, sdb ScriptDB, + isTreasuryEnabled bool) ([]byte, txscript.ScriptClass, []stdaddr.Address, int, error) { const scriptVersion = 0 - class, addresses, nrequired, err := ExtractPkScriptAddrs(scriptVersion, - subScript, chainParams, isTreasuryEnabled) + class, addresses, nrequired, err := txscript.ExtractPkScriptAddrs( + scriptVersion, subScript, chainParams, isTreasuryEnabled) if err != nil { - return nil, NonStandardTy, nil, 0, err + return nil, txscript.NonStandardTy, nil, 0, err } subClass := class - isStakeType := class == StakeSubmissionTy || - class == StakeSubChangeTy || - class == StakeGenTy || - class == StakeRevocationTy || - (isTreasuryEnabled && class == TreasuryGenTy) + isStakeType := class == txscript.StakeSubmissionTy || + class == txscript.StakeSubChangeTy || + class == txscript.StakeGenTy || + class == txscript.StakeRevocationTy || + (isTreasuryEnabled && class == txscript.TreasuryGenTy) if isStakeType { - subClass, err = GetStakeOutSubclass(subScript, isTreasuryEnabled) + subClass, err = txscript.GetStakeOutSubclass(subScript, isTreasuryEnabled) if err != nil { return nil, 0, nil, 0, fmt.Errorf("unknown stake output subclass encountered") @@ -206,7 +214,7 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript } switch class { - case PubKeyTy: + case txscript.PubKeyTy: // look up key for address key, sigType, _, err := kdb.GetKey(addresses[0]) if err != nil { @@ -221,7 +229,7 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript return script, class, addresses, nrequired, nil - case PubkeyAltTy: + case txscript.PubkeyAltTy: // look up key for address key, sigType, _, err := kdb.GetKey(addresses[0]) if err != nil { @@ -236,7 +244,7 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript return script, class, addresses, nrequired, nil - case PubKeyHashTy: + case txscript.PubKeyHashTy: // look up key for address key, sigType, compressed, err := kdb.GetKey(addresses[0]) if err != nil { @@ -251,7 +259,7 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript return script, class, addresses, nrequired, nil - case PubkeyHashAltTy: + case txscript.PubkeyHashAltTy: // look up key for address key, sigType, compressed, err := kdb.GetKey(addresses[0]) if err != nil { @@ -266,7 +274,7 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript return script, class, addresses, nrequired, nil - case ScriptHashTy: + case txscript.ScriptHashTy: script, err := sdb.GetScript(addresses[0]) if err != nil { return nil, class, nil, 0, err @@ -274,32 +282,32 @@ func sign(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, subScript return script, class, addresses, nrequired, nil - case MultiSigTy: + case txscript.MultiSigTy: script, _ := signMultiSig(tx, idx, subScript, hashType, addresses, nrequired, kdb) return script, class, addresses, nrequired, nil - case StakeSubmissionTy: + case txscript.StakeSubmissionTy: return handleStakeOutSign(tx, idx, subScript, hashType, kdb, sdb, addresses, class, subClass, nrequired) - case StakeGenTy: + case txscript.StakeGenTy: return handleStakeOutSign(tx, idx, subScript, hashType, kdb, sdb, addresses, class, subClass, nrequired) - case StakeRevocationTy: + case txscript.StakeRevocationTy: return handleStakeOutSign(tx, idx, subScript, hashType, kdb, sdb, addresses, class, subClass, nrequired) - case StakeSubChangeTy: + case txscript.StakeSubChangeTy: return handleStakeOutSign(tx, idx, subScript, hashType, kdb, sdb, addresses, class, subClass, nrequired) - case TreasuryGenTy: + case txscript.TreasuryGenTy: return handleStakeOutSign(tx, idx, subScript, hashType, kdb, sdb, addresses, class, subClass, nrequired) - case NullDataTy: + case txscript.NullDataTy: return nil, class, nil, 0, errors.New("can't sign NULLDATA transactions") @@ -335,7 +343,7 @@ func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []stdaddr.Address, var possibleSigs [][]byte extractSigs := func(script []byte) error { const scriptVersion = 0 - tokenizer := MakeScriptTokenizer(scriptVersion, script) + tokenizer := txscript.MakeScriptTokenizer(scriptVersion, script) for tokenizer.Next() { if data := tokenizer.Data(); len(data) != 0 { possibleSigs = append(possibleSigs, data) @@ -370,7 +378,7 @@ sigLoop: continue } tSig := sig[:len(sig)-1] - hashType := SigHashType(sig[len(sig)-1]) + hashType := txscript.SigHashType(sig[len(sig)-1]) pSig, err := ecdsa.ParseDERSignature(tSig) if err != nil { @@ -382,7 +390,7 @@ sigLoop: // however, assume no sigs etc are in the script since that // would make the transaction nonstandard and thus not // MultiSigTy, so we just need to hash the full thing. - hash, err := calcSignatureHash(pkScript, hashType, tx, idx, nil) + hash, err := txscript.CalcSignatureHash(pkScript, hashType, tx, idx, nil) if err != nil { // Decred -- is this the right handling for SIGHASH_SINGLE error ? // TODO make sure this doesn't break anything. @@ -412,7 +420,7 @@ sigLoop: } } - builder := NewScriptBuilder() + builder := txscript.NewScriptBuilder() doneSigs := 0 // This assumes that addresses are in the same order as in the script. for _, addr := range addresses { @@ -429,13 +437,41 @@ sigLoop: // padding for missing ones. for i := doneSigs; i < nRequired; i++ { - builder.AddOp(OP_0) + builder.AddOp(txscript.OP_0) } script, _ := builder.Script() return script } +// checkScriptParses returns an error if the provided script fails to parse. +func checkScriptParses(scriptVersion uint16, script []byte) error { + tokenizer := txscript.MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + // Nothing to do. + } + return tokenizer.Err() +} + +// finalOpcodeData returns the data associated with the final opcode in the +// script. It will return nil if the script fails to parse. +func finalOpcodeData(scriptVersion uint16, script []byte) []byte { + // Avoid unnecessary work. + if len(script) == 0 { + return nil + } + + var data []byte + tokenizer := txscript.MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + data = tokenizer.Data() + } + if tokenizer.Err() != nil { + return nil + } + return data +} + // mergeScripts merges sigScript and prevScript assuming they are both // partial solutions for pkScript spending output idx of tx. class, addresses // and nrequired are the result of extracting the addresses from pkscript. @@ -446,7 +482,9 @@ sigLoop: // NOTE: This function is only valid for version 0 scripts. Since the function // does not accept a script version, the results are undefined for other script // versions. -func mergeScripts(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pkScript []byte, class ScriptClass, addresses []stdaddr.Address, nRequired int, sigScript, prevScript []byte, isTreasuryEnabled bool) []byte { +func mergeScripts(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, + pkScript []byte, class txscript.ScriptClass, addresses []stdaddr.Address, + nRequired int, sigScript, prevScript []byte, isTreasuryEnabled bool) []byte { // TODO(oga) the scripthash and multisig paths here are overly // inefficient in that they will recompute already known data. @@ -454,7 +492,7 @@ func mergeScripts(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk // extra calculations. const scriptVersion = 0 switch class { - case ScriptHashTy: + case txscript.ScriptHashTy: // Nothing to merge if either the new or previous signature // scripts are empty or fail to parse. if len(sigScript) == 0 || @@ -477,8 +515,8 @@ func mergeScripts(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk // We already know this information somewhere up the stack, // therefore the error is ignored. - class, addresses, nrequired, _ := ExtractPkScriptAddrs(scriptVersion, - script, chainParams, isTreasuryEnabled) + class, addresses, nrequired, _ := txscript.ExtractPkScriptAddrs( + scriptVersion, script, chainParams, isTreasuryEnabled) // Merge mergedScript := mergeScripts(chainParams, tx, idx, script, @@ -486,13 +524,13 @@ func mergeScripts(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk isTreasuryEnabled) // Reappend the script and return the result. - builder := NewScriptBuilder() + builder := txscript.NewScriptBuilder() builder.AddOps(mergedScript) builder.AddData(script) finalScript, _ := builder.Script() return finalScript - case MultiSigTy: + case txscript.MultiSigTy: return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, sigScript, prevScript) @@ -549,7 +587,9 @@ func (sc ScriptClosure) GetScript(address stdaddr.Address) ([]byte, error) { // NOTE: This function is only valid for version 0 scripts. Since the function // does not accept a script version, the results are undefined for other script // versions. -func SignTxOutput(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, previousScript []byte, isTreasuryEnabled bool) ([]byte, error) { +func SignTxOutput(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, + pkScript []byte, hashType txscript.SigHashType, kdb KeyDB, sdb ScriptDB, + previousScript []byte, isTreasuryEnabled bool) ([]byte, error) { sigScript, class, addresses, nrequired, err := sign(chainParams, tx, idx, pkScript, hashType, kdb, sdb, isTreasuryEnabled) @@ -557,19 +597,19 @@ func SignTxOutput(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk return nil, err } - isStakeType := class == StakeSubmissionTy || - class == StakeSubChangeTy || - class == StakeGenTy || - class == StakeRevocationTy || - (isTreasuryEnabled && class == TreasuryGenTy) + isStakeType := class == txscript.StakeSubmissionTy || + class == txscript.StakeSubChangeTy || + class == txscript.StakeGenTy || + class == txscript.StakeRevocationTy || + (isTreasuryEnabled && class == txscript.TreasuryGenTy) if isStakeType { - class, err = GetStakeOutSubclass(pkScript, isTreasuryEnabled) + class, err = txscript.GetStakeOutSubclass(pkScript, isTreasuryEnabled) if err != nil { return nil, fmt.Errorf("unknown stake output subclass encountered") } } - if class == ScriptHashTy { + if class == txscript.ScriptHashTy { // TODO keep the sub addressed and pass down to merge. realSigScript, _, _, _, err := sign(chainParams, tx, idx, sigScript, hashType, kdb, sdb, isTreasuryEnabled) @@ -578,7 +618,7 @@ func SignTxOutput(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk } // Append the p2sh script as the last push in the script. - builder := NewScriptBuilder() + builder := txscript.NewScriptBuilder() builder.AddOps(realSigScript) builder.AddData(sigScript) @@ -598,7 +638,8 @@ func SignTxOutput(chainParams stdaddr.AddressParams, tx *wire.MsgTx, idx int, pk // spent from the treasury. The private key must correspond to one of the // valid public keys for a Pi instance recognized by consensus. func TSpendSignatureScript(msgTx *wire.MsgTx, privKey []byte) ([]byte, error) { - hash, err := CalcSignatureHash(nil, SigHashAll, msgTx, 0, nil) + hash, err := txscript.CalcSignatureHash(nil, txscript.SigHashAll, msgTx, 0, + nil) if err != nil { return nil, err } @@ -611,6 +652,6 @@ func TSpendSignatureScript(msgTx *wire.MsgTx, privKey []byte) ([]byte, error) { sigBytes := sig.Serialize() pkBytes := priv.PubKey().SerializeCompressed() - return NewScriptBuilder().AddData(sigBytes).AddData(pkBytes). - AddOp(OP_TSPEND).Script() + return txscript.NewScriptBuilder().AddData(sigBytes).AddData(pkBytes). + AddOp(txscript.OP_TSPEND).Script() } diff --git a/txscript/sign_test.go b/txscript/sign/sign_test.go similarity index 97% rename from txscript/sign_test.go rename to txscript/sign/sign_test.go index 031fa2c83e..2ed59f8565 100644 --- a/txscript/sign_test.go +++ b/txscript/sign/sign_test.go @@ -3,7 +3,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package txscript +package sign import ( "crypto/rand" @@ -17,6 +17,7 @@ import ( "github.com/decred/dcrd/dcrec" "github.com/decred/dcrd/dcrec/edwards/v2" "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/decred/dcrd/txscript/v4" "github.com/decred/dcrd/txscript/v4/stdaddr" "github.com/decred/dcrd/wire" ) @@ -98,8 +99,8 @@ func mkGetScript(scripts map[string][]byte) ScriptDB { func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byte) error { tx.TxIn[idx].SignatureScript = sigScript - var scriptFlags ScriptFlags - vm, err := NewEngine(pkScript, tx, idx, scriptFlags, 0, nil) + var scriptFlags txscript.ScriptFlags + vm, err := txscript.NewEngine(pkScript, tx, idx, scriptFlags, 0, nil) if err != nil { return fmt.Errorf("failed to make script engine for %s: %v", msg, err) @@ -114,7 +115,9 @@ func checkScripts(msg string, tx *wire.MsgTx, idx int, sigScript, pkScript []byt return nil } -func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, isTreasuryEnabled bool) error { +func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, + hashType txscript.SigHashType, kdb KeyDB, sdb ScriptDB, + isTreasuryEnabled bool) error { sigScript, err := SignTxOutput(testingParams, tx, idx, pkScript, hashType, kdb, sdb, nil, isTreasuryEnabled) @@ -125,7 +128,10 @@ func signAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, hashType return checkScripts(msg, tx, idx, sigScript, pkScript) } -func signBadAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, isTreasuryEnabled bool) error { +func signBadAndCheck(msg string, tx *wire.MsgTx, idx int, pkScript []byte, + hashType txscript.SigHashType, kdb KeyDB, sdb ScriptDB, + isTreasuryEnabled bool) error { + // Setup a PRNG. randScriptHash := chainhash.HashB(pkScript) tRand := mrand.New(mrand.NewSource(int64(randScriptHash[0]))) @@ -154,13 +160,13 @@ func TestSignTxOutput(t *testing.T) { // make key // make script based on key. // sign with magic pixie dust. - hashTypes := []SigHashType{ - SigHashAll, - SigHashNone, - SigHashSingle, - SigHashAll | SigHashAnyOneCanPay, - SigHashNone | SigHashAnyOneCanPay, - SigHashSingle | SigHashAnyOneCanPay, + hashTypes := []txscript.SigHashType{ + txscript.SigHashAll, + txscript.SigHashNone, + txscript.SigHashSingle, + txscript.SigHashAll | txscript.SigHashAnyOneCanPay, + txscript.SigHashNone | txscript.SigHashAnyOneCanPay, + txscript.SigHashSingle | txscript.SigHashAnyOneCanPay, } signatureSuites := []dcrec.SignatureType{ dcrec.STEcdsaSecp256k1, @@ -2073,8 +2079,8 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := MultiSigScript(2, pk1.SerializeCompressed(), - pk2.SerializeCompressed()) + pkScript, err := txscript.MultiSigScript(2, + pk1.SerializeCompressed(), pk2.SerializeCompressed()) if err != nil { t.Errorf("failed to make pkscript for %s: %v", msg, err) } @@ -2171,8 +2177,8 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := MultiSigScript(2, pk1.SerializeCompressed(), - pk2.SerializeCompressed()) + pkScript, err := txscript.MultiSigScript(2, + pk1.SerializeCompressed(), pk2.SerializeCompressed()) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) @@ -2310,8 +2316,8 @@ func TestSignTxOutput(t *testing.T) { break } - pkScript, err := MultiSigScript(2, pk1.SerializeCompressed(), - pk2.SerializeCompressed()) + pkScript, err := txscript.MultiSigScript(2, + pk1.SerializeCompressed(), pk2.SerializeCompressed()) if err != nil { t.Errorf("failed to make pkscript for %s: %v", msg, err) } @@ -2432,7 +2438,7 @@ type tstInput struct { type tstSigScript struct { name string inputs []tstInput - hashType SigHashType + hashType txscript.SigHashType compress bool scriptAtWrongIndex bool } @@ -2477,7 +2483,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2497,7 +2503,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2511,7 +2517,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2531,7 +2537,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2545,7 +2551,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashNone, + hashType: txscript.SigHashNone, compress: false, scriptAtWrongIndex: false, }, @@ -2559,7 +2565,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashSingle, + hashType: txscript.SigHashSingle, compress: false, scriptAtWrongIndex: false, }, @@ -2573,7 +2579,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAnyOneCanPay | SigHashAll, + hashType: txscript.SigHashAnyOneCanPay | txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2601,7 +2607,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: true, scriptAtWrongIndex: false, }, @@ -2614,7 +2620,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: false, }, @@ -2634,7 +2640,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, @@ -2654,7 +2660,7 @@ var sigScriptTests = []tstSigScript{ indexOutOfRange: false, }, }, - hashType: SigHashAll, + hashType: txscript.SigHashAll, compress: false, scriptAtWrongIndex: true, }, @@ -2672,7 +2678,7 @@ nexttest: for i := range sigScriptTests { tx := wire.NewMsgTx() - output := wire.NewTxOut(500, []byte{OP_RETURN}) + output := wire.NewTxOut(500, []byte{txscript.OP_RETURN}) tx.AddTxOut(output) for range sigScriptTests[i].inputs { @@ -2722,9 +2728,9 @@ nexttest: } // Validate tx input scripts - var scriptFlags ScriptFlags + var scriptFlags txscript.ScriptFlags for j := range tx.TxIn { - vm, err := NewEngine(sigScriptTests[i].inputs[j].txout. + vm, err := txscript.NewEngine(sigScriptTests[i].inputs[j].txout. PkScript, tx, j, scriptFlags, 0, nil) if err != nil {