kaspad/domain/consensus/utils/consensushashing/calculate_signature_hash_test.go
Svarog 369a3bac09
Limit block mass instead of merge set limit + Introduce SigOpCount to TransactionInput (#1790)
* Update constants

* Add to transaction SigOpCount

* Update mass calculation, and move it from InContext to InIsolation

* Update block validation accordingly

* Add SigOpCount validation during TransactionInContext

* Remove checking of mass vs maxMassAcceptedByBlock from consensusStateManager

* Update mining manager with latest changes

* Add SigOpCount to MsgTx.Copy()

* Fix initTestTransactionAcceptanceDataForClone

* Fix all tests in transaction_equal_clone_test.go

* Fix TestBlockMass

* Fix tests in transactionvalidator package

* Add SigOpCount to sighash

* Fix TestPruningDepth

* Fix problems in libkaspawalelt

* Fix integration tests

* Fix CalculateSignatureHash tests

* Remove remaining places talking about block size

* Add sanity check to checkBlockMass to make sure all transactions have their mass filled

* always add own sigOpCount to sigHash

* Update protowire/rpc.md

* Start working on removing any remaining reference to block/tx size

* Update rpc transaction verbose data to include mass rather then size

* Convert verboseData and block size check to mass

* Remove remaining usages of tx size in mempool

* Move transactionEstimatedSerializedSize to transactionvalidator

* Add PopulateMass to fakeRelayInvsContext

* Move PopulateMass to beggining of ValidateAndInsertTransaction + fix in it

* Assign mass a new number for backward-compatibility
2021-07-14 14:21:57 +03:00

517 lines
25 KiB
Go

package consensushashing_test
import (
"encoding/hex"
"fmt"
"testing"
"github.com/kaspanet/go-secp256k1"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
// shortened versions of SigHash types to fit in single line of test case
const (
all = consensushashing.SigHashAll
none = consensushashing.SigHashNone
single = consensushashing.SigHashSingle
allAnyoneCanPay = consensushashing.SigHashAll | consensushashing.SigHashAnyOneCanPay
noneAnyoneCanPay = consensushashing.SigHashNone | consensushashing.SigHashAnyOneCanPay
singleAnyoneCanPay = consensushashing.SigHashSingle | consensushashing.SigHashAnyOneCanPay
)
func modifyOutput(outputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.Outputs[outputIndex].Value = 100
return clone
}
}
func modifyInput(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.Inputs[inputIndex].PreviousOutpoint.Index = 2
return clone
}
}
func modifyAmountSpent(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
utxoEntry := clone.Inputs[inputIndex].UTXOEntry
clone.Inputs[inputIndex].UTXOEntry = utxo.NewUTXOEntry(666, utxoEntry.ScriptPublicKey(), false, 100)
return clone
}
}
func modifyScriptPublicKey(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
utxoEntry := clone.Inputs[inputIndex].UTXOEntry
scriptPublicKey := utxoEntry.ScriptPublicKey()
scriptPublicKey.Script = append(scriptPublicKey.Script, 1, 2, 3)
clone.Inputs[inputIndex].UTXOEntry = utxo.NewUTXOEntry(utxoEntry.Amount(), scriptPublicKey, false, 100)
return clone
}
}
func modifySequence(inputIndex int) func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
return func(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.Inputs[inputIndex].Sequence = 12345
return clone
}
}
func modifyPayload(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.Payload = []byte{6, 6, 6, 4, 2, 0, 1, 3, 3, 7}
return clone
}
func modifyGas(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.Gas = 1234
return clone
}
func modifySubnetworkID(tx *externalapi.DomainTransaction) *externalapi.DomainTransaction {
clone := tx.Clone()
clone.SubnetworkID = externalapi.DomainSubnetworkID{6, 6, 6, 4, 2, 0, 1, 3, 3, 7}
return clone
}
func TestCalculateSignatureHashSchnorr(t *testing.T) {
nativeTx, subnetworkTx, err := generateTxs()
if err != nil {
t.Fatalf("Error from generateTxs: %+v", err)
}
// Note: Expected values were generated by the same code that they test,
// As long as those were not verified using 3rd-party code they only check for regression, not correctness
tests := []struct {
name string
tx *externalapi.DomainTransaction
hashType consensushashing.SigHashType
inputIndex int
modificationFunction func(*externalapi.DomainTransaction) *externalapi.DomainTransaction
expectedSignatureHash string
}{
// native transactions
// sigHashAll
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "56071ab5533ce9635d2a65d911b15d50b5e5f3e3103797d53173188a11696962"},
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "3ee15a1f5d3827b9c3bca740ebbe422a8d07fbde287944f855da26c06782d38b"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "1794d1d074a587678174223788bea272d092a6155f031686b85caf11595ff6d8"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "8c580bd47a220e4ab6f343dde74a23f9e4b3971b2b519b0ed0ad34d682aa85d3"},
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(0), // should change the hash
expectedSignatureHash: "29cca3e62ad1e7069ccb67a4589ad6858b741ecb2abd9d470d0ec72903467edc"},
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(1), // shouldn't change the hash
expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "94dbee595dcbac18cc2c158e67315dacfdfc4af9ab08713d41d3546076daeb5a"},
// sigHashNone
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "52b3888a3680c79712b53c4010b7cdebd158e09b7574d95b846ba9989946c38b"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "af54114c72a3192d05cfa80fb4be60bad77fc484b0072798e5e264da692dc4db"},
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "cf1fd4691c22a75011909e7444c0d9582610374f7eea3debc450bbe939862cac"},
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyAmountSpent(0), // should change the hash
expectedSignatureHash: "f76731710af7731896e415d85da6518fa316cddebd8abcb4b2ee931679296a0a"},
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "382e8196e1fe34ccc4c3004ad6e6d4c41b81b8a5dd6de24fe51065a1970ef00b"},
// sigHashSingle
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "ca882be7c6c3ae37badda62c9277be0808160d65a6a89feb514e41ed7a9658f0"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "7dec3b5b7b5ccd3f82f93c6c08cd05acecb970d4a4d127fcd87a11d7e0dd96e3"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "80a8db8aa43c5cd5d067c69e32f998ac5c0820d89fcfda9beaf55c8df41c4c86"},
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "3c6daba7d6849df524517f505d6abb93e20930726f89b50416eb2b6d59f202c6"},
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "35d28b074df6959cbef5aca8923e53312db3a88aab0039bd0a6b2fe92dff5aa7"},
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
expectedSignatureHash: "26a05df8e562f5c43cacab9a8126ae2da77e2137f8c28d13a330cd3d2b37d56b"},
// subnetwork transaction
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "1529c132cad68a014b01bac39992462f8d6c9ba6a34382e0d1d3054232e46c54"},
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "0366d1f0ab7a2150cd1b80b8f8944e7f6a42a38b846f2610adc4106fe70696ec"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "19054bbf6dc75936dd018983373afd623a292ad1f39774cd1783b58074c3caa7"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "2fbfa5d3d24673b2e3530c3b268b58ecb6e7e34116d5c18849c27b0e7b6bfe4c"},
}
for _, test := range tests {
tx := test.tx
if test.modificationFunction != nil {
tx = test.modificationFunction(tx)
}
actualSignatureHash, err := consensushashing.CalculateSignatureHashSchnorr(
tx, test.inputIndex, test.hashType, &consensushashing.SighashReusedValues{})
if err != nil {
t.Errorf("%s: Error from CalculateSignatureHashSchnorr: %+v", test.name, err)
continue
}
if actualSignatureHash.String() != test.expectedSignatureHash {
t.Errorf("%s: expected signature hash: '%s'; but got: '%s'",
test.name, test.expectedSignatureHash, actualSignatureHash)
}
}
}
func TestCalculateSignatureHashECDSA(t *testing.T) {
nativeTx, subnetworkTx, err := generateTxs()
if err != nil {
t.Fatalf("Error from generateTxs: %+v", err)
}
// Note: Expected values were generated by the same code that they test,
// As long as those were not verified using 3rd-party code they only check for regression, not correctness
tests := []struct {
name string
tx *externalapi.DomainTransaction
hashType consensushashing.SigHashType
inputIndex int
modificationFunction func(*externalapi.DomainTransaction) *externalapi.DomainTransaction
expectedSignatureHash string
}{
// native transactions
// sigHashAll
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "ea7b79230b41f503baa6d3c14edf2d3e2cabc62db5b384bbac451a84c7a69694"},
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "9ba940467c07b4254f913a95398dc6f9fac0915e0dfe9560c58dfc1f87977c08"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "ba413a6ef1101c4a4995ac30a9013fe5591ef5f6dd8d7aabaa5dd8cb74d4d765"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "a471958e25168ab6671a76629d6f83b7f197a22972b333ebfa55d62dcc0ef065"},
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(0), // should change the hash
expectedSignatureHash: "6cce1e9ac60a7921a08ced668c03f74d207df02064896e0beb46988a8d2c243d"},
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(1), // shouldn't change the hash
expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "1113e57a0a188f1b9d0e07889792193af37374112874af681b3e36bee0627c1f"},
// sigHashNone
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "155e020f420fdaf62b31ccb3a13b6cb684c3db9ff85fc7062bb7e6a0653c7057"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "609c6f87c2cf10938ad1f69ceb0a6bb726690169b5e45d7c5797a420d244da55"},
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "3ee6c91cbbc998c52c02cad43b4a28743d6e96c9422393de69a0e15e08f470fb"},
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyAmountSpent(0), // should change the hash
expectedSignatureHash: "36e54667d08987a5d28d2124e7277ba5c2e93a9b8b9a7392bb7a57f1637edf76"},
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "bdce98b53163b42175f4e885f50e8a44821159fc05d7756e3870c5f91df2be2f"},
// sigHashSingle
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "394192ce7faee4f5055939c6fa3bf41a3008ec29e667d60bd5203987850debd4"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "55b1a9f7ee395ea37a8a6da804c9a654216364a42e37d329c5dc69c349369825"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "354c6ac137e5a3d05e85e9740039909202c20f8e229d7a94abc9096da3118256"},
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "8f386eefc0b389615279025f9c537102047fdf079df9a17ddad39d726130c736"},
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "7062156c393e71c6308f9d451a9f4850d9c331f77372d165bb9bcf0296e6a3d3"},
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
expectedSignatureHash: "84b56500814e4c7de8569ef6a5dfc269ca35db3160adaebedd92e68fe9d2c02b"},
// subnetwork transaction
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "ab783013148f1fbc6a0c29c5e2e320ea1dab61122f4b556810ef07c96871964a"},
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "bad87ce0a6d5fade1bb9eb5de572a3a9904e6d0ef5d627b97c69380818c1ad6f"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "54bdd33d4c8ea1baac6e92a129ad8a6bb90803b7b21387cc4ec9640752f4bb61"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "e71d0226c6c0cc26e0a99146f597ff9b9b51406f64854235b18f741d4c87eac4"},
}
for _, test := range tests {
tx := test.tx
if test.modificationFunction != nil {
tx = test.modificationFunction(tx)
}
actualSignatureHash, err := consensushashing.CalculateSignatureHashECDSA(
tx, test.inputIndex, test.hashType, &consensushashing.SighashReusedValues{})
if err != nil {
t.Errorf("%s: Error from CalculateSignatureHashECDSA: %+v", test.name, err)
continue
}
if actualSignatureHash.String() != test.expectedSignatureHash {
t.Errorf("%s: expected signature hash: '%s'; but got: '%s'",
test.name, test.expectedSignatureHash, actualSignatureHash)
}
}
}
func generateTxs() (nativeTx, subnetworkTx *externalapi.DomainTransaction, err error) {
genesisCoinbase := dagconfig.SimnetParams.GenesisBlock.Transactions[0]
genesisCoinbaseTransactionID := consensushashing.TransactionID(genesisCoinbase)
address1Str := "kaspasim:qzpj2cfa9m40w9m2cmr8pvfuqpp32mzzwsuw6ukhfduqpp32mzzws59e8fapc"
address1, err := util.DecodeAddress(address1Str, util.Bech32PrefixKaspaSim)
if err != nil {
return nil, nil, fmt.Errorf("error decoding address1: %+v", err)
}
address1ToScript, err := txscript.PayToAddrScript(address1)
if err != nil {
return nil, nil, fmt.Errorf("error generating script: %+v", err)
}
address2Str := "kaspasim:qr7w7nqsdnc3zddm6u8s9fex4ysk95hm3v30q353ymuqpp32mzzws59e8fapc"
address2, err := util.DecodeAddress(address2Str, util.Bech32PrefixKaspaSim)
if err != nil {
return nil, nil, fmt.Errorf("error decoding address2: %+v", err)
}
address2ToScript, err := txscript.PayToAddrScript(address2)
if err != nil {
return nil, nil, fmt.Errorf("error generating script: %+v", err)
}
txIns := []*externalapi.DomainTransactionInput{
{
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 0),
Sequence: 0,
UTXOEntry: utxo.NewUTXOEntry(100, address1ToScript, false, 0),
},
{
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 1),
Sequence: 1,
UTXOEntry: utxo.NewUTXOEntry(200, address2ToScript, false, 0),
},
{
PreviousOutpoint: *externalapi.NewDomainOutpoint(genesisCoinbaseTransactionID, 2),
Sequence: 2,
UTXOEntry: utxo.NewUTXOEntry(300, address2ToScript, false, 0),
},
}
txOuts := []*externalapi.DomainTransactionOutput{
{
Value: 300,
ScriptPublicKey: address2ToScript,
},
{
Value: 300,
ScriptPublicKey: address1ToScript,
},
}
nativeTx = &externalapi.DomainTransaction{
Version: 0,
Inputs: txIns,
Outputs: txOuts,
LockTime: 1615462089000,
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
}
subnetworkTx = &externalapi.DomainTransaction{
Version: 0,
Inputs: txIns,
Outputs: txOuts,
LockTime: 1615462089000,
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
Gas: 250,
Payload: []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
}
return nativeTx, subnetworkTx, nil
}
func BenchmarkCalculateSignatureHashSchnorr(b *testing.B) {
sigHashTypes := []consensushashing.SigHashType{
consensushashing.SigHashAll,
consensushashing.SigHashNone,
consensushashing.SigHashSingle,
consensushashing.SigHashAll | consensushashing.SigHashAnyOneCanPay,
consensushashing.SigHashNone | consensushashing.SigHashAnyOneCanPay,
consensushashing.SigHashSingle | consensushashing.SigHashAnyOneCanPay}
for _, size := range []int{10, 100, 1000} {
tx := generateTransaction(b, sigHashTypes, size)
b.Run(fmt.Sprintf("%d-inputs-and-outputs", size), func(b *testing.B) {
for i := 0; i < b.N; i++ {
reusedValues := &consensushashing.SighashReusedValues{}
for inputIndex := range tx.Inputs {
sigHashType := sigHashTypes[inputIndex%len(sigHashTypes)]
_, err := consensushashing.CalculateSignatureHashSchnorr(tx, inputIndex, sigHashType, reusedValues)
if err != nil {
b.Fatalf("Error from CalculateSignatureHashSchnorr: %+v", err)
}
}
}
})
}
}
func generateTransaction(b *testing.B, sigHashTypes []consensushashing.SigHashType, inputAndOutputSizes int) *externalapi.DomainTransaction {
sourceScript := getSourceScript(b)
tx := &externalapi.DomainTransaction{
Version: 0,
Inputs: generateInputs(inputAndOutputSizes, sourceScript),
Outputs: generateOutputs(inputAndOutputSizes, sourceScript),
LockTime: 123456789,
SubnetworkID: externalapi.DomainSubnetworkID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
Gas: 125,
Payload: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
Fee: 0,
Mass: 0,
ID: nil,
}
signTx(b, tx, sigHashTypes)
return tx
}
func signTx(b *testing.B, tx *externalapi.DomainTransaction, sigHashTypes []consensushashing.SigHashType) {
sourceAddressPKStr := "a4d85b7532123e3dd34e58d7ce20895f7ca32349e29b01700bb5a3e72d2570eb"
privateKeyBytes, err := hex.DecodeString(sourceAddressPKStr)
if err != nil {
b.Fatalf("Error parsing private key hex: %+v", err)
}
keyPair, err := secp256k1.DeserializeSchnorrPrivateKeyFromSlice(privateKeyBytes)
if err != nil {
b.Fatalf("Error deserializing private key: %+v", err)
}
for i, txIn := range tx.Inputs {
signatureScript, err := txscript.SignatureScript(
tx, i, sigHashTypes[i%len(sigHashTypes)], keyPair, &consensushashing.SighashReusedValues{})
if err != nil {
b.Fatalf("Error from SignatureScript: %+v", err)
}
txIn.SignatureScript = signatureScript
}
}
func generateInputs(size int, sourceScript *externalapi.ScriptPublicKey) []*externalapi.DomainTransactionInput {
inputs := make([]*externalapi.DomainTransactionInput, size)
for i := 0; i < size; i++ {
inputs[i] = &externalapi.DomainTransactionInput{
PreviousOutpoint: *externalapi.NewDomainOutpoint(
externalapi.NewDomainTransactionIDFromByteArray(&[32]byte{12, 3, 4, 5}), 1),
SignatureScript: nil,
Sequence: uint64(i),
UTXOEntry: utxo.NewUTXOEntry(uint64(i), sourceScript, false, 12),
}
}
return inputs
}
func getSourceScript(b *testing.B) *externalapi.ScriptPublicKey {
sourceAddressStr := "kaspasim:qz6f9z6l3x4v3lf9mgf0t934th4nx5kgzu663x9yjh"
sourceAddress, err := util.DecodeAddress(sourceAddressStr, util.Bech32PrefixKaspaSim)
if err != nil {
b.Fatalf("Error from DecodeAddress: %+v", err)
}
sourceScript, err := txscript.PayToAddrScript(sourceAddress)
if err != nil {
b.Fatalf("Error from PayToAddrScript: %+v", err)
}
return sourceScript
}
func generateOutputs(size int, script *externalapi.ScriptPublicKey) []*externalapi.DomainTransactionOutput {
outputs := make([]*externalapi.DomainTransactionOutput, size)
for i := 0; i < size; i++ {
outputs[i] = &externalapi.DomainTransactionOutput{
Value: uint64(i),
ScriptPublicKey: script,
}
}
return outputs
}