From 2fb8578126651bfdb976ac84118535c3a133fe05 Mon Sep 17 00:00:00 2001 From: paologalligit Date: Wed, 18 Dec 2024 15:24:02 +0100 Subject: [PATCH] test: add more dynFee txs to tests --- api/subscriptions/block_reader_test.go | 4 +- api/subscriptions/pending_tx_test.go | 62 ++++++++++------ api/subscriptions/subscriptions_test.go | 4 +- api/subscriptions/types_test.go | 70 +++++++++++++----- api/transactions/types_test.go | 98 ++++++++++++++++--------- block/block_test.go | 2 +- chain/chain_test.go | 97 +++++++++++++----------- chain/repository_test.go | 20 +++++ packer/flow_test.go | 84 +++++++++++++++++++-- runtime/resolved_tx_test.go | 83 +++++++++++++++------ runtime/runtime_test.go | 21 ++++-- tx/signer_test.go | 98 ++++++++++++++----------- tx/transaction_test.go | 2 +- 13 files changed, 436 insertions(+), 209 deletions(-) diff --git a/api/subscriptions/block_reader_test.go b/api/subscriptions/block_reader_test.go index 76c0be17b..e60bfb770 100644 --- a/api/subscriptions/block_reader_test.go +++ b/api/subscriptions/block_reader_test.go @@ -75,9 +75,9 @@ func initChain(t *testing.T) *testchain.Chain { Build() tr = tx.MustSign(tr, genesis.DevAccounts()[0].PrivateKey) - txDeploy := new(tx.LegacyBuilder). + txDeploy := new(tx.DynFeeBuilder). ChainTag(thorChain.Repo().ChainTag()). - GasPriceCoef(1). + MaxFeePerGas(big.NewInt(1)). Expiration(100). Gas(1_000_000). Nonce(3). diff --git a/api/subscriptions/pending_tx_test.go b/api/subscriptions/pending_tx_test.go index c54c14227..c1bf98509 100644 --- a/api/subscriptions/pending_tx_test.go +++ b/api/subscriptions/pending_tx_test.go @@ -95,7 +95,7 @@ func TestPendingTx_DispatchLoop(t *testing.T) { p.Subscribe(txCh) // Add a new tx to the mempool - transaction := createTx(repo, 0) + transaction := createLegacyTx(repo, 0) txPool.AddLocal(transaction) // Start the dispatch loop @@ -113,7 +113,7 @@ func TestPendingTx_DispatchLoop(t *testing.T) { p.Unsubscribe(txCh) // Add another tx to the mempool - tx2 := createTx(repo, 1) + tx2 := createDynFeeTx(repo, 1) txPool.AddLocal(tx2) // Assert that the channel did not receive the second transaction @@ -147,24 +147,6 @@ func addNewBlock(repo *chain.Repository, stater *state.Stater, b0 *block.Block, } } -func createTx(repo *chain.Repository, addressNumber uint) *tx.Transaction { - addr := thor.BytesToAddress([]byte("to")) - cla := tx.NewClause(&addr).WithValue(big.NewInt(10000)) - - return tx.MustSign( - new(tx.LegacyBuilder). - ChainTag(repo.ChainTag()). - GasPriceCoef(1). - Expiration(1000). - Gas(21000). - Nonce(uint64(datagen.RandInt())). - Clause(cla). - BlockRef(tx.NewBlockRef(0)). - Build(), - genesis.DevAccounts()[addressNumber].PrivateKey, - ) -} - func TestPendingTx_NoWriteAfterUnsubscribe(t *testing.T) { // Arrange thorChain := initChain(t) @@ -183,7 +165,7 @@ func TestPendingTx_NoWriteAfterUnsubscribe(t *testing.T) { done := make(chan struct{}) // Attempt to write a new transaction - trx := createTx(thorChain.Repo(), 0) + trx := createLegacyTx(thorChain.Repo(), 0) assert.NotPanics(t, func() { p.dispatch(trx, done) // dispatch should not panic after unsubscribe }, "Dispatching after unsubscribe should not panic") @@ -221,7 +203,7 @@ func TestPendingTx_UnsubscribeOnWebSocketClose(t *testing.T) { defer ws.Close() // Add a transaction - trx := createTx(thorChain.Repo(), 0) + trx := createLegacyTx(thorChain.Repo(), 0) txPool.AddLocal(trx) // Wait to receive transaction @@ -242,3 +224,39 @@ func TestPendingTx_UnsubscribeOnWebSocketClose(t *testing.T) { require.Equal(t, len(sub.pendingTx.listeners), 0) sub.pendingTx.mu.Unlock() } + +func createLegacyTx(repo *chain.Repository, addressNumber uint) *tx.Transaction { + addr := thor.BytesToAddress([]byte("to")) + cla := tx.NewClause(&addr).WithValue(big.NewInt(10000)) + + return tx.MustSign( + new(tx.LegacyBuilder). + ChainTag(repo.ChainTag()). + GasPriceCoef(1). + Expiration(1000). + Gas(21000). + Nonce(uint64(datagen.RandInt())). + Clause(cla). + BlockRef(tx.NewBlockRef(0)). + Build(), + genesis.DevAccounts()[addressNumber].PrivateKey, + ) +} + +func createDynFeeTx(repo *chain.Repository, addressNumber uint) *tx.Transaction { + addr := thor.BytesToAddress([]byte("to")) + cla := tx.NewClause(&addr).WithValue(big.NewInt(10000)) + + return tx.MustSign( + new(tx.DynFeeBuilder). + ChainTag(repo.ChainTag()). + MaxFeePerGas(big.NewInt(1)). + Expiration(10). + Gas(21000). + Nonce(1). + Clause(cla). + BlockRef(tx.NewBlockRef(0)). + Build(), + genesis.DevAccounts()[addressNumber].PrivateKey, + ) +} diff --git a/api/subscriptions/subscriptions_test.go b/api/subscriptions/subscriptions_test.go index c89b78861..ec6af802c 100644 --- a/api/subscriptions/subscriptions_test.go +++ b/api/subscriptions/subscriptions_test.go @@ -239,9 +239,9 @@ func initSubscriptionsServer(t *testing.T, enabledDeprecated bool) { addr := thor.BytesToAddress([]byte("to")) cla := tx.NewClause(&addr).WithValue(big.NewInt(10000)) - tr := new(tx.LegacyBuilder). + tr := new(tx.DynFeeBuilder). ChainTag(thorChain.Repo().ChainTag()). - GasPriceCoef(1). + MaxFeePerGas(big.NewInt(1)). Expiration(10). Gas(21000). Nonce(1). diff --git a/api/subscriptions/types_test.go b/api/subscriptions/types_test.go index 890542452..5720ad2b2 100644 --- a/api/subscriptions/types_test.go +++ b/api/subscriptions/types_test.go @@ -95,7 +95,7 @@ func TestConvertTransfer(t *testing.T) { repo, _ := chain.NewRepository(db, b) // New tx - transaction := new(tx.LegacyBuilder). + legacyTx := new(tx.LegacyBuilder). ChainTag(repo.ChainTag()). GasPriceCoef(1). Expiration(10). @@ -103,11 +103,22 @@ func TestConvertTransfer(t *testing.T) { Nonce(1). BlockRef(tx.NewBlockRef(0)). Build() - transaction = tx.MustSign(transaction, genesis.DevAccounts()[0].PrivateKey) + legacyTx = tx.MustSign(legacyTx, genesis.DevAccounts()[0].PrivateKey) + + dynFeeTx := new(tx.DynFeeBuilder). + ChainTag(repo.ChainTag()). + MaxFeePerGas(big.NewInt(1)). + Expiration(10). + Gas(21000). + Nonce(1). + BlockRef(tx.NewBlockRef(0)). + Build() + dynFeeTx = tx.MustSign(dynFeeTx, genesis.DevAccounts()[0].PrivateKey) // New block blk := new(block.Builder). - Transaction(transaction). + Transaction(legacyTx). + Transaction(dynFeeTx). Build() transfer := &tx.Transfer{ @@ -117,25 +128,46 @@ func TestConvertTransfer(t *testing.T) { } // Act - transferMessage, err := convertTransfer(blk.Header(), transaction, 0, transfer, false) + transferLegacyMessage, errL := convertTransfer(blk.Header(), legacyTx, 0, transfer, false) + transferDynFeeMessage, errD := convertTransfer(blk.Header(), dynFeeTx, 1, transfer, false) // Assert - assert.NoError(t, err) - assert.Equal(t, transfer.Sender, transferMessage.Sender) - assert.Equal(t, transfer.Recipient, transferMessage.Recipient) + assert.NoError(t, errL) + assert.NoError(t, errD) + + assert.Equal(t, transfer.Sender, transferLegacyMessage.Sender) + assert.Equal(t, transfer.Sender, transferDynFeeMessage.Sender) + + assert.Equal(t, transfer.Recipient, transferLegacyMessage.Recipient) + assert.Equal(t, transfer.Recipient, transferDynFeeMessage.Recipient) + amount := (*math.HexOrDecimal256)(transfer.Amount) - assert.Equal(t, amount, transferMessage.Amount) - assert.Equal(t, blk.Header().ID(), transferMessage.Meta.BlockID) - assert.Equal(t, blk.Header().Number(), transferMessage.Meta.BlockNumber) - assert.Equal(t, blk.Header().Timestamp(), transferMessage.Meta.BlockTimestamp) - assert.Equal(t, transaction.ID(), transferMessage.Meta.TxID) - origin, err := transaction.Origin() - if err != nil { - t.Fatal(err) - } - assert.Equal(t, origin, transferMessage.Meta.TxOrigin) - assert.Equal(t, uint32(0), transferMessage.Meta.ClauseIndex) - assert.Equal(t, false, transferMessage.Obsolete) + assert.Equal(t, amount, transferLegacyMessage.Amount) + assert.Equal(t, amount, transferDynFeeMessage.Amount) + + assert.Equal(t, blk.Header().ID(), transferLegacyMessage.Meta.BlockID) + assert.Equal(t, blk.Header().ID(), transferDynFeeMessage.Meta.BlockID) + + assert.Equal(t, blk.Header().Number(), transferLegacyMessage.Meta.BlockNumber) + assert.Equal(t, blk.Header().Number(), transferDynFeeMessage.Meta.BlockNumber) + + assert.Equal(t, blk.Header().Timestamp(), transferLegacyMessage.Meta.BlockTimestamp) + assert.Equal(t, blk.Header().Timestamp(), transferDynFeeMessage.Meta.BlockTimestamp) + + assert.Equal(t, legacyTx.ID(), transferLegacyMessage.Meta.TxID) + assert.Equal(t, dynFeeTx.ID(), transferDynFeeMessage.Meta.TxID) + + origin, err := legacyTx.Origin() + assert.NoError(t, err) + assert.Equal(t, origin, transferLegacyMessage.Meta.TxOrigin) + assert.Equal(t, uint32(0), transferLegacyMessage.Meta.ClauseIndex) + assert.Equal(t, false, transferLegacyMessage.Obsolete) + + origin, err = dynFeeTx.Origin() + assert.NoError(t, err) + assert.Equal(t, origin, transferDynFeeMessage.Meta.TxOrigin) + assert.Equal(t, uint32(1), transferDynFeeMessage.Meta.ClauseIndex) + assert.Equal(t, false, transferDynFeeMessage.Obsolete) } func TestConvertEventWithBadSignature(t *testing.T) { diff --git a/api/transactions/types_test.go b/api/transactions/types_test.go index b560b2ddc..e11d346df 100644 --- a/api/transactions/types_test.go +++ b/api/transactions/types_test.go @@ -21,55 +21,72 @@ import ( ) func TestErrorWhileRetrievingTxOriginInConvertReceipt(t *testing.T) { - tr := new(tx.LegacyBuilder).Build() - header := &block.Header{} - receipt := &tx.Receipt{ - Reward: big.NewInt(100), - Paid: big.NewInt(10), + txs := []*tx.Transaction{ + new(tx.LegacyBuilder).Build(), + new(tx.DynFeeBuilder).Build(), } - convRec, err := convertReceipt(receipt, header, tr) + for _, tr := range txs { + header := &block.Header{} + receipt := &tx.Receipt{ + Reward: big.NewInt(100), + Paid: big.NewInt(10), + } - assert.Error(t, err) - assert.Equal(t, err, secp256k1.ErrInvalidSignatureLen) - assert.Nil(t, convRec) + convRec, err := convertReceipt(receipt, header, tr) + + assert.Error(t, err) + assert.Equal(t, err, secp256k1.ErrInvalidSignatureLen) + assert.Nil(t, convRec) + } } func TestConvertReceiptWhenTxHasNoClauseTo(t *testing.T) { value := big.NewInt(100) - tr := newTx(tx.NewClause(nil).WithValue(value)) - b := new(block.Builder).Build() - header := b.Header() - receipt := newReceipt() - expectedOutputAddress := thor.CreateContractAddress(tr.ID(), uint32(0), 0) + txs := []*tx.Transaction{ + newLegacyTx(tx.NewClause(nil).WithValue(value)), + newDynFeeTx(tx.NewClause(nil).WithValue(value)), + } + for _, tr := range txs { + b := new(block.Builder).Build() + header := b.Header() + receipt := newReceipt() + expectedOutputAddress := thor.CreateContractAddress(tr.ID(), uint32(0), 0) - convRec, err := convertReceipt(receipt, header, tr) + convRec, err := convertReceipt(receipt, header, tr) - assert.NoError(t, err) - assert.Equal(t, 1, len(convRec.Outputs)) - assert.Equal(t, &expectedOutputAddress, convRec.Outputs[0].ContractAddress) + assert.NoError(t, err) + assert.Equal(t, 1, len(convRec.Outputs)) + assert.Equal(t, &expectedOutputAddress, convRec.Outputs[0].ContractAddress) + } } func TestConvertReceipt(t *testing.T) { value := big.NewInt(100) addr := randAddress() - tr := newTx(tx.NewClause(&addr).WithValue(value)) - b := new(block.Builder).Build() - header := b.Header() - receipt := newReceipt() - - convRec, err := convertReceipt(receipt, header, tr) - - assert.NoError(t, err) - assert.Equal(t, 1, len(convRec.Outputs)) - assert.Equal(t, 1, len(convRec.Outputs[0].Events)) - assert.Equal(t, 1, len(convRec.Outputs[0].Transfers)) - assert.Nil(t, convRec.Outputs[0].ContractAddress) - assert.Equal(t, receipt.Outputs[0].Events[0].Address, convRec.Outputs[0].Events[0].Address) - assert.Equal(t, hexutil.Encode(receipt.Outputs[0].Events[0].Data), convRec.Outputs[0].Events[0].Data) - assert.Equal(t, receipt.Outputs[0].Transfers[0].Sender, convRec.Outputs[0].Transfers[0].Sender) - assert.Equal(t, receipt.Outputs[0].Transfers[0].Recipient, convRec.Outputs[0].Transfers[0].Recipient) - assert.Equal(t, (*math.HexOrDecimal256)(receipt.Outputs[0].Transfers[0].Amount), convRec.Outputs[0].Transfers[0].Amount) + + txs := []*tx.Transaction{ + newLegacyTx(tx.NewClause(&addr).WithValue(value)), + newDynFeeTx(tx.NewClause(&addr).WithValue(value)), + } + for _, tr := range txs { + b := new(block.Builder).Build() + header := b.Header() + receipt := newReceipt() + + convRec, err := convertReceipt(receipt, header, tr) + + assert.NoError(t, err) + assert.Equal(t, 1, len(convRec.Outputs)) + assert.Equal(t, 1, len(convRec.Outputs[0].Events)) + assert.Equal(t, 1, len(convRec.Outputs[0].Transfers)) + assert.Nil(t, convRec.Outputs[0].ContractAddress) + assert.Equal(t, receipt.Outputs[0].Events[0].Address, convRec.Outputs[0].Events[0].Address) + assert.Equal(t, hexutil.Encode(receipt.Outputs[0].Events[0].Data), convRec.Outputs[0].Events[0].Data) + assert.Equal(t, receipt.Outputs[0].Transfers[0].Sender, convRec.Outputs[0].Transfers[0].Sender) + assert.Equal(t, receipt.Outputs[0].Transfers[0].Recipient, convRec.Outputs[0].Transfers[0].Recipient) + assert.Equal(t, (*math.HexOrDecimal256)(receipt.Outputs[0].Transfers[0].Amount), convRec.Outputs[0].Transfers[0].Amount) + } } // Utilities functions @@ -99,7 +116,7 @@ func newReceipt() *tx.Receipt { } } -func newTx(clause *tx.Clause) *tx.Transaction { +func newLegacyTx(clause *tx.Clause) *tx.Transaction { tx := new(tx.LegacyBuilder). Clause(clause). Build() @@ -108,6 +125,15 @@ func newTx(clause *tx.Clause) *tx.Transaction { return tx.WithSignature(sig) } +func newDynFeeTx(clause *tx.Clause) *tx.Transaction { + tx := new(tx.DynFeeBuilder). + Clause(clause). + Build() + pk, _ := crypto.GenerateKey() + sig, _ := crypto.Sign(tx.SigningHash().Bytes(), pk) + return tx.WithSignature(sig) +} + func randomBytes32() thor.Bytes32 { var b32 thor.Bytes32 diff --git a/block/block_test.go b/block/block_test.go index 24c16159c..3f635e2a2 100644 --- a/block/block_test.go +++ b/block/block_test.go @@ -19,7 +19,7 @@ import ( func TestBlock(t *testing.T) { tx1 := new(tx.LegacyBuilder).Clause(tx.NewClause(&thor.Address{})).Clause(tx.NewClause(&thor.Address{})).Build() - tx2 := new(tx.LegacyBuilder).Clause(tx.NewClause(nil)).Build() + tx2 := new(tx.DynFeeBuilder).Clause(tx.NewClause(nil)).Build() privKey := string("dce1443bd2ef0c2631adc1c67e5c93f13dc23a41c18b536effbbdcbcdb96fb65") diff --git a/chain/chain_test.go b/chain/chain_test.go index 23a9ec27d..781d4ca86 100644 --- a/chain/chain_test.go +++ b/chain/chain_test.go @@ -16,71 +16,82 @@ import ( "github.com/vechain/thor/v2/tx" ) -func newTx() *tx.Transaction { +func newLegacyTx() *tx.Transaction { tx := new(tx.LegacyBuilder).Build() pk, _ := crypto.GenerateKey() sig, _ := crypto.Sign(tx.SigningHash().Bytes(), pk) return tx.WithSignature(sig) } -func TestChain(t *testing.T) { - tx1 := newTx() +func newDynFeeTx() *tx.Transaction { + tx := new(tx.LegacyBuilder).Build() + pk, _ := crypto.GenerateKey() + sig, _ := crypto.Sign(tx.SigningHash().Bytes(), pk) + return tx.WithSignature(sig) +} +func TestChain(t *testing.T) { _, repo := newTestRepo() + txs := []*tx.Transaction{ + newLegacyTx(), + newDynFeeTx(), + } - b1 := newBlock(repo.GenesisBlock(), 10, tx1) - tx1Meta := &chain.TxMeta{BlockID: b1.Header().ID(), Index: 0, Reverted: false} - tx1Receipt := &tx.Receipt{} - repo.AddBlock(b1, tx.Receipts{tx1Receipt}, 0) + for _, tr := range txs { + b1 := newBlock(repo.GenesisBlock(), 10, tr) + tx1Meta := &chain.TxMeta{BlockID: b1.Header().ID(), Index: 0, Reverted: false} + tx1Receipt := &tx.Receipt{} + repo.AddBlock(b1, tx.Receipts{tx1Receipt}, 0) - b2 := newBlock(b1, 20) - repo.AddBlock(b2, nil, 0) + b2 := newBlock(b1, 20) + repo.AddBlock(b2, nil, 0) - b3 := newBlock(b2, 30) - repo.AddBlock(b3, nil, 0) + b3 := newBlock(b2, 30) + repo.AddBlock(b3, nil, 0) - b3x := newBlock(b2, 30) - repo.AddBlock(b3x, nil, 1) + b3x := newBlock(b2, 30) + repo.AddBlock(b3x, nil, 1) - c := repo.NewChain(b3.Header().ID()) + c := repo.NewChain(b3.Header().ID()) - assert.Equal(t, b3.Header().ID(), c.HeadID()) - assert.Equal(t, M(b3.Header().ID(), nil), M(c.GetBlockID(3))) - assert.Equal(t, M(b3.Header(), nil), M(c.GetBlockHeader(3))) - assert.Equal(t, M(block.Compose(b3.Header(), b3.Transactions()), nil), M(c.GetBlock(3))) + assert.Equal(t, b3.Header().ID(), c.HeadID()) + assert.Equal(t, M(b3.Header().ID(), nil), M(c.GetBlockID(3))) + assert.Equal(t, M(b3.Header(), nil), M(c.GetBlockHeader(3))) + assert.Equal(t, M(block.Compose(b3.Header(), b3.Transactions()), nil), M(c.GetBlock(3))) - _, err := c.GetBlockID(4) - assert.True(t, c.IsNotFound(err)) + _, err := c.GetBlockID(4) + assert.True(t, c.IsNotFound(err)) - assert.Equal(t, M(tx1Meta, nil), M(c.GetTransactionMeta(tx1.ID()))) - assert.Equal(t, M(tx1, tx1Meta, nil), M(c.GetTransaction(tx1.ID()))) - assert.Equal(t, M(tx1Receipt, nil), M(c.GetTransactionReceipt(tx1.ID()))) - _, err = c.GetTransactionMeta(thor.Bytes32{}) - assert.True(t, c.IsNotFound(err)) + assert.Equal(t, M(tx1Meta, nil), M(c.GetTransactionMeta(tr.ID()))) + assert.Equal(t, M(tr, tx1Meta, nil), M(c.GetTransaction(tr.ID()))) + assert.Equal(t, M(tx1Receipt, nil), M(c.GetTransactionReceipt(tr.ID()))) + _, err = c.GetTransactionMeta(thor.Bytes32{}) + assert.True(t, c.IsNotFound(err)) - assert.Equal(t, M(true, nil), M(c.HasTransaction(tx1.ID(), tx1.BlockRef().Number()))) - assert.Equal(t, M(false, nil), M(c.HasTransaction(tx1.ID(), block.Number(c.HeadID())))) - assert.Equal(t, M(false, nil), M(c.HasTransaction(thor.Bytes32{}, 0))) + assert.Equal(t, M(true, nil), M(c.HasTransaction(tr.ID(), tr.BlockRef().Number()))) + assert.Equal(t, M(false, nil), M(c.HasTransaction(tr.ID(), block.Number(c.HeadID())))) + assert.Equal(t, M(false, nil), M(c.HasTransaction(thor.Bytes32{}, 0))) - assert.Equal(t, M(true, nil), M(c.HasBlock(b1.Header().ID()))) - assert.Equal(t, M(false, nil), M(c.HasBlock(b3x.Header().ID()))) + assert.Equal(t, M(true, nil), M(c.HasBlock(b1.Header().ID()))) + assert.Equal(t, M(false, nil), M(c.HasBlock(b3x.Header().ID()))) - assert.Equal(t, M(b3.Header(), nil), M(c.FindBlockHeaderByTimestamp(25, 1))) - assert.Equal(t, M(b2.Header(), nil), M(c.FindBlockHeaderByTimestamp(25, -1))) - _, err = c.FindBlockHeaderByTimestamp(25, 0) - assert.True(t, c.IsNotFound(err)) + assert.Equal(t, M(b3.Header(), nil), M(c.FindBlockHeaderByTimestamp(25, 1))) + assert.Equal(t, M(b2.Header(), nil), M(c.FindBlockHeaderByTimestamp(25, -1))) + _, err = c.FindBlockHeaderByTimestamp(25, 0) + assert.True(t, c.IsNotFound(err)) - c1, c2 := repo.NewChain(b3.Header().ID()), repo.NewChain(b3x.Header().ID()) + c1, c2 := repo.NewChain(b3.Header().ID()), repo.NewChain(b3x.Header().ID()) - assert.Equal(t, M([]thor.Bytes32{b3.Header().ID()}, nil), M(c1.Exclude(c2))) - assert.Equal(t, M([]thor.Bytes32{b3x.Header().ID()}, nil), M(c2.Exclude(c1))) + assert.Equal(t, M([]thor.Bytes32{b3.Header().ID()}, nil), M(c1.Exclude(c2))) + assert.Equal(t, M([]thor.Bytes32{b3x.Header().ID()}, nil), M(c2.Exclude(c1))) - dangleID := thor.Bytes32{0, 0, 0, 4} - dangleChain := repo.NewChain(dangleID) + dangleID := thor.Bytes32{0, 0, 0, 4} + dangleChain := repo.NewChain(dangleID) - _, err = c1.Exclude(dangleChain) - assert.Error(t, err) + _, err = c1.Exclude(dangleChain) + assert.Error(t, err) - _, err = dangleChain.Exclude(c1) - assert.Error(t, err) + _, err = dangleChain.Exclude(c1) + assert.Error(t, err) + } } diff --git a/chain/repository_test.go b/chain/repository_test.go index c15c10e0f..48e7f31aa 100644 --- a/chain/repository_test.go +++ b/chain/repository_test.go @@ -97,6 +97,26 @@ func TestRepository(t *testing.T) { assert.Equal(t, tx.Receipts{receipt1}.RootHash(), gotReceipts.RootHash()) } + + tx2 := new(tx.DynFeeBuilder).Build() + receipt2 := &tx.Receipt{} + + b2 := newBlock(b1, 20, tx2) + assert.Nil(t, repo1.AddBlock(b2, tx.Receipts{receipt2}, 0)) + + repo1.SetBestBlockID(b2.Header().ID()) + repo2, _ = chain.NewRepository(db, b0) + for _, repo := range []*chain.Repository{repo1, repo2} { + assert.Equal(t, b2.Header().ID(), repo.BestBlockSummary().Header.ID()) + s, err := repo.GetBlockSummary(b2.Header().ID()) + assert.Nil(t, err) + assert.Equal(t, b2.Header().ID(), s.Header.ID()) + assert.Equal(t, 1, len(s.Txs)) + assert.Equal(t, tx2.ID(), s.Txs[0]) + + gotb, _ := repo.GetBlock(b2.Header().ID()) + assert.Equal(t, b2.Transactions().RootHash(), gotb.Transactions().RootHash()) + } } func TestConflicts(t *testing.T) { diff --git a/packer/flow_test.go b/packer/flow_test.go index 7b44f04c5..0fcb61be2 100644 --- a/packer/flow_test.go +++ b/packer/flow_test.go @@ -21,7 +21,7 @@ import ( "github.com/vechain/thor/v2/tx" ) -func createTx(chainTag byte, gasPriceCoef uint8, expiration uint32, gas uint64, nonce uint64, dependsOn *thor.Bytes32, clause *tx.Clause, br tx.BlockRef) *tx.Transaction { +func createLegacyTx(chainTag byte, gasPriceCoef uint8, expiration uint32, gas uint64, nonce uint64, dependsOn *thor.Bytes32, clause *tx.Clause, br tx.BlockRef) *tx.Transaction { builder := new(tx.LegacyBuilder). ChainTag(chainTag). GasPriceCoef(gasPriceCoef). @@ -39,6 +39,25 @@ func createTx(chainTag byte, gasPriceCoef uint8, expiration uint32, gas uint64, return transaction.WithSignature(signature) } +func createDynFeeTx(chainTag byte, expiration uint32, gas uint64, maxFeePerGas, maxPriorityFeePerGas *big.Int, nonce uint64, dependsOn *thor.Bytes32, clause *tx.Clause, br tx.BlockRef) *tx.Transaction { + builder := new(tx.DynFeeBuilder). + ChainTag(chainTag). + Expiration(expiration). + Gas(gas). + MaxFeePerGas(maxFeePerGas). + MaxPriorityFeePerGas(maxPriorityFeePerGas). + Nonce(nonce). + DependsOn(dependsOn). + Clause(clause). + BlockRef(br) + + transaction := builder.Build() + + signature, _ := crypto.Sign(transaction.SigningHash().Bytes(), genesis.DevAccounts()[0].PrivateKey) + + return transaction.WithSignature(signature) +} + func TestAdopt(t *testing.T) { // Setup environment db := muxdb.NewMem() @@ -66,12 +85,12 @@ func TestAdopt(t *testing.T) { t.Fatal("Error scheduling:", err) } - tx1 := createTx(chainTag, 1, 10, 21000, 1, nil, clause, tx.NewBlockRef(0)) + tx1 := createLegacyTx(chainTag, 1, 10, 21000, 1, nil, clause, tx.NewBlockRef(0)) if err := flow.Adopt(tx1); err != nil { t.Fatal("Error adopting tx1:", err) } - tx2 := createTx(chainTag, 1, 10, 21000, 2, (*thor.Bytes32)(tx1.ID().Bytes()), clause, tx.NewBlockRef(0)) + tx2 := createLegacyTx(chainTag, 1, 10, 21000, 2, (*thor.Bytes32)(tx1.ID().Bytes()), clause, tx.NewBlockRef(0)) if err := flow.Adopt(tx2); err != nil { t.Fatal("Error adopting tx2:", err) } @@ -83,7 +102,7 @@ func TestAdopt(t *testing.T) { } // Test dependency that does not exist - tx3 := createTx(chainTag, 1, 10, 21000, 2, (*thor.Bytes32)((thor.Bytes32{0x1}).Bytes()), clause, tx.NewBlockRef(0)) + tx3 := createLegacyTx(chainTag, 1, 10, 21000, 2, (*thor.Bytes32)((thor.Bytes32{0x1}).Bytes()), clause, tx.NewBlockRef(0)) expectedErrorMessage = "tx not adoptable now" if err := flow.Adopt(tx3); err.Error() != expectedErrorMessage { t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) @@ -95,6 +114,57 @@ func TestAdopt(t *testing.T) { flow.TotalScore() } +func TestAdoptTypedTxs(t *testing.T) { + // Setup environment + db := muxdb.NewMem() + stater := state.NewStater(db) + g := genesis.NewDevnet() + + // Build genesis block + b, _, _, _ := g.Build(stater) + repo, _ := chain.NewRepository(db, b) + + // Common transaction setup + chainTag := repo.ChainTag() + addr := thor.BytesToAddress([]byte("to")) + clause := tx.NewClause(&addr).WithValue(big.NewInt(10000)) + + // Create and adopt two transactions + pkr := packer.New(repo, stater, genesis.DevAccounts()[0].Address, &genesis.DevAccounts()[0].Address, thor.NoFork) + sum, err := repo.GetBlockSummary(b.Header().ID()) + if err != nil { + t.Fatal("Error getting block summary:", err) + } + + flow, err := pkr.Schedule(sum, uint64(time.Now().Unix())) + if err != nil { + t.Fatal("Error scheduling:", err) + } + + tx1 := createLegacyTx(chainTag, 1, 10, 21000, 1, nil, clause, tx.NewBlockRef(0)) + if err := flow.Adopt(tx1); err != nil { + t.Fatal("Error adopting tx1:", err) + } + + tx2 := createDynFeeTx(chainTag, 10, 21000, big.NewInt(2500), big.NewInt(1000), 2, (*thor.Bytes32)(tx1.ID().Bytes()), clause, tx.NewBlockRef(0)) + if err := flow.Adopt(tx2); err != nil { + t.Fatal("Error adopting tx2:", err) + } + + //Repeat transaction + expectedErrorMessage := "known tx" + if err := flow.Adopt(tx2); err.Error() != expectedErrorMessage { + t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) + } + + // Test dependency that does not exist + tx3 := createDynFeeTx(chainTag, 10, 21000, big.NewInt(2500), big.NewInt(1000), 2, (*thor.Bytes32)((thor.Bytes32{0x1}).Bytes()), clause, tx.NewBlockRef(0)) + expectedErrorMessage = "tx not adoptable now" + if err := flow.Adopt(tx3); err.Error() != expectedErrorMessage { + t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) + } +} + func TestPack(t *testing.T) { db := muxdb.NewMem() g := genesis.NewDevnet() @@ -160,21 +230,21 @@ func TestAdoptErr(t *testing.T) { flow, _ := pkr.Schedule(sum, uint64(time.Now().Unix())) // Test chain tag mismatch - tx1 := createTx(byte(0xFF), 1, 10, 21000, 1, nil, clause, tx.NewBlockRef(0)) + tx1 := createLegacyTx(byte(0xFF), 1, 10, 21000, 1, nil, clause, tx.NewBlockRef(0)) expectedErrorMessage := "bad tx: chain tag mismatch" if err := flow.Adopt(tx1); err.Error() != expectedErrorMessage { t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) } // Test wrong block reference - tx2 := createTx(repo.ChainTag(), 1, 10, 1, 21000, nil, clause, tx.NewBlockRef(1000)) + tx2 := createLegacyTx(repo.ChainTag(), 1, 10, 1, 21000, nil, clause, tx.NewBlockRef(1000)) expectedErrorMessage = "tx not adoptable now" if err := flow.Adopt(tx2); err.Error() != expectedErrorMessage { t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) } // Test exceeded gas limit - tx3 := createTx(repo.ChainTag(), 1, 0, 1, 1, nil, clause, tx.NewBlockRef(1)) + tx3 := createLegacyTx(repo.ChainTag(), 1, 0, 1, 1, nil, clause, tx.NewBlockRef(1)) expectedErrorMessage = "gas limit reached" if err := flow.Adopt(tx3); err.Error() != expectedErrorMessage { t.Fatalf("Expected error message: '%s', but got: '%s'", expectedErrorMessage, err.Error()) diff --git a/runtime/resolved_tx_test.go b/runtime/resolved_tx_test.go index f9b9a00a2..31880d4d5 100644 --- a/runtime/resolved_tx_test.go +++ b/runtime/resolved_tx_test.go @@ -76,33 +76,52 @@ func (tr *testResolvedTransaction) currentState() *state.State { } func (tr *testResolvedTransaction) TestResolveTransaction() { - txBuild := func() *tx.LegacyBuilder { - return txBuilder(tr.repo.ChainTag()) + legacyTxBuild := func() *tx.LegacyBuilder { + return legacyTxBuilder(tr.repo.ChainTag()) + } + dynFeeTxBuild := func() *tx.DynFeeBuilder { + return dynFeeTxBuilder(tr.repo.ChainTag()) } - _, err := runtime.ResolveTransaction(txBuild().Build()) + _, err := runtime.ResolveTransaction(legacyTxBuild().Build()) + tr.assert.Equal(secp256k1.ErrInvalidSignatureLen.Error(), err.Error()) + _, err = runtime.ResolveTransaction(dynFeeTxBuild().Build()) tr.assert.Equal(secp256k1.ErrInvalidSignatureLen.Error(), err.Error()) - _, err = runtime.ResolveTransaction(txSign(txBuild().Gas(21000 - 1))) + _, err = runtime.ResolveTransaction(txSign(legacyTxBuild().Gas(21000 - 1).Build())) + tr.assert.NotNil(err) + _, err = runtime.ResolveTransaction(txSign(dynFeeTxBuild().Gas(21000 - 1).Build())) tr.assert.NotNil(err) address := thor.BytesToAddress([]byte("addr")) - _, err = runtime.ResolveTransaction(txSign(txBuild().Clause(tx.NewClause(&address).WithValue(big.NewInt(-10)).WithData(nil)))) + _, err = runtime.ResolveTransaction(txSign(legacyTxBuild().Clause(tx.NewClause(&address).WithValue(big.NewInt(-10)).WithData(nil)).Build())) + tr.assert.NotNil(err) + _, err = runtime.ResolveTransaction(txSign(dynFeeTxBuild().Clause(tx.NewClause(&address).WithValue(big.NewInt(-10)).WithData(nil)).Build())) tr.assert.NotNil(err) - _, err = runtime.ResolveTransaction(txSign(txBuild(). + _, err = runtime.ResolveTransaction(txSign(legacyTxBuild(). Clause(tx.NewClause(&address).WithValue(math.MaxBig256).WithData(nil)). - Clause(tx.NewClause(&address).WithValue(math.MaxBig256).WithData(nil)), + Clause(tx.NewClause(&address).WithValue(math.MaxBig256).WithData(nil)).Build(), + )) + tr.assert.NotNil(err) + _, err = runtime.ResolveTransaction(txSign(dynFeeTxBuild(). + Clause(tx.NewClause(&address).WithValue(math.MaxBig256).WithData(nil)). + Clause(tx.NewClause(&address).WithValue(math.MaxBig256).WithData(nil)).Build(), )) tr.assert.NotNil(err) - _, err = runtime.ResolveTransaction(txSign(txBuild())) + _, err = runtime.ResolveTransaction(txSign(legacyTxBuild().Build())) + tr.assert.Nil(err) + _, err = runtime.ResolveTransaction(txSign(dynFeeTxBuild().Build())) tr.assert.Nil(err) } func (tr *testResolvedTransaction) TestCommonTo() { - txBuild := func() *tx.LegacyBuilder { - return txBuilder(tr.repo.ChainTag()) + legacyTxBuild := func() *tx.LegacyBuilder { + return legacyTxBuilder(tr.repo.ChainTag()) + } + dynFeeTxBuild := func() *tx.DynFeeBuilder { + return dynFeeTxBuilder(tr.repo.ChainTag()) } commonTo := func(tx *tx.Transaction, assert func(interface{}, ...interface{}) bool) { @@ -114,26 +133,34 @@ func (tr *testResolvedTransaction) TestCommonTo() { assert(to) } - commonTo(txSign(txBuild()), tr.assert.Nil) + commonTo(txSign(legacyTxBuild().Build()), tr.assert.Nil) + commonTo(txSign(dynFeeTxBuild().Build()), tr.assert.Nil) - commonTo(txSign(txBuild().Clause(tx.NewClause(nil))), tr.assert.Nil) + commonTo(txSign(legacyTxBuild().Clause(tx.NewClause(nil)).Build()), tr.assert.Nil) + commonTo(txSign(dynFeeTxBuild().Clause(tx.NewClause(nil)).Build()), tr.assert.Nil) - commonTo(txSign(txBuild().Clause(clause()).Clause(tx.NewClause(nil))), tr.assert.Nil) + commonTo(txSign(legacyTxBuild().Clause(clause()).Clause(tx.NewClause(nil)).Build()), tr.assert.Nil) + commonTo(txSign(dynFeeTxBuild().Clause(clause()).Clause(tx.NewClause(nil)).Build()), tr.assert.Nil) address := thor.BytesToAddress([]byte("addr1")) - commonTo(txSign(txBuild(). + commonTo(txSign(legacyTxBuild(). + Clause(clause()). + Clause(tx.NewClause(&address)).Build(), + ), tr.assert.Nil) + commonTo(txSign(dynFeeTxBuild(). Clause(clause()). - Clause(tx.NewClause(&address)), + Clause(tx.NewClause(&address)).Build(), ), tr.assert.Nil) - commonTo(txSign(txBuild().Clause(clause())), tr.assert.NotNil) + commonTo(txSign(legacyTxBuild().Clause(clause()).Build()), tr.assert.NotNil) + commonTo(txSign(dynFeeTxBuild().Clause(clause()).Build()), tr.assert.NotNil) } func (tr *testResolvedTransaction) TestBuyGas() { state := tr.currentState() txBuild := func() *tx.LegacyBuilder { - return txBuilder(tr.repo.ChainTag()) + return legacyTxBuilder(tr.repo.ChainTag()) } targetTime := tr.repo.BestBlockSummary().Header.Timestamp() + thor.BlockInterval @@ -151,7 +178,7 @@ func (tr *testResolvedTransaction) TestBuyGas() { tr.assert.Equal( genesis.DevAccounts()[0].Address, - buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))))), + buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))).Build())), ) bind := builtin.Prototype.Native(state).Bind(genesis.DevAccounts()[1].Address) @@ -159,14 +186,14 @@ func (tr *testResolvedTransaction) TestBuyGas() { bind.AddUser(genesis.DevAccounts()[0].Address, targetTime) tr.assert.Equal( genesis.DevAccounts()[1].Address, - buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))))), + buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))).Build())), ) bind.Sponsor(genesis.DevAccounts()[2].Address, true) bind.SelectSponsor(genesis.DevAccounts()[2].Address) tr.assert.Equal( genesis.DevAccounts()[2].Address, - buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))))), + buyGas(txSign(txBuild().Clause(clause().WithValue(big.NewInt(100))).Build())), ) } @@ -175,7 +202,7 @@ func clause() *tx.Clause { return tx.NewClause(&address).WithData(nil) } -func txBuilder(tag byte) *tx.LegacyBuilder { +func legacyTxBuilder(tag byte) *tx.LegacyBuilder { return new(tx.LegacyBuilder). GasPriceCoef(1). Gas(1000000). @@ -184,7 +211,15 @@ func txBuilder(tag byte) *tx.LegacyBuilder { ChainTag(tag) } -func txSign(builder *tx.LegacyBuilder) *tx.Transaction { - transaction := builder.Build() - return tx.MustSign(transaction, genesis.DevAccounts()[0].PrivateKey) +func dynFeeTxBuilder(tag byte) *tx.DynFeeBuilder { + return new(tx.DynFeeBuilder). + MaxFeePerGas(big.NewInt(1)). + Gas(1000000). + Expiration(100). + Nonce(1). + ChainTag(tag) +} + +func txSign(trx *tx.Transaction) *tx.Transaction { + return tx.MustSign(trx, genesis.DevAccounts()[0].PrivateKey) } diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 00fb141ae..72f51a833 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -390,7 +390,7 @@ func TestCall(t *testing.T) { assert.Nil(t, err) } -func GetMockTx(repo *chain.Repository, t *testing.T) tx.Transaction { +func getMockTx(repo *chain.Repository, txType int, t *testing.T) *tx.Transaction { var blockRef = tx.NewBlockRef(0) var chainTag = repo.ChainTag() var expiration = uint32(10) @@ -411,7 +411,7 @@ func GetMockTx(repo *chain.Repository, t *testing.T) tx.Transaction { } tx = tx.WithSignature(sig) - return *tx + return tx } func GetMockFailedTx() tx.Transaction { @@ -467,15 +467,20 @@ func TestExecuteTransaction(t *testing.T) { originEnergy.SetString("9000000000000000000000000000000000000", 10) state.SetEnergy(origin.Address, originEnergy, 0) - tx := GetMockTx(repo, t) + txs := []*tx.Transaction{ + getMockTx(repo, tx.LegacyTxType, t), + getMockTx(repo, tx.DynamicFeeTxType, t), + } - rt := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{}, thor.NoFork) + for _, trx := range txs { + rt := runtime.New(repo.NewChain(b0.Header().ID()), state, &xenv.BlockContext{}, thor.NoFork) - receipt, err := rt.ExecuteTransaction(&tx) - if err != nil { - t.Fatal(err) + receipt, err := rt.ExecuteTransaction(trx) + if err != nil { + t.Fatal(err) + } + _ = receipt } - _ = receipt } func TestExecuteTransactionFailure(t *testing.T) { diff --git a/tx/signer_test.go b/tx/signer_test.go index 35f9c9082..452f6039a 100644 --- a/tx/signer_test.go +++ b/tx/signer_test.go @@ -19,24 +19,29 @@ func TestSign(t *testing.T) { pk, err := crypto.GenerateKey() assert.NoError(t, err) - tx := new(LegacyBuilder).Build() - - // Sign the transaction - signedTx, err := Sign(tx, pk) - assert.NoError(t, err) - - // Verify the transaction was signed - assert.NotNil(t, signedTx) - - // Verify address from Origin - addr, err := signedTx.Origin() - require.NoError(t, err) - assert.Equal(t, thor.Address(crypto.PubkeyToAddress(pk.PublicKey)), addr) - - // Verify the delegator - delegator, err := signedTx.Delegator() - require.NoError(t, err) - assert.Nil(t, delegator) + txs := []*Transaction{ + new(LegacyBuilder).Build(), + new(DynFeeBuilder).Build(), + } + + for _, tx := range txs { + // Sign the transaction + signedTx, err := Sign(tx, pk) + assert.NoError(t, err) + + // Verify the transaction was signed + assert.NotNil(t, signedTx) + + // Verify address from Origin + addr, err := signedTx.Origin() + require.NoError(t, err) + assert.Equal(t, thor.Address(crypto.PubkeyToAddress(pk.PublicKey)), addr) + + // Verify the delegator + delegator, err := signedTx.Delegator() + require.NoError(t, err) + assert.Nil(t, delegator) + } } func TestSignDelegated(t *testing.T) { @@ -47,30 +52,35 @@ func TestSignDelegated(t *testing.T) { originPK, err := crypto.GenerateKey() assert.NoError(t, err) - tx := new(LegacyBuilder).Build() - - // Feature not enabled - signedTx, err := SignDelegated(tx, originPK, delegatorPK) - assert.ErrorContains(t, err, "transaction delegated feature is not enabled") - assert.Nil(t, signedTx) - - // enable the feature - var features Features - features.SetDelegated(true) - tx = new(LegacyBuilder).Features(features).Build() - - // Sign the transaction as a delegator - signedTx, err = SignDelegated(tx, originPK, delegatorPK) - assert.NoError(t, err) - assert.NotNil(t, signedTx) - - // Verify address from Origin - origin, err := signedTx.Origin() - require.NoError(t, err) - assert.Equal(t, thor.Address(crypto.PubkeyToAddress(originPK.PublicKey)), origin) - - // Verify the delegator - delegator, err := signedTx.Delegator() - require.NoError(t, err) - assert.Equal(t, thor.Address(crypto.PubkeyToAddress(delegatorPK.PublicKey)), *delegator) + txs := []*Transaction{ + new(LegacyBuilder).Build(), + new(DynFeeBuilder).Build(), + } + + for _, tx := range txs { + // Feature not enabled + signedTx, err := SignDelegated(tx, originPK, delegatorPK) + assert.ErrorContains(t, err, "transaction delegated feature is not enabled") + assert.Nil(t, signedTx) + + // enable the feature + var features Features + features.SetDelegated(true) + tx = new(LegacyBuilder).Features(features).Build() + + // Sign the transaction as a delegator + signedTx, err = SignDelegated(tx, originPK, delegatorPK) + assert.NoError(t, err) + assert.NotNil(t, signedTx) + + // Verify address from Origin + origin, err := signedTx.Origin() + require.NoError(t, err) + assert.Equal(t, thor.Address(crypto.PubkeyToAddress(originPK.PublicKey)), origin) + + // Verify the delegator + delegator, err := signedTx.Delegator() + require.NoError(t, err) + assert.Equal(t, thor.Address(crypto.PubkeyToAddress(delegatorPK.PublicKey)), *delegator) + } } diff --git a/tx/transaction_test.go b/tx/transaction_test.go index 6910bfaee..b40422750 100644 --- a/tx/transaction_test.go +++ b/tx/transaction_test.go @@ -190,7 +190,7 @@ func TestEvaluateWork(t *testing.T) { } } -func LegacyTx(t *testing.T) { +func TestLegacyTx(t *testing.T) { to, _ := thor.ParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed") trx := new(tx.LegacyBuilder).ChainTag(1). BlockRef(tx.BlockRef{0, 0, 0, 0, 0xaa, 0xbb, 0xcc, 0xdd}).