From 1adc32865ef59f9157e2578e2739e5671d878aee Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 10 Jan 2024 13:52:05 +0100 Subject: [PATCH 01/53] E fork scaffolding --- node/node.go | 3 + version/constants.go | 13 ++ vms/avm/block/executor/block_test.go | 140 +++++++++++++++++- vms/avm/block/executor/manager_test.go | 25 +++- vms/avm/config/config.go | 7 + vms/avm/environment_test.go | 3 + vms/avm/index_test.go | 17 ++- vms/avm/service_test.go | 36 ++++- .../txs/executor/syntactic_verifier_test.go | 3 + vms/avm/vm_regression_test.go | 7 +- vms/avm/vm_test.go | 24 ++- vms/platformvm/block/builder/helpers_test.go | 2 + vms/platformvm/block/executor/helpers_test.go | 2 + vms/platformvm/config/config.go | 7 + vms/platformvm/txs/executor/helpers_test.go | 1 + .../executor/staker_tx_verification_test.go | 14 ++ .../txs/executor/standard_tx_executor_test.go | 14 ++ vms/platformvm/validator_set_property_test.go | 1 + vms/platformvm/vm_regression_test.go | 1 + vms/platformvm/vm_test.go | 8 + 20 files changed, 305 insertions(+), 23 deletions(-) diff --git a/node/node.go b/node/node.go index 45e2f6a506e..0c61b0ba848 100644 --- a/node/node.go +++ b/node/node.go @@ -1078,6 +1078,7 @@ func (n *Node) initVMs() error { }) durangoTime := version.GetDurangoTime(n.Config.NetworkID) + eForkTime := version.GetEForkTime(n.Config.NetworkID) if err := txs.InitCodec(durangoTime); err != nil { return err } @@ -1120,6 +1121,7 @@ func (n *Node) initVMs() error { BanffTime: version.GetBanffTime(n.Config.NetworkID), CortinaTime: version.GetCortinaTime(n.Config.NetworkID), DurangoTime: durangoTime, + EForkTime: eForkTime, UseCurrentHeight: n.Config.UseCurrentHeight, }, }), @@ -1128,6 +1130,7 @@ func (n *Node) initVMs() error { TxFee: n.Config.TxFee, CreateAssetTxFee: n.Config.CreateAssetTxFee, DurangoTime: durangoTime, + EForkTime: eForkTime, }, }), vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), diff --git a/version/constants.go b/version/constants.go index 053a57a4585..4a4187bd277 100644 --- a/version/constants.go +++ b/version/constants.go @@ -109,6 +109,12 @@ var ( constants.MainnetID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), constants.FujiID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), } + + EForkTimes = map[uint32]time.Time{ + constants.MainnetID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), + constants.FujiID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), + } + TempForkTime = time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC) ) func init() { @@ -204,6 +210,13 @@ func GetDurangoTime(networkID uint32) time.Time { return DefaultUpgradeTime } +func GetEForkTime(networkID uint32) time.Time { + if upgradeTime, exists := EForkTimes[networkID]; exists { + return upgradeTime + } + return TempForkTime +} + func GetCompatibility(networkID uint32) Compatibility { return NewCompatibility( CurrentApp, diff --git a/vms/avm/block/executor/block_test.go b/vms/avm/block/executor/block_test.go index 0b6738822c6..c44a6938956 100644 --- a/vms/avm/block/executor/block_test.go +++ b/vms/avm/block/executor/block_test.go @@ -23,6 +23,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" + "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/metrics" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" @@ -46,6 +47,12 @@ func TestBlockVerify(t *testing.T) { b := &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{}, }, } @@ -63,8 +70,15 @@ func TestBlockVerify(t *testing.T) { mockBlock.EXPECT().ID().Return(ids.Empty).AnyTimes() mockBlock.EXPECT().MerkleRoot().Return(ids.GenerateTestID()).AnyTimes() return &Block{ - Block: mockBlock, - manager: &manager{}, + Block: mockBlock, + manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, + }, } }, expectedErr: ErrUnexpectedMerkleRoot, @@ -83,6 +97,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, clk: clk, }, } @@ -100,6 +120,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{}, clk: &mockable.Clock{}, }, @@ -126,6 +152,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), blkIDToState: map[ids.ID]*blockState{}, @@ -158,6 +190,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, state: mockState, blkIDToState: map[ids.ID]*blockState{}, clk: &mockable.Clock{}, @@ -194,6 +232,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, state: mockState, blkIDToState: map[ids.ID]*blockState{}, clk: &mockable.Clock{}, @@ -233,6 +277,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ parentID: { onAcceptState: mockParentState, @@ -280,6 +330,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), blkIDToState: map[ids.ID]*blockState{ @@ -332,7 +388,12 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), - backend: &executor.Backend{}, + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ parentID: { onAcceptState: mockParentState, @@ -410,7 +471,12 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), - backend: &executor.Backend{}, + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ parentID: { onAcceptState: mockParentState, @@ -468,7 +534,12 @@ func TestBlockVerify(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ - backend: &executor.Backend{}, + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ parentID: { onAcceptState: mockParentState, @@ -520,7 +591,12 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ mempool: mockMempool, metrics: metrics.NewMockMetrics(ctrl), - backend: &executor.Backend{}, + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ parentID: { onAcceptState: mockParentState, @@ -598,6 +674,10 @@ func TestBlockAccept(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, blkIDToState: map[ids.ID]*blockState{}, }, @@ -632,6 +712,10 @@ func TestBlockAccept(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -676,6 +760,10 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -724,6 +812,10 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -775,6 +867,10 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -872,6 +968,10 @@ func TestBlockReject(t *testing.T) { metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ Bootstrapped: true, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, Ctx: &snow.Context{ Log: logging.NoLog{}, }, @@ -933,6 +1033,10 @@ func TestBlockReject(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, state: mockState, blkIDToState: map[ids.ID]*blockState{ @@ -982,6 +1086,12 @@ func TestBlockStatus(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, lastAccepted: blockID, }, } @@ -997,6 +1107,12 @@ func TestBlockStatus(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{ blockID: {}, }, @@ -1018,6 +1134,12 @@ func TestBlockStatus(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{}, state: mockState, }, @@ -1038,6 +1160,12 @@ func TestBlockStatus(t *testing.T) { return &Block{ Block: mockBlock, manager: &manager{ + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, blkIDToState: map[ids.ID]*blockState{}, state: mockState, }, diff --git a/vms/avm/block/executor/manager_test.go b/vms/avm/block/executor/manager_test.go index 012428d582e..89b547eed96 100644 --- a/vms/avm/block/executor/manager_test.go +++ b/vms/avm/block/executor/manager_test.go @@ -14,7 +14,9 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" + "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" @@ -124,7 +126,12 @@ func TestManagerVerifyTx(t *testing.T) { }, managerF: func(ctrl *gomock.Controller) *manager { return &manager{ - backend: &executor.Backend{}, + backend: &executor.Backend{ + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + }, } }, expectedErr: ErrChainNotSynced, @@ -142,6 +149,10 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, } }, @@ -170,6 +181,10 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, state: state, lastAccepted: lastAcceptedID, @@ -202,6 +217,10 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, state: state, lastAccepted: lastAcceptedID, @@ -234,6 +253,10 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, + Config: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }, state: state, lastAccepted: lastAcceptedID, diff --git a/vms/avm/config/config.go b/vms/avm/config/config.go index df6e4f7de2a..b4da6e3781e 100644 --- a/vms/avm/config/config.go +++ b/vms/avm/config/config.go @@ -15,4 +15,11 @@ type Config struct { // Time of the Durango network upgrade DurangoTime time.Time + + // Time of the E network upgrade + EForkTime time.Time +} + +func (c *Config) IsEForkActivated(timestamp time.Time) bool { + return !timestamp.Before(c.EForkTime) } diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 236c2087579..00a1b2725e4 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -29,6 +29,7 @@ import ( "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/sampler" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block/executor" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" @@ -149,6 +150,8 @@ func setup(tb testing.TB, c *envConfig) *environment { vmStaticConfig := config.Config{ TxFee: testTxFee, CreateAssetTxFee: testTxFee, + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, } if c.vmStaticConfig != nil { vmStaticConfig = *c.vmStaticConfig diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 03a2fd863c6..642410951c9 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -6,6 +6,7 @@ package avm import ( "context" "testing" + "time" "github.com/prometheus/client_golang/prometheus" @@ -20,6 +21,7 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -31,7 +33,10 @@ func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -75,7 +80,10 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -123,7 +131,10 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index c659b8e9de9..62f81d08f48 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -34,6 +34,7 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/json" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" "github.com/ava-labs/avalanchego/vms/avm/config" @@ -703,7 +704,10 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -819,7 +823,10 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -918,7 +925,10 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1056,7 +1066,10 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1159,7 +1172,10 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1305,7 +1321,10 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1405,7 +1424,10 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, diff --git a/vms/avm/txs/executor/syntactic_verifier_test.go b/vms/avm/txs/executor/syntactic_verifier_test.go index 108ac9e94a6..3b5c05d42d0 100644 --- a/vms/avm/txs/executor/syntactic_verifier_test.go +++ b/vms/avm/txs/executor/syntactic_verifier_test.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" @@ -30,6 +31,8 @@ var ( feeConfig = config.Config{ TxFee: 2, CreateAssetTxFee: 3, + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, } ) diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index c6ac40df845..1e4720f80fe 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -6,12 +6,14 @@ package avm import ( "context" "testing" + "time" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -24,7 +26,10 @@ func TestVerifyFxUsage(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) env.vm.ctx.Lock.Unlock() defer func() { diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index d8aeaf3b874..f7c7d11af0e 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -7,6 +7,7 @@ import ( "context" "math" "testing" + "time" "github.com/stretchr/testify/require" @@ -19,6 +20,7 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" @@ -132,7 +134,10 @@ func TestIssueNFT(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) env.vm.ctx.Lock.Unlock() defer func() { @@ -233,7 +238,10 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -520,7 +528,10 @@ func TestIssueImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -620,8 +631,11 @@ func TestForceAcceptImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, - notLinearized: true, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, + }, + notLinearized: true, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index fa7339be6fd..7d84060b134 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -298,6 +298,8 @@ func defaultConfig() *config.Config { ApricotPhase3Time: defaultValidateEndTime, ApricotPhase5Time: defaultValidateEndTime, BanffTime: time.Time{}, // neglecting fork ordering this for package tests + DurangoTime: time.Time{}, + EForkTime: mockable.MaxTime, } } diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index 5e7b5a3fce1..848cbdb5c62 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -316,6 +316,8 @@ func defaultConfig() *config.Config { ApricotPhase3Time: defaultValidateEndTime, ApricotPhase5Time: defaultValidateEndTime, BanffTime: mockable.MaxTime, + DurangoTime: mockable.MaxTime, + EForkTime: mockable.MaxTime, } } diff --git a/vms/platformvm/config/config.go b/vms/platformvm/config/config.go index 50628c422af..292981ddc02 100644 --- a/vms/platformvm/config/config.go +++ b/vms/platformvm/config/config.go @@ -107,6 +107,9 @@ type Config struct { // Time of the Durango network upgrade DurangoTime time.Time + // Time of the E network upgrade + EForkTime time.Time + // UseCurrentHeight forces [GetMinimumHeight] to return the current height // of the P-Chain instead of the oldest block in the [recentlyAccepted] // window. @@ -137,6 +140,10 @@ func (c *Config) IsDurangoActivated(timestamp time.Time) bool { return !timestamp.Before(c.DurangoTime) } +func (c *Config) IsEForkActivated(timestamp time.Time) bool { + return !timestamp.Before(c.EForkTime) +} + func (c *Config) GetCreateBlockchainTxFee(timestamp time.Time) uint64 { if c.IsApricotPhase3Activated(timestamp) { return c.CreateBlockchainTxFee diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index 1ea645efcfb..7f90b6ab785 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -284,6 +284,7 @@ func defaultConfig(postBanff, postCortina, postDurango bool) *config.Config { BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, + EForkTime: mockable.MaxTime, } } diff --git a/vms/platformvm/txs/executor/staker_tx_verification_test.go b/vms/platformvm/txs/executor/staker_tx_verification_test.go index b59daf0da2b..204ed382a2a 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification_test.go +++ b/vms/platformvm/txs/executor/staker_tx_verification_test.go @@ -113,6 +113,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, } }, @@ -134,6 +135,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, } @@ -159,6 +161,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ CortinaTime: activeForkTime, DurangoTime: mockable.MaxTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -185,6 +188,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -214,6 +218,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -243,6 +248,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -273,6 +279,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -306,6 +313,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -339,6 +347,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -374,6 +383,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -403,6 +413,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Ctx: ctx, Config: &config.Config{ DurangoTime: activeForkTime, // activate latest fork + EForkTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -449,6 +460,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ AddSubnetValidatorFee: 1, DurangoTime: activeForkTime, // activate latest fork, + EForkTime: mockable.MaxTime, }, Ctx: ctx, Bootstrapped: bootstrapped, @@ -495,6 +507,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ CortinaTime: activeForkTime, DurangoTime: mockable.MaxTime, + EForkTime: mockable.MaxTime, AddSubnetValidatorFee: 1, }, Ctx: ctx, @@ -547,6 +560,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ AddSubnetValidatorFee: 1, DurangoTime: activeForkTime, // activate latest fork, + EForkTime: mockable.MaxTime, }, Ctx: ctx, Bootstrapped: bootstrapped, diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index a86c579fee7..de0e3eebecc 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -21,6 +21,7 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/platformvm/config" @@ -1150,6 +1151,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1177,6 +1179,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1204,6 +1207,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1234,6 +1238,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1262,6 +1267,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1289,6 +1295,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1318,6 +1325,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1350,6 +1358,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1507,6 +1516,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1533,6 +1543,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1561,6 +1572,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, MaxStakeDuration: math.MaxInt64, + EForkTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1593,6 +1605,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, MaxStakeDuration: math.MaxInt64, }, Bootstrapped: &utils.Atomic[bool]{}, @@ -1631,6 +1644,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, MaxStakeDuration: math.MaxInt64, }, Bootstrapped: &utils.Atomic[bool]{}, diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index 5ca5bfd6c24..c2894e594f7 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -730,6 +730,7 @@ func buildVM(t *testing.T) (*VM, ids.ID, error) { ApricotPhase5Time: forkTime, BanffTime: forkTime, CortinaTime: forkTime, + EForkTime: mockable.MaxTime, }} vm.clock.Set(forkTime.Add(time.Second)) diff --git a/vms/platformvm/vm_regression_test.go b/vms/platformvm/vm_regression_test.go index 36186ec32ae..a82cf6f76c6 100644 --- a/vms/platformvm/vm_regression_test.go +++ b/vms/platformvm/vm_regression_test.go @@ -373,6 +373,7 @@ func TestUnverifiedParentPanicRegression(t *testing.T) { BanffTime: latestForkTime, CortinaTime: mockable.MaxTime, DurangoTime: mockable.MaxTime, + EForkTime: mockable.MaxTime, }} ctx := snowtest.Context(t, snowtest.PChainID) diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 23e88a64636..6c8733550d0 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -252,6 +252,7 @@ func defaultVM(t *testing.T, fork activeFork) (*VM, database.Database, *mutableS BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, + EForkTime: mockable.MaxTime, }} db := memdb.New() @@ -1135,6 +1136,7 @@ func TestRestartFullyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1222,6 +1224,7 @@ func TestRestartFullyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1272,6 +1275,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1613,6 +1617,7 @@ func TestUnverifiedParent(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1776,6 +1781,7 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1824,6 +1830,7 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1923,6 +1930,7 @@ func TestUptimeDisallowedAfterNeverConnecting(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, + EForkTime: mockable.MaxTime, }} ctx := snowtest.Context(t, snowtest.PChainID) From e00d7c9953990f7758e3fb8aa201252e641252d4 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 29 Jan 2024 13:36:20 +0100 Subject: [PATCH 02/53] drop temporary fork time --- version/constants.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/version/constants.go b/version/constants.go index a535f2a0759..f90e1188ab3 100644 --- a/version/constants.go +++ b/version/constants.go @@ -135,7 +135,6 @@ var ( constants.MainnetID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), constants.FujiID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), } - TempForkTime = time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC) ) func init() { @@ -263,7 +262,7 @@ func GetEForkTime(networkID uint32) time.Time { if upgradeTime, exists := EForkTimes[networkID]; exists { return upgradeTime } - return TempForkTime + return DefaultUpgradeTime } func GetCompatibility(networkID uint32) Compatibility { From f832034e7aadba290a87c2a88d6f40fa027919cb Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 1 Feb 2024 22:38:42 +0100 Subject: [PATCH 03/53] nits --- node/node.go | 6 +- version/constants.go | 6 +- vms/avm/block/executor/block_test.go | 96 +++++++++---------- vms/avm/block/executor/manager_test.go | 20 ++-- vms/avm/config/config.go | 6 +- vms/avm/environment_test.go | 2 +- vms/avm/index_test.go | 12 +-- vms/avm/service_test.go | 28 +++--- .../txs/executor/syntactic_verifier_test.go | 2 +- vms/avm/vm_regression_test.go | 4 +- vms/avm/vm_test.go | 16 ++-- vms/platformvm/block/builder/helpers_test.go | 2 +- vms/platformvm/block/executor/helpers_test.go | 2 +- vms/platformvm/config/config.go | 4 +- vms/platformvm/txs/executor/helpers_test.go | 2 +- .../executor/staker_tx_verification_test.go | 52 +++++----- .../txs/executor/standard_tx_executor_test.go | 86 ++++++++--------- vms/platformvm/validator_set_property_test.go | 2 +- vms/platformvm/vm_regression_test.go | 2 +- vms/platformvm/vm_test.go | 16 ++-- 20 files changed, 183 insertions(+), 183 deletions(-) diff --git a/node/node.go b/node/node.go index a9cfc4e951e..88c14ba3a08 100644 --- a/node/node.go +++ b/node/node.go @@ -1182,7 +1182,7 @@ func (n *Node) initVMs() error { } durangoTime := version.GetDurangoTime(n.Config.NetworkID) - eForkTime := version.GetEForkTime(n.Config.NetworkID) + eUpgradeTime := version.GetEUpgradeTime(n.Config.NetworkID) if err := txs.InitCodec(durangoTime); err != nil { return err } @@ -1225,7 +1225,7 @@ func (n *Node) initVMs() error { BanffTime: version.GetBanffTime(n.Config.NetworkID), CortinaTime: version.GetCortinaTime(n.Config.NetworkID), DurangoTime: durangoTime, - EForkTime: eForkTime, + EUpgradeTime: eUpgradeTime, UseCurrentHeight: n.Config.UseCurrentHeight, }, }), @@ -1234,7 +1234,7 @@ func (n *Node) initVMs() error { TxFee: n.Config.TxFee, CreateAssetTxFee: n.Config.CreateAssetTxFee, DurangoTime: durangoTime, - EForkTime: eForkTime, + EUpgradeTime: eUpgradeTime, }, }), n.VMManager.RegisterFactory(context.TODO(), constants.EVMID, &coreth.Factory{}), diff --git a/version/constants.go b/version/constants.go index 494448d0830..153c87a3381 100644 --- a/version/constants.go +++ b/version/constants.go @@ -142,7 +142,7 @@ var ( constants.FujiID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), } - EForkTimes = map[uint32]time.Time{ + EUpgradeTimes = map[uint32]time.Time{ constants.MainnetID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), constants.FujiID: time.Date(10000, time.December, 1, 0, 0, 0, 0, time.UTC), } @@ -246,8 +246,8 @@ func GetDurangoTime(networkID uint32) time.Time { return DefaultUpgradeTime } -func GetEForkTime(networkID uint32) time.Time { - if upgradeTime, exists := EForkTimes[networkID]; exists { +func GetEUpgradeTime(networkID uint32) time.Time { + if upgradeTime, exists := EUpgradeTimes[networkID]; exists { return upgradeTime } return DefaultUpgradeTime diff --git a/vms/avm/block/executor/block_test.go b/vms/avm/block/executor/block_test.go index c44a6938956..00d7c89264f 100644 --- a/vms/avm/block/executor/block_test.go +++ b/vms/avm/block/executor/block_test.go @@ -49,8 +49,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{}, @@ -74,8 +74,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, }, @@ -99,8 +99,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, clk: clk, @@ -122,8 +122,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{}, @@ -154,8 +154,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, mempool: mempool, @@ -192,8 +192,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: mockState, @@ -234,8 +234,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: mockState, @@ -279,8 +279,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -332,8 +332,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, mempool: mempool, @@ -390,8 +390,8 @@ func TestBlockVerify(t *testing.T) { metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -473,8 +473,8 @@ func TestBlockVerify(t *testing.T) { metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -536,8 +536,8 @@ func TestBlockVerify(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -593,8 +593,8 @@ func TestBlockVerify(t *testing.T) { metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -675,8 +675,8 @@ func TestBlockAccept(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{}, @@ -713,8 +713,8 @@ func TestBlockAccept(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -761,8 +761,8 @@ func TestBlockAccept(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -813,8 +813,8 @@ func TestBlockAccept(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -868,8 +868,8 @@ func TestBlockAccept(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -969,8 +969,8 @@ func TestBlockReject(t *testing.T) { backend: &executor.Backend{ Bootstrapped: true, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, Ctx: &snow.Context{ Log: logging.NoLog{}, @@ -1034,8 +1034,8 @@ func TestBlockReject(t *testing.T) { Log: logging.NoLog{}, }, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: mockState, @@ -1088,8 +1088,8 @@ func TestBlockStatus(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, lastAccepted: blockID, @@ -1109,8 +1109,8 @@ func TestBlockStatus(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{ @@ -1136,8 +1136,8 @@ func TestBlockStatus(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{}, @@ -1162,8 +1162,8 @@ func TestBlockStatus(t *testing.T) { manager: &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, blkIDToState: map[ids.ID]*blockState{}, diff --git a/vms/avm/block/executor/manager_test.go b/vms/avm/block/executor/manager_test.go index 89b547eed96..f0200f398a6 100644 --- a/vms/avm/block/executor/manager_test.go +++ b/vms/avm/block/executor/manager_test.go @@ -128,8 +128,8 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, } @@ -150,8 +150,8 @@ func TestManagerVerifyTx(t *testing.T) { backend: &executor.Backend{ Bootstrapped: true, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, } @@ -182,8 +182,8 @@ func TestManagerVerifyTx(t *testing.T) { backend: &executor.Backend{ Bootstrapped: true, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: state, @@ -218,8 +218,8 @@ func TestManagerVerifyTx(t *testing.T) { backend: &executor.Backend{ Bootstrapped: true, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: state, @@ -254,8 +254,8 @@ func TestManagerVerifyTx(t *testing.T) { backend: &executor.Backend{ Bootstrapped: true, Config: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }, state: state, diff --git a/vms/avm/config/config.go b/vms/avm/config/config.go index b4da6e3781e..42e37b678a0 100644 --- a/vms/avm/config/config.go +++ b/vms/avm/config/config.go @@ -17,9 +17,9 @@ type Config struct { DurangoTime time.Time // Time of the E network upgrade - EForkTime time.Time + EUpgradeTime time.Time } -func (c *Config) IsEForkActivated(timestamp time.Time) bool { - return !timestamp.Before(c.EForkTime) +func (c *Config) IsEUpgradeActivated(timestamp time.Time) bool { + return !timestamp.Before(c.EUpgradeTime) } diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 00a1b2725e4..5675964d1b7 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -151,7 +151,7 @@ func setup(tb testing.TB, c *envConfig) *environment { TxFee: testTxFee, CreateAssetTxFee: testTxFee, DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, } if c.vmStaticConfig != nil { vmStaticConfig = *c.vmStaticConfig diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 642410951c9..f164481590e 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -34,8 +34,8 @@ func TestIndexTransaction_Ordered(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) defer func() { @@ -81,8 +81,8 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) defer func() { @@ -132,8 +132,8 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) defer func() { diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 62f81d08f48..8a080c6137b 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -705,8 +705,8 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -824,8 +824,8 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -926,8 +926,8 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -1067,8 +1067,8 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -1173,8 +1173,8 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -1322,8 +1322,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -1425,8 +1425,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, diff --git a/vms/avm/txs/executor/syntactic_verifier_test.go b/vms/avm/txs/executor/syntactic_verifier_test.go index 3b5c05d42d0..cc160ed7982 100644 --- a/vms/avm/txs/executor/syntactic_verifier_test.go +++ b/vms/avm/txs/executor/syntactic_verifier_test.go @@ -32,7 +32,7 @@ var ( TxFee: 2, CreateAssetTxFee: 3, DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, } ) diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 1e4720f80fe..2412c4e9a70 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -27,8 +27,8 @@ func TestVerifyFxUsage(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index f7c7d11af0e..a01aefd349d 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -135,8 +135,8 @@ func TestIssueNFT(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) env.vm.ctx.Lock.Unlock() @@ -239,8 +239,8 @@ func TestIssueProperty(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, @@ -529,8 +529,8 @@ func TestIssueImportTx(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, }) defer func() { @@ -632,8 +632,8 @@ func TestForceAcceptImportTx(t *testing.T) { env := setup(t, &envConfig{ vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, }, notLinearized: true, }) diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index 15ca13e2e10..92892df75ae 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -316,7 +316,7 @@ func defaultConfig() *config.Config { ApricotPhase5Time: defaultValidateEndTime, BanffTime: time.Time{}, // neglecting fork ordering this for package tests DurangoTime: time.Time{}, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, } } diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index f134ecd73dd..9b98681c44c 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -344,7 +344,7 @@ func defaultConfig() *config.Config { ApricotPhase5Time: defaultValidateEndTime, BanffTime: mockable.MaxTime, DurangoTime: mockable.MaxTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, } } diff --git a/vms/platformvm/config/config.go b/vms/platformvm/config/config.go index 292981ddc02..0ac37f81f08 100644 --- a/vms/platformvm/config/config.go +++ b/vms/platformvm/config/config.go @@ -108,7 +108,7 @@ type Config struct { DurangoTime time.Time // Time of the E network upgrade - EForkTime time.Time + EUpgradeTime time.Time // UseCurrentHeight forces [GetMinimumHeight] to return the current height // of the P-Chain instead of the oldest block in the [recentlyAccepted] @@ -141,7 +141,7 @@ func (c *Config) IsDurangoActivated(timestamp time.Time) bool { } func (c *Config) IsEForkActivated(timestamp time.Time) bool { - return !timestamp.Before(c.EForkTime) + return !timestamp.Before(c.EUpgradeTime) } func (c *Config) GetCreateBlockchainTxFee(timestamp time.Time) uint64 { diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index ce59a27e146..3d6683529cc 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -308,7 +308,7 @@ func defaultConfig(postBanff, postCortina, postDurango bool) *config.Config { BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, } } diff --git a/vms/platformvm/txs/executor/staker_tx_verification_test.go b/vms/platformvm/txs/executor/staker_tx_verification_test.go index c874e884561..aa602725083 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification_test.go +++ b/vms/platformvm/txs/executor/staker_tx_verification_test.go @@ -112,8 +112,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, } }, @@ -134,8 +134,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, } @@ -161,9 +161,9 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - CortinaTime: activeForkTime, - DurangoTime: mockable.MaxTime, - EForkTime: mockable.MaxTime, + CortinaTime: activeForkTime, + DurangoTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -189,8 +189,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -219,8 +219,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -249,8 +249,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -280,8 +280,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -314,8 +314,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -348,8 +348,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -384,8 +384,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -414,8 +414,8 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { return &Backend{ Ctx: ctx, Config: &config.Config{ - DurangoTime: activeForkTime, // activate latest fork - EForkTime: mockable.MaxTime, + DurangoTime: activeForkTime, // activate latest fork + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: bootstrapped, } @@ -462,7 +462,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ AddSubnetValidatorFee: 1, DurangoTime: activeForkTime, // activate latest fork, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }, Ctx: ctx, Bootstrapped: bootstrapped, @@ -509,7 +509,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ CortinaTime: activeForkTime, DurangoTime: mockable.MaxTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, AddSubnetValidatorFee: 1, }, Ctx: ctx, @@ -562,7 +562,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: &config.Config{ AddSubnetValidatorFee: 1, DurangoTime: activeForkTime, // activate latest fork, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }, Ctx: ctx, Bootstrapped: bootstrapped, diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index aac52b57193..6fd7fd0bc1f 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -1749,10 +1749,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1777,10 +1777,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1806,10 +1806,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1838,10 +1838,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1868,10 +1868,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1897,10 +1897,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1928,10 +1928,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -1962,10 +1962,10 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -2120,10 +2120,10 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -2148,10 +2148,10 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { e := &StandardTxExecutor{ Backend: &Backend{ Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -2181,7 +2181,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, MaxStakeDuration: math.MaxInt64, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, @@ -2215,7 +2215,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, MaxStakeDuration: math.MaxInt64, }, Bootstrapped: &utils.Atomic[bool]{}, @@ -2255,7 +2255,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { BanffTime: env.latestForkTime, CortinaTime: env.latestForkTime, DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, MaxStakeDuration: math.MaxInt64, }, Bootstrapped: &utils.Atomic[bool]{}, diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index 7a879123af2..9a0fd7f8852 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -625,7 +625,7 @@ func buildVM(t *testing.T) (*VM, ids.ID, error) { ApricotPhase5Time: forkTime, BanffTime: forkTime, CortinaTime: forkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} vm.clock.Set(forkTime.Add(time.Second)) diff --git a/vms/platformvm/vm_regression_test.go b/vms/platformvm/vm_regression_test.go index 761a4ad0812..4335ae46003 100644 --- a/vms/platformvm/vm_regression_test.go +++ b/vms/platformvm/vm_regression_test.go @@ -374,7 +374,7 @@ func TestUnverifiedParentPanicRegression(t *testing.T) { BanffTime: latestForkTime, CortinaTime: mockable.MaxTime, DurangoTime: mockable.MaxTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} ctx := snowtest.Context(t, snowtest.PChainID) diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 5af9deb95db..94e158582cc 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -254,7 +254,7 @@ func defaultVM(t *testing.T, fork activeFork) (*VM, database.Database, *mutableS BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} db := memdb.New() @@ -1113,7 +1113,7 @@ func TestRestartFullyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1201,7 +1201,7 @@ func TestRestartFullyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1252,7 +1252,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1594,7 +1594,7 @@ func TestUnverifiedParent(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} initialClkTime := latestForkTime.Add(time.Second) @@ -1755,7 +1755,7 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} firstCtx := snowtest.Context(t, snowtest.PChainID) @@ -1804,7 +1804,7 @@ func TestUptimeDisallowedWithRestart(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} secondCtx := snowtest.Context(t, snowtest.PChainID) @@ -1904,7 +1904,7 @@ func TestUptimeDisallowedAfterNeverConnecting(t *testing.T) { BanffTime: latestForkTime, CortinaTime: latestForkTime, DurangoTime: latestForkTime, - EForkTime: mockable.MaxTime, + EUpgradeTime: mockable.MaxTime, }} ctx := snowtest.Context(t, snowtest.PChainID) From 3daec3411519365d01497e0e7a920e110b2e245d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 8 Feb 2024 23:36:17 +0100 Subject: [PATCH 04/53] cleanup --- vms/platformvm/block/builder/builder_test.go | 18 ++--- vms/platformvm/block/builder/helpers_test.go | 58 ++++++++++++++--- .../block/builder/standard_block_test.go | 2 +- vms/platformvm/block/executor/helpers_test.go | 57 +++++++++++++--- .../block/executor/proposal_block_test.go | 16 ++--- .../block/executor/standard_block_test.go | 14 ++-- .../txs/executor/advance_time_test.go | 22 +++---- .../txs/executor/create_chain_test.go | 10 +-- .../txs/executor/create_subnet_test.go | 2 +- vms/platformvm/txs/executor/export_test.go | 2 +- vms/platformvm/txs/executor/helpers_test.go | 65 +++++++++++++------ vms/platformvm/txs/executor/import_test.go | 2 +- .../txs/executor/proposal_tx_executor_test.go | 8 +-- .../txs/executor/reward_validator_test.go | 12 ++-- .../txs/executor/standard_tx_executor_test.go | 14 ++-- vms/platformvm/vm_test.go | 7 +- 16 files changed, 212 insertions(+), 97 deletions(-) diff --git a/vms/platformvm/block/builder/builder_test.go b/vms/platformvm/block/builder/builder_test.go index 56f189cb986..039bcc92b0c 100644 --- a/vms/platformvm/block/builder/builder_test.go +++ b/vms/platformvm/block/builder/builder_test.go @@ -33,7 +33,7 @@ import ( func TestBuildBlockBasic(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -75,7 +75,7 @@ func TestBuildBlockBasic(t *testing.T) { func TestBuildBlockDoesNotBuildWithEmptyMempool(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -92,7 +92,7 @@ func TestBuildBlockDoesNotBuildWithEmptyMempool(t *testing.T) { func TestBuildBlockShouldReward(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -193,7 +193,7 @@ func TestBuildBlockShouldReward(t *testing.T) { func TestBuildBlockAdvanceTime(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -226,7 +226,7 @@ func TestBuildBlockAdvanceTime(t *testing.T) { func TestBuildBlockForceAdvanceTime(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -280,7 +280,7 @@ func TestBuildBlockForceAdvanceTime(t *testing.T) { func TestBuildBlockDropExpiredStakerTxs(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -383,7 +383,7 @@ func TestBuildBlockDropExpiredStakerTxs(t *testing.T) { func TestBuildBlockInvalidStakingDurations(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -467,7 +467,7 @@ func TestBuildBlockInvalidStakingDurations(t *testing.T) { func TestPreviouslyDroppedTxsCannotBeReAddedToMempool(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -510,7 +510,7 @@ func TestPreviouslyDroppedTxsCannotBeReAddedToMempool(t *testing.T) { func TestNoErrorOnUnexpectedSetPreferenceDuringBootstrapping(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index 92892df75ae..27b6573c05f 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -5,6 +5,7 @@ package builder import ( "context" + "fmt" "testing" "time" @@ -58,8 +59,17 @@ import ( const ( defaultWeight = 10000 trackChecksum = false + + apricotPhase3 activeFork = iota + apricotPhase5 + banffFork + cortinaFork + durangoFork + eUpgradeFork ) +type activeFork uint8 + var ( defaultMinStakingDuration = 24 * time.Hour defaultMaxStakingDuration = 365 * 24 * time.Hour @@ -111,12 +121,12 @@ type environment struct { backend txexecutor.Backend } -func newEnvironment(t *testing.T) *environment { +func newEnvironment(t *testing.T, fork activeFork) *environment { //nolint:unparam require := require.New(t) res := &environment{ isBootstrapped: &utils.Atomic[bool]{}, - config: defaultConfig(), + config: defaultConfig(t, fork), clk: defaultClock(), } res.isBootstrapped.Set(true) @@ -293,7 +303,38 @@ func defaultState( return state } -func defaultConfig() *config.Config { +func defaultConfig(t *testing.T, fork activeFork) *config.Config { + var ( + apricotPhase3Time = mockable.MaxTime + apricotPhase5Time = mockable.MaxTime + banffTime = mockable.MaxTime + cortinaTime = mockable.MaxTime + durangoTime = mockable.MaxTime + eUpgradeTime = mockable.MaxTime + ) + + switch fork { + case eUpgradeFork: + eUpgradeTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case durangoFork: + durangoTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case cortinaFork: + cortinaTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case banffFork: + banffTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case apricotPhase5: + apricotPhase5Time = defaultValidateEndTime + fallthrough + case apricotPhase3: + apricotPhase3Time = defaultValidateEndTime + default: + require.NoError(t, fmt.Errorf("unhandled fork %d", fork)) + } + return &config.Config{ Chains: chains.TestManager, UptimeLockedCalculator: uptime.NewLockedCalculator(), @@ -312,11 +353,12 @@ func defaultConfig() *config.Config { MintingPeriod: 365 * 24 * time.Hour, SupplyCap: 720 * units.MegaAvax, }, - ApricotPhase3Time: defaultValidateEndTime, - ApricotPhase5Time: defaultValidateEndTime, - BanffTime: time.Time{}, // neglecting fork ordering this for package tests - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, + ApricotPhase3Time: apricotPhase3Time, + ApricotPhase5Time: apricotPhase5Time, + BanffTime: banffTime, + CortinaTime: cortinaTime, + DurangoTime: durangoTime, + EUpgradeTime: eUpgradeTime, } } diff --git a/vms/platformvm/block/builder/standard_block_test.go b/vms/platformvm/block/builder/standard_block_test.go index 6064b215311..f286a9191ec 100644 --- a/vms/platformvm/block/builder/standard_block_test.go +++ b/vms/platformvm/block/builder/standard_block_test.go @@ -22,7 +22,7 @@ import ( func TestAtomicTxImports(t *testing.T) { require := require.New(t) - env := newEnvironment(t) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index 9b98681c44c..26eb69ada86 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -61,8 +61,17 @@ const ( defaultWeight = 10000 trackChecksum = false + + apricotPhase3 activeFork = iota + apricotPhase5 + banffFork + cortinaFork + durangoFork + eUpgradeFork ) +type activeFork uint8 + var ( defaultMinStakingDuration = 24 * time.Hour defaultMaxStakingDuration = 365 * 24 * time.Hour @@ -126,10 +135,10 @@ type environment struct { backend *executor.Backend } -func newEnvironment(t *testing.T, ctrl *gomock.Controller) *environment { +func newEnvironment(t *testing.T, ctrl *gomock.Controller, fork activeFork) *environment { res := &environment{ isBootstrapped: &utils.Atomic[bool]{}, - config: defaultConfig(), + config: defaultConfig(t, fork), clk: defaultClock(), } res.isBootstrapped.Set(true) @@ -321,7 +330,38 @@ func defaultState( return state } -func defaultConfig() *config.Config { +func defaultConfig(t *testing.T, fork activeFork) *config.Config { + var ( + apricotPhase3Time = mockable.MaxTime + apricotPhase5Time = mockable.MaxTime + banffTime = mockable.MaxTime + cortinaTime = mockable.MaxTime + durangoTime = mockable.MaxTime + eUpgradeTime = mockable.MaxTime + ) + + switch fork { + case eUpgradeFork: + eUpgradeTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case durangoFork: + durangoTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case cortinaFork: + cortinaTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case banffFork: + banffTime = time.Time{} // neglecting fork ordering this for package tests + fallthrough + case apricotPhase5: + apricotPhase5Time = defaultValidateEndTime + fallthrough + case apricotPhase3: + apricotPhase3Time = defaultValidateEndTime + default: + require.NoError(t, fmt.Errorf("unhandled fork %d", fork)) + } + return &config.Config{ Chains: chains.TestManager, UptimeLockedCalculator: uptime.NewLockedCalculator(), @@ -340,11 +380,12 @@ func defaultConfig() *config.Config { MintingPeriod: 365 * 24 * time.Hour, SupplyCap: 720 * units.MegaAvax, }, - ApricotPhase3Time: defaultValidateEndTime, - ApricotPhase5Time: defaultValidateEndTime, - BanffTime: mockable.MaxTime, - DurangoTime: mockable.MaxTime, - EUpgradeTime: mockable.MaxTime, + ApricotPhase3Time: apricotPhase3Time, + ApricotPhase5Time: apricotPhase5Time, + BanffTime: banffTime, + DurangoTime: durangoTime, + CortinaTime: cortinaTime, + EUpgradeTime: eUpgradeTime, } } diff --git a/vms/platformvm/block/executor/proposal_block_test.go b/vms/platformvm/block/executor/proposal_block_test.go index 33a3877fc24..7476c4f5772 100644 --- a/vms/platformvm/block/executor/proposal_block_test.go +++ b/vms/platformvm/block/executor/proposal_block_test.go @@ -36,7 +36,7 @@ func TestApricotProposalBlockTimeVerification(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - env := newEnvironment(t, ctrl) + env := newEnvironment(t, ctrl, apricotPhase5) // create apricotParentBlk. It's a standard one for simplicity parentHeight := uint64(2022) @@ -139,7 +139,7 @@ func TestBanffProposalBlockTimeVerification(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - env := newEnvironment(t, ctrl) + env := newEnvironment(t, ctrl, banffFork) env.clk.Set(defaultGenesisTime) env.config.BanffTime = time.Time{} // activate Banff env.config.DurangoTime = mockable.MaxTime // deactivate Durango @@ -550,7 +550,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -700,7 +700,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { func TestBanffProposalBlockRemoveSubnetValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -840,7 +840,7 @@ func TestBanffProposalBlockTrackedSubnet(t *testing.T) { for _, tracked := range []bool{true, false} { t.Run(fmt.Sprintf("tracked %t", tracked), func(ts *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -943,7 +943,7 @@ func TestBanffProposalBlockTrackedSubnet(t *testing.T) { func TestBanffProposalBlockDelegatorStakerWeight(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff // Case: Timestamp is after next validator start time @@ -1125,7 +1125,7 @@ func TestBanffProposalBlockDelegatorStakerWeight(t *testing.T) { func TestBanffProposalBlockDelegatorStakers(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff // Case: Timestamp is after next validator start time @@ -1307,7 +1307,7 @@ func TestBanffProposalBlockDelegatorStakers(t *testing.T) { func TestAddValidatorProposalBlock(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, apricotPhase5) env.config.BanffTime = time.Time{} // activate Banff env.config.DurangoTime = time.Time{} // activate Durango diff --git a/vms/platformvm/block/executor/standard_block_test.go b/vms/platformvm/block/executor/standard_block_test.go index 3e0122c9123..54b45b0ab7c 100644 --- a/vms/platformvm/block/executor/standard_block_test.go +++ b/vms/platformvm/block/executor/standard_block_test.go @@ -30,7 +30,7 @@ func TestApricotStandardBlockTimeVerification(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - env := newEnvironment(t, ctrl) + env := newEnvironment(t, ctrl, apricotPhase5) // setup and store parent block // it's a standard block for simplicity @@ -83,7 +83,7 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - env := newEnvironment(t, ctrl) + env := newEnvironment(t, ctrl, banffFork) now := env.clk.Time() env.clk.Set(now) env.config.BanffTime = time.Time{} // activate Banff @@ -291,7 +291,7 @@ func TestBanffStandardBlockTimeVerification(t *testing.T) { func TestBanffStandardBlockUpdatePrimaryNetworkStakers(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff // Case: Timestamp is after next validator start time @@ -493,7 +493,7 @@ func TestBanffStandardBlockUpdateStakers(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -592,7 +592,7 @@ func TestBanffStandardBlockUpdateStakers(t *testing.T) { // is after the new timestamp func TestBanffStandardBlockRemoveSubnetValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -688,7 +688,7 @@ func TestBanffStandardBlockTrackedSubnet(t *testing.T) { for _, tracked := range []bool{true, false} { t.Run(fmt.Sprintf("tracked %t", tracked), func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff subnetID := testSubnet1.ID() @@ -748,7 +748,7 @@ func TestBanffStandardBlockTrackedSubnet(t *testing.T) { func TestBanffStandardBlockDelegatorStakerWeight(t *testing.T) { require := require.New(t) - env := newEnvironment(t, nil) + env := newEnvironment(t, nil, banffFork) env.config.BanffTime = time.Time{} // activate Banff // Case: Timestamp is after next validator start time diff --git a/vms/platformvm/txs/executor/advance_time_test.go b/vms/platformvm/txs/executor/advance_time_test.go index b7b636ad6db..eaab7ca0f04 100644 --- a/vms/platformvm/txs/executor/advance_time_test.go +++ b/vms/platformvm/txs/executor/advance_time_test.go @@ -34,7 +34,7 @@ func newAdvanceTimeTx(t testing.TB, timestamp time.Time) (*txs.Tx, error) { // for the primary network func TestAdvanceTimeTxUpdatePrimaryNetworkStakers(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() dummyHeight := uint64(1) @@ -97,7 +97,7 @@ func TestAdvanceTimeTxUpdatePrimaryNetworkStakers(t *testing.T) { // Ensure semantic verification fails when proposed timestamp is at or before current timestamp func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) tx, err := newAdvanceTimeTx(t, env.state.GetTimestamp()) require.NoError(err) @@ -121,7 +121,7 @@ func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) { // Ensure semantic verification fails when proposed timestamp is after next validator set change time func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -154,7 +154,7 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { } // Case: Timestamp is after next validator end time - env = newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env = newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -354,7 +354,7 @@ func TestAdvanceTimeTxUpdateStakers(t *testing.T) { for _, test := range tests { t.Run(test.description, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -457,7 +457,7 @@ func TestAdvanceTimeTxUpdateStakers(t *testing.T) { // is after the new timestamp func TestAdvanceTimeTxRemoveSubnetValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -559,7 +559,7 @@ func TestTrackedSubnet(t *testing.T) { for _, tracked := range []bool{true, false} { t.Run(fmt.Sprintf("tracked %t", tracked), func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() dummyHeight := uint64(1) @@ -627,7 +627,7 @@ func TestTrackedSubnet(t *testing.T) { func TestAdvanceTimeTxDelegatorStakerWeight(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() dummyHeight := uint64(1) @@ -732,7 +732,7 @@ func TestAdvanceTimeTxDelegatorStakerWeight(t *testing.T) { func TestAdvanceTimeTxDelegatorStakers(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() dummyHeight := uint64(1) @@ -826,7 +826,7 @@ func TestAdvanceTimeTxDelegatorStakers(t *testing.T) { func TestAdvanceTimeTxAfterBanff(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() env.clk.Set(defaultGenesisTime) // VM's clock reads the genesis time @@ -858,7 +858,7 @@ func TestAdvanceTimeTxAfterBanff(t *testing.T) { // Ensure marshaling/unmarshaling works func TestAdvanceTimeTxUnmarshal(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/txs/executor/create_chain_test.go b/vms/platformvm/txs/executor/create_chain_test.go index 0342c8dc1cf..bfb8097382d 100644 --- a/vms/platformvm/txs/executor/create_chain_test.go +++ b/vms/platformvm/txs/executor/create_chain_test.go @@ -25,7 +25,7 @@ import ( // Ensure Execute fails when there are not enough control sigs func TestCreateChainTxInsufficientControlSigs(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -58,7 +58,7 @@ func TestCreateChainTxInsufficientControlSigs(t *testing.T) { // Ensure Execute fails when an incorrect control signature is given func TestCreateChainTxWrongControlSig(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -98,7 +98,7 @@ func TestCreateChainTxWrongControlSig(t *testing.T) { // its validator set doesn't exist func TestCreateChainTxNoSuchSubnet(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -130,7 +130,7 @@ func TestCreateChainTxNoSuchSubnet(t *testing.T) { // Ensure valid tx passes semanticVerify func TestCreateChainTxValid(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -187,7 +187,7 @@ func TestCreateChainTxAP3FeeChange(t *testing.T) { t.Run(test.name, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.config.ApricotPhase3Time = ap3Time ins, outs, _, signers, err := env.utxosHandler.Spend(env.state, preFundedKeys, 0, test.fee, ids.ShortEmpty) diff --git a/vms/platformvm/txs/executor/create_subnet_test.go b/vms/platformvm/txs/executor/create_subnet_test.go index 6d968daa4df..a2d59281cc6 100644 --- a/vms/platformvm/txs/executor/create_subnet_test.go +++ b/vms/platformvm/txs/executor/create_subnet_test.go @@ -49,7 +49,7 @@ func TestCreateSubnetTxAP3FeeChange(t *testing.T) { t.Run(test.name, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.config.ApricotPhase3Time = ap3Time env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/txs/executor/export_test.go b/vms/platformvm/txs/executor/export_test.go index d9e0ce07100..12aa12de33e 100644 --- a/vms/platformvm/txs/executor/export_test.go +++ b/vms/platformvm/txs/executor/export_test.go @@ -15,7 +15,7 @@ import ( ) func TestNewExportTx(t *testing.T) { - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index 3d6683529cc..2975d4739f5 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -51,8 +51,17 @@ import ( const ( defaultWeight = 5 * units.MilliAvax trackChecksum = false + + apricotPhase3 activeFork = iota + apricotPhase5 + banffFork + cortinaFork + durangoFork + eUpgradeFork ) +type activeFork uint8 + var ( defaultMinStakingDuration = 24 * time.Hour defaultMaxStakingDuration = 365 * 24 * time.Hour @@ -112,12 +121,12 @@ func (e *environment) SetState(blkID ids.ID, chainState state.Chain) { e.states[blkID] = chainState } -func newEnvironment(t *testing.T, postBanff, postCortina, postDurango bool) *environment { +func newEnvironment(t *testing.T, fork activeFork) *environment { var isBootstrapped utils.Atomic[bool] isBootstrapped.Set(true) - config := defaultConfig(postBanff, postCortina, postDurango) - clk := defaultClock(postBanff || postCortina || postDurango) + config := defaultConfig(t, fork) + clk := defaultClock(fork) baseDB := versiondb.New(memdb.New()) ctx := snowtest.Context(t, snowtest.PChainID) @@ -271,18 +280,36 @@ func defaultState( return state } -func defaultConfig(postBanff, postCortina, postDurango bool) *config.Config { - banffTime := mockable.MaxTime - if postBanff { - banffTime = defaultValidateEndTime.Add(-2 * time.Second) - } - cortinaTime := mockable.MaxTime - if postCortina { - cortinaTime = defaultValidateStartTime.Add(-2 * time.Second) - } - durangoTime := mockable.MaxTime - if postDurango { +func defaultConfig(t *testing.T, fork activeFork) *config.Config { + var ( + apricotPhase3Time = mockable.MaxTime + apricotPhase5Time = mockable.MaxTime + banffTime = mockable.MaxTime + cortinaTime = mockable.MaxTime + durangoTime = mockable.MaxTime + eUpgradeTime = mockable.MaxTime + ) + + switch fork { + case eUpgradeFork: + eUpgradeTime = defaultValidateStartTime.Add(-2 * time.Second) + fallthrough + case durangoFork: durangoTime = defaultValidateStartTime.Add(-2 * time.Second) + fallthrough + case cortinaFork: + cortinaTime = defaultValidateStartTime.Add(-2 * time.Second) + fallthrough + case banffFork: + banffTime = defaultValidateStartTime.Add(-2 * time.Second) + fallthrough + case apricotPhase5: + apricotPhase5Time = defaultValidateEndTime + fallthrough + case apricotPhase3: + apricotPhase3Time = defaultValidateEndTime + default: + require.NoError(t, fmt.Errorf("unhandled fork %d", fork)) } return &config.Config{ @@ -303,18 +330,18 @@ func defaultConfig(postBanff, postCortina, postDurango bool) *config.Config { MintingPeriod: 365 * 24 * time.Hour, SupplyCap: 720 * units.MegaAvax, }, - ApricotPhase3Time: defaultValidateEndTime, - ApricotPhase5Time: defaultValidateEndTime, + ApricotPhase3Time: apricotPhase3Time, + ApricotPhase5Time: apricotPhase5Time, BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, - EUpgradeTime: mockable.MaxTime, + EUpgradeTime: eUpgradeTime, } } -func defaultClock(postFork bool) *mockable.Clock { +func defaultClock(fork activeFork) *mockable.Clock { now := defaultGenesisTime - if postFork { + if fork == eUpgradeFork || fork == durangoFork || fork == cortinaFork || fork == banffFork { // 1 second after Banff fork now = defaultValidateEndTime.Add(-2 * time.Second) } diff --git a/vms/platformvm/txs/executor/import_test.go b/vms/platformvm/txs/executor/import_test.go index fed09bd882c..9f1c90dab50 100644 --- a/vms/platformvm/txs/executor/import_test.go +++ b/vms/platformvm/txs/executor/import_test.go @@ -22,7 +22,7 @@ import ( ) func TestNewImportTx(t *testing.T) { - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) type test struct { description string diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index e01bd267a02..d16e072a3a1 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -91,7 +91,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { require.NoError(t, target.state.Commit()) } - dummyH := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + dummyH := newEnvironment(t, apricotPhase5) currentTimestamp := dummyH.state.GetTimestamp() type test struct { @@ -245,7 +245,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { require := require.New(t) - freshTH := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + freshTH := newEnvironment(t, apricotPhase5) freshTH.config.ApricotPhase3Time = tt.AP3Time tx, err := freshTH.txBuilder.NewAddDelegatorTx( @@ -283,7 +283,7 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -716,7 +716,7 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { func TestProposalTxExecuteAddValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index 18ba653a4e7..c9aa34f207d 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -35,7 +35,7 @@ func newRewardValidatorTx(t testing.TB, txID ids.ID) (*txs.Tx, error) { func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) dummyHeight := uint64(1) currentStakerIterator, err := env.state.GetCurrentStakerIterator() @@ -135,7 +135,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) dummyHeight := uint64(1) currentStakerIterator, err := env.state.GetCurrentStakerIterator() @@ -229,7 +229,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { func TestRewardDelegatorTxExecuteOnCommitPreDelegateeDeferral(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) dummyHeight := uint64(1) vdrRewardAddress := ids.GenerateTestShortID() @@ -350,7 +350,7 @@ func TestRewardDelegatorTxExecuteOnCommitPreDelegateeDeferral(t *testing.T) { func TestRewardDelegatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, true /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, cortinaFork) dummyHeight := uint64(1) vdrRewardAddress := ids.GenerateTestShortID() @@ -566,7 +566,7 @@ func TestRewardDelegatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { func TestRewardDelegatorTxAndValidatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, true /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, cortinaFork) dummyHeight := uint64(1) vdrRewardAddress := ids.GenerateTestShortID() @@ -725,7 +725,7 @@ func TestRewardDelegatorTxAndValidatorTxExecuteOnCommitPostDelegateeDeferral(t * func TestRewardDelegatorTxExecuteOnAbort(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) dummyHeight := uint64(1) initialSupply, err := env.state.GetCurrentSupply(constants.PrimaryNetworkID) diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 6fd7fd0bc1f..211bc742409 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -46,7 +46,7 @@ var errTest = errors.New("non-nil error") func TestStandardTxExecutorAddValidatorTxEmptyID(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -168,7 +168,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { require.NoError(t, target.state.Commit()) } - dummyH := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + dummyH := newEnvironment(t, apricotPhase5) currentTimestamp := dummyH.state.GetTimestamp() type test struct { @@ -322,7 +322,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { require := require.New(t) - freshTH := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + freshTH := newEnvironment(t, apricotPhase5) freshTH.config.ApricotPhase3Time = tt.AP3Time tx, err := freshTH.txBuilder.NewAddDelegatorTx( @@ -358,7 +358,7 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, false /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, apricotPhase5) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -785,7 +785,7 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { func TestBanffStandardTxExecutorAddValidator(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, false /*=postCortina*/, false /*=postDurango*/) + env := newEnvironment(t, banffFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -1068,7 +1068,7 @@ func TestDurangoDisabledTransactions(t *testing.T) { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, true /*=postCortina*/, true /*=postDurango*/) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() @@ -1592,7 +1592,7 @@ func TestDurangoMemoField(t *testing.T) { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - env := newEnvironment(t, true /*=postBanff*/, true /*=postCortina*/, true /*=postDurango*/) + env := newEnvironment(t, durangoFork) env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 94e158582cc..ea0e213d6ef 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -80,6 +80,7 @@ const ( banffFork cortinaFork durangoFork + eUpgradeFork latestFork activeFork = durangoFork @@ -210,12 +211,16 @@ func defaultVM(t *testing.T, fork activeFork) (*VM, database.Database, *mutableS banffTime = mockable.MaxTime cortinaTime = mockable.MaxTime durangoTime = mockable.MaxTime + eUpgradeTime = mockable.MaxTime ) // always reset latestForkTime (a package level variable) // to ensure test independence latestForkTime = defaultGenesisTime.Add(time.Second) switch fork { + case eUpgradeFork: + eUpgradeTime = latestForkTime + fallthrough case durangoFork: durangoTime = latestForkTime fallthrough @@ -254,7 +259,7 @@ func defaultVM(t *testing.T, fork activeFork) (*VM, database.Database, *mutableS BanffTime: banffTime, CortinaTime: cortinaTime, DurangoTime: durangoTime, - EUpgradeTime: mockable.MaxTime, + EUpgradeTime: eUpgradeTime, }} db := memdb.New() From 1feae9a4018423a38d66fa041460974d7faae6a6 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 14 Feb 2024 15:55:07 +0100 Subject: [PATCH 05/53] refactored createAssetTx builder --- vms/avm/service.go | 134 ++++++++++------------ vms/avm/service_test.go | 205 ++++++++++++++++++++-------------- vms/avm/utxo/spender.go | 103 +++++++++++++++++ vms/avm/vm_regression_test.go | 35 ++++-- vms/avm/vm_test.go | 75 ++++++++----- 5 files changed, 356 insertions(+), 196 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 4dcc210df81..1d34bef7d12 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -753,32 +753,6 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI return nil, ids.ShortEmpty, err } - amountsSpent, ins, keys, err := s.vm.Spend( - utxos, - kc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.CreateAssetTxFee, - }, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - outs := []*avax.TransferableOutput{} - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.CreateAssetTxFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: s.vm.feeAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - s.vm.CreateAssetTxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - initialState := &txs.InitialState{ FxIndex: 0, // TODO: Should lookup secp256k1fx FxID Outs: make([]verify.State, 0, len(args.InitialHolders)+len(args.MinterSets)), @@ -815,19 +789,55 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI codec := s.vm.parser.Codec() initialState.Sort(codec) - tx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + return buildCreateAssetTx( + s.vm, + args.Name, + args.Symbol, + args.Denomination, + []*txs.InitialState{initialState}, + utxos, + kc, + changeAddr, + ) +} + +func buildCreateAssetTx( + vm *VM, + name, symbol string, + denomination byte, + initialStates []*txs.InitialState, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.CreateAssetTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, }}, - Name: args.Name, - Symbol: args.Symbol, - Denomination: args.Denomination, - States: []*txs.InitialState{initialState}, - }} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) + Name: name, + Symbol: symbol, + Denomination: denomination, + States: initialStates, + } + + toBurn := map[ids.ID]uint64{ + vm.feeAssetID: vm.CreateAssetTxFee, + } + ins, outs, keys, err := vm.NewSpend( + utxos, + kc, + toBurn, + changeAddr, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + return tx, changeAddr, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) } // CreateFixedCapAsset returns ID of the newly created asset @@ -918,32 +928,6 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh return nil, ids.ShortEmpty, err } - amountsSpent, ins, keys, err := s.vm.Spend( - utxos, - kc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.CreateAssetTxFee, - }, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - outs := []*avax.TransferableOutput{} - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.CreateAssetTxFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: s.vm.feeAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - s.vm.CreateAssetTxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - initialState := &txs.InitialState{ FxIndex: 1, // TODO: Should lookup nftfx FxID Outs: make([]verify.State, 0, len(args.MinterSets)), @@ -966,20 +950,16 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh codec := s.vm.parser.Codec() initialState.Sort(codec) - - tx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - }}, - Name: args.Name, - Symbol: args.Symbol, - Denomination: 0, // NFTs are non-fungible - States: []*txs.InitialState{initialState}, - }} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) + return buildCreateAssetTx( + s.vm, + args.Name, + args.Symbol, + 0, // NFTs are non-fungible + []*txs.InitialState{initialState}, + utxos, + kc, + changeAddr, + ) } // CreateAddress creates an address for the user [args.Username] diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 9d187987155..dd526db0312 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -699,7 +699,10 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + CreateAssetTxFee: testTxFee, + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -712,7 +715,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) reply := api.GetTxReply{} @@ -730,8 +733,34 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 49000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "outputIndex": 2, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 50000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "name": "Team Rocket", "symbol": "TR", @@ -801,7 +830,16 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { } ] }, - "credentials": null, + "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xa036832b708b377ef9719ffbc834a3fb933191a467994f844c23f4a44350e86a7151cdbbbfa479d93a4906cc22254dcc5ccc2a6099492e7a9f9e8b575048d69701" + ] + } + } + ], "id": "PLACEHOLDER_TX_ID" }` @@ -829,7 +867,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildNFTxMintOp(createAssetTx, key, 2, 1)) @@ -928,7 +966,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) @@ -1066,7 +1104,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildSecpMintOp(createAssetTx, key, 0)) @@ -1169,7 +1207,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) op1 := buildSecpMintOp(createAssetTx, key, 0) @@ -1315,7 +1353,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildPropertyFxMintOp(createAssetTx, key, 4)) @@ -1415,7 +1453,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) op1 := buildPropertyFxMintOp(createAssetTx, key, 4) @@ -1553,10 +1591,78 @@ func newAvaxExportTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.I return tx } -func newAvaxCreateAssetTxWithOutputs(t *testing.T, chainID ids.ID, parser txs.Parser) *txs.Tx { - key := keys[0] - tx := buildCreateAssetTx(chainID, key) - require.NoError(t, tx.Initialize(parser.Codec())) +func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(t, err) + tx, _, err := buildCreateAssetTx( + env.vm, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + []*txs.InitialState{ + { + FxIndex: 0, + Outs: []verify.State{ + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + }, + { + FxIndex: 1, + Outs: []verify.State{ + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + }, + { + FxIndex: 2, + Outs: []verify.State{ + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + }, + }, + utxos, + kc, + key.Address(), + ) + require.NoError(t, err) return tx } @@ -1628,72 +1734,6 @@ func buildExportTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.Pr }} } -func buildCreateAssetTx(chainID ids.ID, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - }, - { - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - }, - { - FxIndex: 2, - Outs: []verify.State{ - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - }, - }, - }} -} - func buildNFTxMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputIndex, groupID uint32) *txs.Operation { return &txs.Operation{ Asset: avax.Asset{ID: createAssetTx.ID()}, @@ -2536,6 +2576,9 @@ func TestSendMultiple(t *testing.T) { password: password, initialKeys: keys, }}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, }) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/utxo/spender.go b/vms/avm/utxo/spender.go index 02ade0d92ea..2e429d6bc2f 100644 --- a/vms/avm/utxo/spender.go +++ b/vms/avm/utxo/spender.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/timer/mockable" @@ -45,6 +46,18 @@ type Spender interface { error, ) + NewSpend( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + toSpend map[ids.ID]uint64, + changeAddr ids.ShortID, + ) ( + []*avax.TransferableInput, // inputs + []*avax.TransferableOutput, // outputs + [][]*secp256k1.PrivateKey, // signers + error, + ) + SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, @@ -172,6 +185,96 @@ func (s *spender) Spend( return amountsSpent, ins, keys, nil } +func (s *spender) NewSpend( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + amountsToBurn map[ids.ID]uint64, + changeAddr ids.ShortID, +) ( + inputs []*avax.TransferableInput, + outputs []*avax.TransferableOutput, + signers [][]*secp256k1.PrivateKey, + err error, +) { + var ( + minIssuanceTime = s.clock.Unix() + changeOwner = &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + } + ) + + // Iterate over the UTXOs + for _, utxo := range utxos { + assetID := utxo.AssetID() + remainingAmountToBurn := amountsToBurn[assetID] + + // If we have consumed enough of the asset, then we have no need burn + // more. + if remainingAmountToBurn == 0 { + continue + } + + outIntf := utxo.Out + out, ok := outIntf.(*secp256k1fx.TransferOutput) + if !ok { + // We only support burning [secp256k1fx.TransferOutput]s. + continue + } + + inputIntf, keys, err := kc.Spend(utxo.Out, minIssuanceTime) + if err != nil { + // this utxo can't be spent with the current keys right now + continue + } + input, ok := inputIntf.(avax.TransferableIn) + if !ok { + // this input doesn't have an amount, so I don't care about it here + continue + } + + inputs = append(inputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: avax.Asset{ID: assetID}, + In: input, + }) + signers = append(signers, keys) + + // Burn any value that should be burned + amountToBurn := min( + remainingAmountToBurn, // Amount we still need to burn + out.Amt, // Amount available to burn + ) + amountsToBurn[assetID] -= amountToBurn + if remainingAmount := out.Amt - amountToBurn; remainingAmount > 0 { + // This input had extra value, so some of it must be returned + outputs = append(outputs, &avax.TransferableOutput{ + Asset: utxo.Asset, + FxID: secp256k1fx.ID, + Out: &secp256k1fx.TransferOutput{ + Amt: remainingAmount, + OutputOwners: *changeOwner, + }, + }) + } + } + + for assetID, amount := range amountsToBurn { + if amount != 0 { + return nil, nil, nil, fmt.Errorf( + "%w: provided UTXOs need %d more units of asset %q", + errInsufficientFunds, + amount, + assetID, + ) + } + } + + utils.Sort(inputs) // sort inputs + avax.SortTransferableOutputs(outputs, s.codec) // sort the change outputs + return inputs, outputs, signers, nil +} + func (s *spender) SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index c6ac40df845..5a7f73df6d5 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -6,6 +6,7 @@ package avm import ( "context" "testing" + "time" "github.com/stretchr/testify/require" @@ -24,7 +25,9 @@ func TestVerifyFxUsage(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, }) env.vm.ctx.Lock.Unlock() defer func() { @@ -33,15 +36,20 @@ func TestVerifyFxUsage(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{ + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + createAssetTx, _, err := buildCreateAssetTx( + env.vm, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + []*txs.InitialState{ { FxIndex: 0, Outs: []verify.State{ @@ -67,8 +75,11 @@ func TestVerifyFxUsage(t *testing.T) { }, }, }, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + utxos, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index d8aeaf3b874..347ddbdb971 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -7,6 +7,7 @@ import ( "context" "math" "testing" + "time" "github.com/stretchr/testify/require" @@ -132,7 +133,9 @@ func TestIssueNFT(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, }) env.vm.ctx.Lock.Unlock() defer func() { @@ -141,35 +144,45 @@ func TestIssueNFT(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{{ + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + // Create the asset + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + createAssetTx, _, err := buildCreateAssetTx( + env.vm, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + []*txs.InitialState{{ FxIndex: 1, Outs: []verify.State{ &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, &nftfx.MintOutput{ GroupID: 2, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, }, }}, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + utxos, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ @@ -233,7 +246,9 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -246,15 +261,20 @@ func TestIssueProperty(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{{ + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + createAssetTx, _, err := buildCreateAssetTx( + env.vm, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + []*txs.InitialState{{ FxIndex: 2, Outs: []verify.State{ &propertyfx.MintOutput{ @@ -265,8 +285,11 @@ func TestIssueProperty(t *testing.T) { }, }, }}, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + utxos, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) mintPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ From 39cae3c462badd0cf4df73d4fa2736300a49ac64 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 14 Feb 2024 17:48:17 +0100 Subject: [PATCH 06/53] refactored baseTx builder --- vms/avm/service.go | 67 ++++++++--------- vms/avm/service_test.go | 88 +++++++++++----------- vms/avm/vm_regression_test.go | 31 ++++---- vms/avm/vm_test.go | 133 ++++++++++++++++------------------ 4 files changed, 158 insertions(+), 161 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 1d34bef7d12..1c298a9aada 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1268,55 +1268,52 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - amountsWithFee := make(map[ids.ID]uint64, len(amounts)+1) - for assetID, amount := range amounts { - amountsWithFee[assetID] = amount + return buildBaseTx(s.vm, outs, memoBytes, utxos, kc, changeAddr) +} + +func buildBaseTx( + vm *VM, + outs []*avax.TransferableOutput, + memo []byte, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + Memo: memo, + Outs: outs, + }, } - amountWithFee, err := safemath.Add64(amounts[s.vm.feeAssetID], s.vm.TxFee) + toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees + for _, out := range outs { + toBurn[out.AssetID()] += out.Out.Amount() + } + amountWithFee, err := safemath.Add64(toBurn[vm.feeAssetID], vm.TxFee) if err != nil { return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) } - amountsWithFee[s.vm.feeAssetID] = amountWithFee + toBurn[vm.feeAssetID] = amountWithFee - amountsSpent, ins, keys, err := s.vm.Spend( + ins, feeOuts, keys, err := vm.NewSpend( utxos, kc, - amountsWithFee, + toBurn, + changeAddr, ) if err != nil { return nil, ids.ShortEmpty, err } - // Add the required change outputs - for assetID, amountWithFee := range amountsWithFee { - amountSpent := amountsSpent[assetID] - - if amountSpent > amountWithFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - amountWithFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - } - - codec := s.vm.parser.Codec() - avax.SortTransferableOutputs(outs, codec) + uTx.Ins = ins + uTx.Outs = append(uTx.Outs, feeOuts...) + codec := vm.parser.Codec() + avax.SortTransferableOutputs(uTx.Outs, codec) - tx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - Memo: memoBytes, - }}} + tx := &txs.Tx{Unsigned: uTx} return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index dd526db0312..cc5075dd2a4 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -28,6 +28,7 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" "github.com/ava-labs/avalanchego/vms/avm/config" @@ -86,7 +87,7 @@ func TestServiceGetTxStatus(t *testing.T) { err := env.service.GetTxStatus(nil, statusArgs, statusReply) require.ErrorIs(err, errNilTxID) - newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := newAvaxBaseTxWithOutputs(t, env) txID := newTx.ID() statusArgs = &api.JSONTxID{ @@ -539,7 +540,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := newAvaxBaseTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -565,7 +566,19 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 49000, + "amount": 1000, + "locktime": 0, + "threshold": 1 + } + }, + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1d6kkj0qh4wcmus3tk59npwt3rluc6en72ngurd" + ], + "amount": 48000, "locktime": 0, "threshold": 1 } @@ -1575,11 +1588,35 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require.Equal(expectedReplyTxString, string(replyTxBytes)) } -func newAvaxBaseTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { - avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") - key := keys[0] - tx := buildBaseTx(avaxTx, chainID, fee, key) - require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) +func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { + var ( + memo = []byte{1, 2, 3, 4, 5, 6, 7, 8} + key = keys[0] + changeKey = keys[1] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(t, err) + + tx, _, err := buildBaseTx( + env.vm, + []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: env.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.MicroAvax, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }}, + memo, + utxos, + kc, + changeKey.PublicKey().Address(), + ) + require.NoError(t, err) return tx } @@ -1666,41 +1703,6 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { return tx } -func buildBaseTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - Memo: []byte{1, 2, 3, 4, 5, 6, 7, 8}, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, - }, - }}, - Outs: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - fee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }, - }} -} - func buildExportTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { return &txs.Tx{Unsigned: &txs.ExportTx{ BaseTx: txs.BaseTx{ diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 5a7f73df6d5..84bdd518481 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -106,23 +106,28 @@ func TestVerifyFxUsage(t *testing.T) { require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - spendTx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }, + // refresh the UTXOs set + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + to := keys[2].PublicKey().Address() + spendTx, _, err := buildBaseTx( + env.vm, + []*avax.TransferableOutput{{ Asset: avax.Asset{ID: createAssetTx.ID()}, - In: &secp256k1fx.TransferInput{ + Out: &secp256k1fx.TransferOutput{ Amt: 1, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{to}, }, }, }}, - }}} - require.NoError(spendTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + nil, // memo + utxos, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, spendTx) } diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 347ddbdb971..f83e4fec400 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -377,51 +377,47 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { }() // send second asset - feeAssetCreateTx := getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) - createTx := getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() - tx := &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{ - // fee asset - { - UTXOID: avax.UTXOID{ - TxID: feeAssetCreateTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, + feeAssetCreateTx = getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) + createTx = getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + tx, _, err := buildBaseTx( + env.vm, + []*avax.TransferableOutput{ + { // fee asset + Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - // issued asset - { - UTXOID: avax.UTXOID{ - TxID: createTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: createTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, + }, + { // issued asset + Asset: avax.Asset{ID: createTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, }, }, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}, {keys[0]}})) - + nil, // memo + utxos, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, tx) } @@ -455,6 +451,9 @@ func TestTxAcceptAfterParseTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, notLinearized: true, }) defer func() { @@ -462,40 +461,34 @@ func TestTxAcceptAfterParseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - key := keys[0] - firstTx := &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: env.genesisTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: env.genesisTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, - }, - }}, - Outs: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: env.genesisTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + firstTx, _, err := buildBaseTx( + env.vm, + []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: env.genesisTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, - }}, - }, - }} - require.NoError(firstTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + }, + }}, + nil, // memo + utxos, + kc, + key.Address(), + ) + require.NoError(err) + // let secondTx spend firstTx outputs secondTx := &txs.Tx{Unsigned: &txs.BaseTx{ BaseTx: avax.BaseTx{ NetworkID: constants.UnitTestID, From 7c04d760a3ae64934e4f512358b43a2db681d354 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 14 Feb 2024 18:46:20 +0100 Subject: [PATCH 07/53] refactored operationTx builder --- vms/avm/service.go | 154 +++++++-------------------- vms/avm/service_test.go | 71 ++++++++----- vms/avm/vm_regression_test.go | 49 +++++---- vms/avm/vm_test.go | 194 +++++++++++++++++----------------- 4 files changed, 207 insertions(+), 261 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 1c298a9aada..758e4031e2f 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1393,32 +1393,6 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - amountsSpent, ins, keys, err := s.vm.Spend( - feeUTXOs, - feeKc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.TxFee, - }, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - outs := []*avax.TransferableOutput{} - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: s.vm.feeAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - s.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - // Get all UTXOs/keys for the user utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { @@ -1436,18 +1410,44 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { if err != nil { return nil, ids.ShortEmpty, err } - keys = append(keys, opKeys...) - tx := &txs.Tx{Unsigned: &txs.OperationTx{ + return buildOperation(s.vm, ops, opKeys, feeUTXOs, feeKc, changeAddr) +} + +func buildOperation( + vm *VM, + ops []*txs.Operation, + opsKeys [][]*secp256k1.PrivateKey, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.OperationTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, }}, Ops: ops, - }} - return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), keys) + } + + toBurn := map[ids.ID]uint64{ + vm.feeAssetID: vm.TxFee, + } + ins, outs, keys, err := vm.NewSpend( + utxos, + kc, + toBurn, + changeAddr, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + keys = append(keys, opsKeys...) + return tx, changeAddr, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) } // SendNFTArgs are arguments for passing into SendNFT requests @@ -1518,32 +1518,6 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - amountsSpent, ins, secpKeys, err := s.vm.Spend( - utxos, - kc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.TxFee, - }, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - outs := []*avax.TransferableOutput{} - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: s.vm.feeAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - s.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - ops, nftKeys, err := s.vm.SpendNFT( utxos, kc, @@ -1555,21 +1529,12 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - }}, - Ops: ops, - }} - - codec := s.vm.parser.Codec() - if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil { + tx, _, err := buildOperation(s.vm, ops, nil, utxos, kc, changeAddr) + if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, tx.SignNFTFx(codec, nftKeys) + + return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys) } // MintNFTArgs are arguments for passing into MintNFT requests @@ -1644,38 +1609,11 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - amountsSpent, ins, secpKeys, err := s.vm.Spend( - feeUTXOs, - feeKc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.TxFee, - }, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - outs := []*avax.TransferableOutput{} - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: s.vm.feeAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - s.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - // Get all UTXOs/keys utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, ids.ShortEmpty, err } - ops, nftKeys, err := s.vm.MintNFT( utxos, kc, @@ -1687,21 +1625,11 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - }}, - Ops: ops, - }} - - codec := s.vm.parser.Codec() - if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil { + tx, _, err := buildOperation(s.vm, ops, nil, feeUTXOs, feeKc, changeAddr) + if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, tx.SignNFTFx(codec, nftKeys) + return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys) } // ImportArgs are arguments for passing into Import requests diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index cc5075dd2a4..38135413048 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -866,7 +866,9 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -883,7 +885,8 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildNFTxMintOp(createAssetTx, key, 2, 1)) + op := buildNFTxMintOp(createAssetTx, key, 2, 1) + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil) require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) @@ -965,7 +968,9 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -984,8 +989,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2) - mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, mintOp1, mintOp2) - + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}, nil) require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) @@ -1103,7 +1107,9 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1120,8 +1126,8 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildSecpMintOp(createAssetTx, key, 0)) - require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + op := buildSecpMintOp(createAssetTx, key, 0) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, [][]*secp256k1.PrivateKey{{key}}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1206,7 +1212,9 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1225,9 +1233,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { op1 := buildSecpMintOp(createAssetTx, key, 0) op2 := buildSecpMintOp(createAssetTx, key, 1) - mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) - - require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, [][]*secp256k1.PrivateKey{{key}, {key}}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1352,7 +1358,9 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1369,7 +1377,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildPropertyFxMintOp(createAssetTx, key, 4)) + op := buildPropertyFxMintOp(createAssetTx, key, 4) + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil) require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) @@ -1452,7 +1461,9 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{}, + vmStaticConfig: &config.Config{ + DurangoTime: time.Time{}, + }, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1471,8 +1482,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) op1 := buildPropertyFxMintOp(createAssetTx, key, 4) op2 := buildPropertyFxMintOp(createAssetTx, key, 5) - mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) - + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, nil) require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) @@ -1809,14 +1819,25 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd } } -func buildOperationTxWithOp(chainID ids.ID, op ...*txs.Operation) *txs.Tx { - return &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - }}, - Ops: op, - }} +func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation, opsKeys [][]*secp256k1.PrivateKey) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(t, err) + + tx, _, err := buildOperation( + env.vm, + ops, + opsKeys, + utxos, + kc, + key.Address(), + ) + require.NoError(t, err) + return tx } func TestServiceGetNilTx(t *testing.T) { diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 84bdd518481..161e631156f 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -11,8 +11,6 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -44,6 +42,7 @@ func TestVerifyFxUsage(t *testing.T) { utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) + // Create the asset createAssetTx, _, err := buildCreateAssetTx( env.vm, "Team Rocket", // name @@ -82,31 +81,31 @@ func TestVerifyFxUsage(t *testing.T) { require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 1, - }}, - Op: &nftfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - Outputs: []*secp256k1fx.OutputOwners{{}}, - }, - }}, - }} - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + // Mint the NFT + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + mintOp, nftKeys, err := env.vm.MintNFT( + utxos, + kc, + createAssetTx.ID(), + []byte{'h', 'e', 'l', 'l', 'o'}, // payload + key.Address(), + ) + require.NoError(err) + + mintNFTTx, _, err := buildOperation( + env.vm, + mintOp, + nil, + utxos, + kc, + key.Address(), + ) + require.NoError(err) + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), nftKeys)) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - // refresh the UTXOs set + // move the NFT utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index f83e4fec400..cb299ddafbc 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -21,7 +21,6 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/vms/avm/config" - "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -169,13 +168,6 @@ func TestIssueNFT(t *testing.T) { Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, }, }}, utxos, @@ -185,59 +177,52 @@ func TestIssueNFT(t *testing.T) { require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }}, - Op: &nftfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - Outputs: []*secp256k1fx.OutputOwners{{}}, - }, - }}, - }} - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + // Mint the NFT + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + mintOp, nftKeys, err := env.vm.MintNFT( + utxos, + kc, + createAssetTx.ID(), + []byte{'h', 'e', 'l', 'l', 'o'}, // payload + key.Address(), + ) + require.NoError(err) + + mintNFTTx, _, err := buildOperation( + env.vm, + mintOp, + nil, + utxos, + kc, + key.Address(), + ) + require.NoError(err) + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), nftKeys)) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - transferNFTTx := &txs.Tx{ - Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: mintNFTTx.ID(), - OutputIndex: 0, - }}, - Op: &nftfx.TransferOperation{ - Input: secp256k1fx.Input{}, - Output: nftfx.TransferOutput{ - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - OutputOwners: secp256k1fx.OutputOwners{}, - }, - }, - }}, - }, - Creds: []*fxs.FxCredential{ - { - Credential: &nftfx.Credential{}, - }, - }, - } - require.NoError(transferNFTTx.Initialize(env.vm.parser.Codec())) + // Move the NFT + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + transferOp, moveNftKeys, err := env.vm.SpendNFT( + utxos, + kc, + createAssetTx.ID(), + 1, + keys[2].Address(), + ) + require.NoError(err) + + transferNFTTx, _, err := buildOperation( + env.vm, + transferOp, + nil, + utxos, + kc, + key.Address(), + ) + require.NoError(err) + require.NoError(transferNFTTx.SignNFTFx(env.vm.parser.Codec(), moveNftKeys)) issueAndAccept(require, env.vm, env.issuer, transferNFTTx) } @@ -262,13 +247,15 @@ func TestIssueProperty(t *testing.T) { }() var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() + key = keys[0] + kc = secp256k1fx.NewKeychain() + codec = env.vm.parser.Codec() ) kc.Add(key) + + // create the asset utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) - createAssetTx, _, err := buildCreateAssetTx( env.vm, "Team Rocket", // name @@ -292,53 +279,64 @@ func TestIssueProperty(t *testing.T) { require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, + // mint the property + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + mintPropertyOp := &txs.Operation{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: createAssetTx.ID(), + OutputIndex: 0, }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }}, - Op: &propertyfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - MintOutput: propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, + Op: &propertyfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: []uint32{0}, + }, + MintOutput: propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, - OwnedOutput: propertyfx.OwnedOutput{}, }, - }}, - }} + OwnedOutput: propertyfx.OwnedOutput{}, + }, + } - codec := env.vm.parser.Codec() + mintPropertyTx, _, err := buildOperation( + env.vm, + []*txs.Operation{mintPropertyOp}, + nil, + utxos, + kc, + key.Address(), + ) + require.NoError(err) require.NoError(mintPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ {keys[0]}, })) issueAndAccept(require, env.vm, env.issuer, mintPropertyTx) - burnPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: mintPropertyTx.ID(), - OutputIndex: 1, - }}, - Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, + // burn the property + utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + burnPropertyOp := &txs.Operation{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: mintPropertyTx.ID(), + OutputIndex: 1, }}, - }} + Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, + } + burnPropertyTx, _, err := buildOperation( + env.vm, + []*txs.Operation{burnPropertyOp}, + nil, + utxos, + kc, + key.Address(), + ) + require.NoError(err) require.NoError(burnPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ {}, })) From 40e480a9382cd81d38cda516db7b648006818a78 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 15 Feb 2024 11:02:53 +0100 Subject: [PATCH 08/53] refactored exportTx builder --- vms/avm/service.go | 97 +++++++++++++++++----------------- vms/avm/service_test.go | 81 ++++++++++++++--------------- vms/avm/vm_test.go | 112 +++++++++++++++++----------------------- 3 files changed, 133 insertions(+), 157 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 758e4031e2f..54ab837e52a 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1848,65 +1848,62 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - amounts := map[ids.ID]uint64{} - if assetID == s.vm.feeAssetID { - amountWithFee, err := safemath.Add64(uint64(args.Amount), s.vm.TxFee) + return buildExportTx(s.vm, chainID, to, assetID, uint64(args.Amount), utxos, kc, changeAddr) +} + +func buildExportTx( + vm *VM, + destinationChain ids.ID, + to ids.ShortID, + exportedAssetID ids.ID, + exportedAmt uint64, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.ExportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + }}, + DestinationChain: destinationChain, + ExportedOuts: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: exportedAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: exportedAmt, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, + }, + }}, + } + toBurn := map[ids.ID]uint64{} + if exportedAssetID == vm.feeAssetID { + amountWithFee, err := safemath.Add64(exportedAmt, vm.TxFee) if err != nil { return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) } - amounts[s.vm.feeAssetID] = amountWithFee + toBurn[vm.feeAssetID] = amountWithFee } else { - amounts[s.vm.feeAssetID] = s.vm.TxFee - amounts[assetID] = uint64(args.Amount) + toBurn[exportedAssetID] = exportedAmt + toBurn[vm.feeAssetID] = vm.TxFee } - - amountsSpent, ins, keys, err := s.vm.Spend(utxos, kc, amounts) + ins, outs, keys, err := vm.NewSpend( + utxos, + kc, + toBurn, + changeAddr, + ) if err != nil { return nil, ids.ShortEmpty, err } - exportOuts := []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: uint64(args.Amount), - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, - }, - }} - - outs := []*avax.TransferableOutput{} - for assetID, amountSpent := range amountsSpent { - amountToSend := amounts[assetID] - if amountSpent > amountToSend { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - amountToSend, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - } - - codec := s.vm.parser.Codec() - avax.SortTransferableOutputs(outs, codec) + codec := vm.parser.Codec() - tx := &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - }}, - DestinationChain: chainID, - ExportedOuts: exportOuts, - }} + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 38135413048..dc3995c776c 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -635,7 +635,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := newAvaxExportTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -652,7 +652,20 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], "inputs": [ { "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -668,7 +681,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { } ], "memo": "0x", - "destinationChain": "11111111111111111111111111111111LpoYY", + "destinationChain": "2mcwQKiD8VEspmMJpL1dc7okQQ5dDVAWeCBZ7FWBFAbxpv3t7w", "exportedOutputs": [ { "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -677,7 +690,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 49000, + "amount": 1000, "locktime": 0, "threshold": 1 } @@ -1630,14 +1643,6 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { return tx } -func newAvaxExportTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { - avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") - key := keys[0] - tx := buildExportTx(avaxTx, chainID, fee, key) - require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - return tx -} - func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { var ( key = keys[0] @@ -1713,37 +1718,27 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { return tx } -func buildExportTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }, - }, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - fee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }} +func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(t, err) + tx, _, err := buildExportTx( + env.vm, + chainID, + to, + env.vm.feeAssetID, + units.MicroAvax, + utxos, + kc, + key.Address(), + ) + require.NoError(t, err) + return tx } func buildNFTxMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputIndex, groupID uint32) *txs.Operation { diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index cb299ddafbc..cfeb7cbc8b5 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -718,38 +718,30 @@ func TestIssueExportTx(t *testing.T) { }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") - avaxID := genesisTx.ID() - key := keys[0] - tx := &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxID, - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxID}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }}, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxID}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + var ( + avaxID = genesisTx.ID() + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + changeAddr = to + ) + + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + tx, _, err := buildExportTx( + env.vm, + constants.PlatformChainID, + to, // to + avaxID, + startBalance-env.vm.TxFee, + utxos, + kc, + changeAddr, + ) + require.NoError(err) peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) utxoBytes, _, _, err := peerSharedMemory.Indexed( @@ -793,39 +785,31 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") - avaxID := genesisTx.ID() - key := keys[0] - assetID := avax.Asset{ID: avaxID} - tx := &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxID, - OutputIndex: 2, - }, - Asset: assetID, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }}, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: assetID, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + var ( + avaxID = genesisTx.ID() + assetID = avax.Asset{ID: avaxID} + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + changeAddr = to + ) + + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + + tx, _, err := buildExportTx( + env.vm, + constants.PlatformChainID, + to, // to + avaxID, + startBalance-env.vm.TxFee, + utxos, + kc, + changeAddr, + ) + require.NoError(err) utxo := avax.UTXOID{ TxID: tx.ID(), @@ -840,7 +824,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }, })) - _, err := peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) + _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) env.vm.ctx.Lock.Unlock() From 03c0a9f0a19ff99ca53afdb0319baf09633953e7 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 15 Feb 2024 11:50:01 +0100 Subject: [PATCH 09/53] wip: refactoring importTx builder --- vms/avm/service.go | 93 ++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 54ab837e52a..3f74b3d4cb4 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1692,70 +1692,51 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return nil, fmt.Errorf("problem retrieving user's atomic UTXOs: %w", err) } - amountsSpent, importInputs, importKeys, err := s.vm.SpendAll(atomicUTXOs, kc) + return buildImportTx(s.vm, chainID, atomicUTXOs, to, utxos, kc) +} + +func buildImportTx( + vm *VM, + sourceChain ids.ID, + atomicUTXOs []*avax.UTXO, + to ids.ShortID, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, +) (*txs.Tx, error) { + toBurn, importInputs, importKeys, err := vm.SpendAll(atomicUTXOs, kc) if err != nil { return nil, err } - ins := []*avax.TransferableInput{} - keys := [][]*secp256k1.PrivateKey{} - - if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent < s.vm.TxFee { - var localAmountsSpent map[ids.ID]uint64 - localAmountsSpent, ins, keys, err = s.vm.Spend( - utxos, - kc, - map[ids.ID]uint64{ - s.vm.feeAssetID: s.vm.TxFee - amountSpent, - }, - ) - if err != nil { - return nil, err - } - for asset, amount := range localAmountsSpent { - newAmount, err := safemath.Add64(amountsSpent[asset], amount) - if err != nil { - return nil, fmt.Errorf("problem calculating required spend amount: %w", err) - } - amountsSpent[asset] = newAmount - } + uTx := &txs.ImportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + }}, + SourceChain: sourceChain, + ImportedIns: importInputs, } - // Because we ensured that we had enough inputs for the fee, we can - // safely just remove it without concern for underflow. - amountsSpent[s.vm.feeAssetID] -= s.vm.TxFee - - keys = append(keys, importKeys...) - - outs := []*avax.TransferableOutput{} - for assetID, amount := range amountsSpent { - if amount > 0 { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amount, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, - }, - }) - } + if importedAmt := toBurn[vm.feeAssetID]; importedAmt < vm.TxFee { + toBurn[vm.feeAssetID] = vm.TxFee - importedAmt + } else { + toBurn[vm.feeAssetID] = importedAmt - vm.TxFee + } + ins, outs, keys, err := vm.NewSpend( + utxos, + kc, + toBurn, + to, + ) + if err != nil { + return nil, err } - avax.SortTransferableOutputs(outs, s.vm.parser.Codec()) + keys = append(keys, importKeys...) - tx := &txs.Tx{Unsigned: &txs.ImportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: s.vm.ctx.NetworkID, - BlockchainID: s.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - }}, - SourceChain: chainID, - ImportedIns: importInputs, - }} - return tx, tx.SignSECP256K1Fx(s.vm.parser.Codec(), keys) + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) } // ExportArgs are arguments for passing into ExportAVA requests From cb0a69334f4c201fcf00f38152c590fe336a78a2 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 15 Feb 2024 12:16:10 +0100 Subject: [PATCH 10/53] replaced Spend with NewSpend --- vms/avm/service.go | 10 ++--- vms/avm/utxo/spender.go | 81 +-------------------------------------- vms/avm/vm_test.go | 81 ++++++++++++++++----------------------- vms/avm/wallet_service.go | 54 ++++++++++---------------- 4 files changed, 62 insertions(+), 164 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index 3f74b3d4cb4..d11bc405860 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -824,7 +824,7 @@ func buildCreateAssetTx( toBurn := map[ids.ID]uint64{ vm.feeAssetID: vm.CreateAssetTxFee, } - ins, outs, keys, err := vm.NewSpend( + ins, outs, keys, err := vm.Spend( utxos, kc, toBurn, @@ -1298,7 +1298,7 @@ func buildBaseTx( } toBurn[vm.feeAssetID] = amountWithFee - ins, feeOuts, keys, err := vm.NewSpend( + ins, feeOuts, keys, err := vm.Spend( utxos, kc, toBurn, @@ -1433,7 +1433,7 @@ func buildOperation( toBurn := map[ids.ID]uint64{ vm.feeAssetID: vm.TxFee, } - ins, outs, keys, err := vm.NewSpend( + ins, outs, keys, err := vm.Spend( utxos, kc, toBurn, @@ -1722,7 +1722,7 @@ func buildImportTx( } else { toBurn[vm.feeAssetID] = importedAmt - vm.TxFee } - ins, outs, keys, err := vm.NewSpend( + ins, outs, keys, err := vm.Spend( utxos, kc, toBurn, @@ -1871,7 +1871,7 @@ func buildExportTx( toBurn[exportedAssetID] = exportedAmt toBurn[vm.feeAssetID] = vm.TxFee } - ins, outs, keys, err := vm.NewSpend( + ins, outs, keys, err := vm.Spend( utxos, kc, toBurn, diff --git a/vms/avm/utxo/spender.go b/vms/avm/utxo/spender.go index 2e429d6bc2f..1ccd4982f66 100644 --- a/vms/avm/utxo/spender.go +++ b/vms/avm/utxo/spender.go @@ -30,23 +30,12 @@ type Spender interface { // Arguments: // - [utxos] contains assets ID and amount to be spend for each assestID // - [kc] are the owners of the funds - // - [amounts] is the amount of funds that are available to be spent for each assetID + // - [toSpend] is the amount of funds that are available to be spent for each assetID // Returns: - // - [amountsSpent] the amount of funds that are spent // - [inputs] the inputs that should be consumed to fund the outputs + // - [outputs] the outputs produced // - [signers] the proof of ownership of the funds being moved Spend( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - amounts map[ids.ID]uint64, - ) ( - map[ids.ID]uint64, // amountsSpent - []*avax.TransferableInput, // inputs - [][]*secp256k1.PrivateKey, // signers - error, - ) - - NewSpend( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, toSpend map[ids.ID]uint64, @@ -120,72 +109,6 @@ type spender struct { } func (s *spender) Spend( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - amounts map[ids.ID]uint64, -) ( - map[ids.ID]uint64, // amountsSpent - []*avax.TransferableInput, // inputs - [][]*secp256k1.PrivateKey, // signers - error, -) { - amountsSpent := make(map[ids.ID]uint64, len(amounts)) - time := s.clock.Unix() - - ins := []*avax.TransferableInput{} - keys := [][]*secp256k1.PrivateKey{} - for _, utxo := range utxos { - assetID := utxo.AssetID() - amount := amounts[assetID] - amountSpent := amountsSpent[assetID] - - if amountSpent >= amount { - // we already have enough inputs allocated to this asset - continue - } - - inputIntf, signers, err := kc.Spend(utxo.Out, time) - if err != nil { - // this utxo can't be spent with the current keys right now - continue - } - input, ok := inputIntf.(avax.TransferableIn) - if !ok { - // this input doesn't have an amount, so I don't care about it here - continue - } - newAmountSpent, err := math.Add64(amountSpent, input.Amount()) - if err != nil { - // there was an error calculating the consumed amount, just error - return nil, nil, nil, errSpendOverflow - } - amountsSpent[assetID] = newAmountSpent - - // add the new input to the array - ins = append(ins, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: avax.Asset{ID: assetID}, - In: input, - }) - // add the required keys to the array - keys = append(keys, signers) - } - - for asset, amount := range amounts { - if amountsSpent[asset] < amount { - return nil, nil, nil, fmt.Errorf("want to spend %d of asset %s but only have %d", - amount, - asset, - amountsSpent[asset], - ) - } - } - - avax.SortTransferableInputsWithSigners(ins, keys) - return amountsSpent, ins, keys, nil -} - -func (s *spender) NewSpend( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, amountsToBurn map[ids.ID]uint64, diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index cfeb7cbc8b5..cff92c6d8ad 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -546,63 +546,50 @@ func TestIssueImportTx(t *testing.T) { genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() - key := keys[0] - utxoID := avax.UTXOID{ - TxID: ids.ID{ - 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, - 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, - 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, - 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, - }, - } + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() - txAssetID := avax.Asset{ID: avaxID} - tx := &txs.Tx{Unsigned: &txs.ImportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Outs: []*avax.TransferableOutput{{ - Asset: txAssetID, - Out: &secp256k1fx.TransferOutput{ - Amt: 1000, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }}, - }}, - SourceChain: constants.PlatformChainID, - ImportedIns: []*avax.TransferableInput{{ + utxoID = avax.UTXOID{ + TxID: ids.ID{ + 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, + 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, + 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, + 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, + }, + } + txAssetID = avax.Asset{ID: avaxID} + importedUtxo = &avax.UTXO{ UTXOID: utxoID, Asset: txAssetID, - In: &secp256k1fx.TransferInput{ + Out: &secp256k1fx.TransferOutput{ Amt: 1010, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + } + ) + kc.Add(key) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) - // Provide the platform UTXO: - utxo := &avax.UTXO{ - UTXOID: utxoID, - Asset: txAssetID, - Out: &secp256k1fx.TransferOutput{ - Amt: 1010, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - } + tx, err := buildImportTx( + env.vm, + constants.PlatformChainID, // source chain + []*avax.UTXO{importedUtxo}, // atomicUTXOs + key.Address(), + utxos, + kc, + ) + require.NoError(err) - utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, utxo) + // Provide the platform UTXO: + utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, importedUtxo) require.NoError(err) - inputID := utxo.InputID() + inputID := importedUtxo.InputID() require.NoError(peerSharedMemory.Apply(map[ids.ID]*atomic.Requests{ env.vm.ctx.ChainID: { PutRequests: []*atomic.Element{{ diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index 321bf9e57eb..e27c0ea7df8 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -256,52 +256,40 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re }) } - amountsWithFee := maps.Clone(amounts) + uTx := &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: w.vm.ctx.NetworkID, + BlockchainID: w.vm.ctx.ChainID, + Memo: memoBytes, + }, + } - amountWithFee, err := math.Add64(amounts[w.vm.feeAssetID], w.vm.TxFee) + toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees + for _, out := range outs { + toBurn[out.AssetID()] += out.Out.Amount() + } + amountWithFee, err := math.Add64(toBurn[w.vm.feeAssetID], w.vm.TxFee) if err != nil { return fmt.Errorf("problem calculating required spend amount: %w", err) } - amountsWithFee[w.vm.feeAssetID] = amountWithFee + toBurn[w.vm.feeAssetID] = amountWithFee - amountsSpent, ins, keys, err := w.vm.Spend( + ins, feeOuts, keys, err := w.vm.Spend( utxos, kc, - amountsWithFee, + toBurn, + changeAddr, ) if err != nil { return err } - // Add the required change outputs - for assetID, amountWithFee := range amountsWithFee { - amountSpent := amountsSpent[assetID] - - if amountSpent > amountWithFee { - outs = append(outs, &avax.TransferableOutput{ - Asset: avax.Asset{ID: assetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: amountSpent - amountWithFee, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }, - }, - }) - } - } - + uTx.Ins = ins + uTx.Outs = append(uTx.Outs, feeOuts...) codec := w.vm.parser.Codec() - avax.SortTransferableOutputs(outs, codec) - - tx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: w.vm.ctx.NetworkID, - BlockchainID: w.vm.ctx.ChainID, - Outs: outs, - Ins: ins, - Memo: memoBytes, - }}} + avax.SortTransferableOutputs(uTx.Outs, codec) + + tx := &txs.Tx{Unsigned: uTx} if err := tx.SignSECP256K1Fx(codec, keys); err != nil { return err } From 1f95de4fa6c9275844c95b0b689d7cef809580b9 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 15 Feb 2024 16:26:01 +0100 Subject: [PATCH 11/53] nits --- vms/avm/service.go | 18 ++++++++++-------- vms/avm/service_test.go | 4 ++-- vms/avm/vm_regression_test.go | 3 +-- vms/avm/vm_test.go | 12 ++++-------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/vms/avm/service.go b/vms/avm/service.go index d11bc405860..99157fe1a29 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1411,17 +1411,20 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - return buildOperation(s.vm, ops, opKeys, feeUTXOs, feeKc, changeAddr) + tx, err := buildOperation(s.vm, ops, feeUTXOs, feeKc, changeAddr) + if err != nil { + return nil, ids.ShortEmpty, err + } + return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), opKeys) } func buildOperation( vm *VM, ops []*txs.Operation, - opsKeys [][]*secp256k1.PrivateKey, utxos []*avax.UTXO, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { +) (*txs.Tx, error) { uTx := &txs.OperationTx{ BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ NetworkID: vm.ctx.NetworkID, @@ -1440,14 +1443,13 @@ func buildOperation( changeAddr, ) if err != nil { - return nil, ids.ShortEmpty, err + return nil, err } uTx.Ins = ins uTx.Outs = outs tx := &txs.Tx{Unsigned: uTx} - keys = append(keys, opsKeys...) - return tx, changeAddr, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) + return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) } // SendNFTArgs are arguments for passing into SendNFT requests @@ -1529,7 +1531,7 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, _, err := buildOperation(s.vm, ops, nil, utxos, kc, changeAddr) + tx, err := buildOperation(s.vm, ops, utxos, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1625,7 +1627,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, _, err := buildOperation(s.vm, ops, nil, feeUTXOs, feeKc, changeAddr) + tx, err := buildOperation(s.vm, ops, feeUTXOs, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index dc3995c776c..0fa3b8983e0 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1823,15 +1823,15 @@ func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(t, err) - tx, _, err := buildOperation( + tx, err := buildOperation( env.vm, ops, - opsKeys, utxos, kc, key.Address(), ) require.NoError(t, err) + require.NoError(t, tx.SignSECP256K1Fx(env.vm.parser.Codec(), opsKeys)) return tx } diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 161e631156f..acaacd1785f 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -93,10 +93,9 @@ func TestVerifyFxUsage(t *testing.T) { ) require.NoError(err) - mintNFTTx, _, err := buildOperation( + mintNFTTx, err := buildOperation( env.vm, mintOp, - nil, utxos, kc, key.Address(), diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index cff92c6d8ad..4596789f451 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -189,10 +189,9 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) - mintNFTTx, _, err := buildOperation( + mintNFTTx, err := buildOperation( env.vm, mintOp, - nil, utxos, kc, key.Address(), @@ -213,10 +212,9 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) - transferNFTTx, _, err := buildOperation( + transferNFTTx, err := buildOperation( env.vm, transferOp, - nil, utxos, kc, key.Address(), @@ -302,10 +300,9 @@ func TestIssueProperty(t *testing.T) { }, } - mintPropertyTx, _, err := buildOperation( + mintPropertyTx, err := buildOperation( env.vm, []*txs.Operation{mintPropertyOp}, - nil, utxos, kc, key.Address(), @@ -328,10 +325,9 @@ func TestIssueProperty(t *testing.T) { Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, } - burnPropertyTx, _, err := buildOperation( + burnPropertyTx, err := buildOperation( env.vm, []*txs.Operation{burnPropertyOp}, - nil, utxos, kc, key.Address(), From a4b81e65e4757932d7add5bad19c5c275bff1fdf Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 20 Feb 2024 09:22:54 +0100 Subject: [PATCH 12/53] fork switch to the avm --- vms/avm/block/executor/block_test.go | 127 +++++------------- vms/avm/block/executor/manager_test.go | 27 +--- vms/avm/environment_test.go | 45 ++++++- vms/avm/index_test.go | 26 +--- vms/avm/service_test.go | 63 +++------ vms/avm/state_test.go | 3 + vms/avm/vm_benchmark_test.go | 3 +- vms/avm/vm_regression_test.go | 10 +- vms/avm/vm_test.go | 40 ++---- vms/avm/wallet_service_test.go | 1 + vms/platformvm/block/builder/helpers_test.go | 2 +- vms/platformvm/block/executor/helpers_test.go | 2 +- vms/platformvm/txs/executor/helpers_test.go | 2 +- vms/platformvm/vm_test.go | 2 +- 14 files changed, 122 insertions(+), 231 deletions(-) diff --git a/vms/avm/block/executor/block_test.go b/vms/avm/block/executor/block_test.go index 59200e5d88c..8b2e85a8378 100644 --- a/vms/avm/block/executor/block_test.go +++ b/vms/avm/block/executor/block_test.go @@ -30,6 +30,13 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" ) +var noFeesTestConfig = &config.Config{ + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, + TxFee: 0, + CreateAssetTxFee: 0, +} + func TestBlockVerify(t *testing.T) { type test struct { name string @@ -47,10 +54,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{}, }, @@ -72,10 +76,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, }, } @@ -97,10 +98,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, clk: clk, }, @@ -120,10 +118,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{}, clk: &mockable.Clock{}, @@ -152,10 +147,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), @@ -190,10 +182,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: mockState, blkIDToState: map[ids.ID]*blockState{}, @@ -232,10 +221,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: mockState, blkIDToState: map[ids.ID]*blockState{}, @@ -277,10 +263,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ parentID: { @@ -330,10 +313,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), @@ -388,10 +368,7 @@ func TestBlockVerify(t *testing.T) { mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ parentID: { @@ -471,10 +448,7 @@ func TestBlockVerify(t *testing.T) { mempool: mempool, metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ parentID: { @@ -534,10 +508,7 @@ func TestBlockVerify(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ parentID: { @@ -591,10 +562,7 @@ func TestBlockVerify(t *testing.T) { mempool: mockMempool, metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ parentID: { @@ -673,10 +641,7 @@ func TestBlockAccept(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{}, }, @@ -711,10 +676,7 @@ func TestBlockAccept(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -759,10 +721,7 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -811,10 +770,7 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -866,10 +822,7 @@ func TestBlockAccept(t *testing.T) { SharedMemory: mockSharedMemory, Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ blockID: { @@ -967,10 +920,7 @@ func TestBlockReject(t *testing.T) { metrics: metrics.NewMockMetrics(ctrl), backend: &executor.Backend{ Bootstrapped: true, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, Ctx: &snow.Context{ Log: logging.NoLog{}, }, @@ -1032,10 +982,7 @@ func TestBlockReject(t *testing.T) { Ctx: &snow.Context{ Log: logging.NoLog{}, }, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: mockState, blkIDToState: map[ids.ID]*blockState{ @@ -1086,10 +1033,7 @@ func TestBlockStatus(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, lastAccepted: blockID, }, @@ -1107,10 +1051,7 @@ func TestBlockStatus(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{ blockID: {}, @@ -1134,10 +1075,7 @@ func TestBlockStatus(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{}, state: mockState, @@ -1160,10 +1098,7 @@ func TestBlockStatus(t *testing.T) { Block: mockBlock, manager: &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, blkIDToState: map[ids.ID]*blockState{}, state: mockState, diff --git a/vms/avm/block/executor/manager_test.go b/vms/avm/block/executor/manager_test.go index 517ced98eaf..adf1650cc78 100644 --- a/vms/avm/block/executor/manager_test.go +++ b/vms/avm/block/executor/manager_test.go @@ -13,9 +13,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" @@ -126,10 +124,7 @@ func TestManagerVerifyTx(t *testing.T) { managerF: func(*gomock.Controller) *manager { return &manager{ backend: &executor.Backend{ - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, } }, @@ -148,10 +143,7 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, } }, @@ -180,10 +172,7 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: state, lastAccepted: lastAcceptedID, @@ -216,10 +205,7 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: state, lastAccepted: lastAcceptedID, @@ -252,10 +238,7 @@ func TestManagerVerifyTx(t *testing.T) { return &manager{ backend: &executor.Backend{ Bootstrapped: true, - Config: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + Config: noFeesTestConfig, }, state: state, lastAccepted: lastAcceptedID, diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index b4f3e899a41..a013ec4e039 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -6,6 +6,7 @@ package avm import ( "context" "encoding/json" + "fmt" "math/rand" "testing" "time" @@ -40,7 +41,12 @@ import ( keystoreutils "github.com/ava-labs/avalanchego/vms/components/keystore" ) +type fork uint8 + const ( + durango fork = iota + eUpgrade + testTxFee uint64 = 1000 startBalance uint64 = 50000 @@ -70,6 +76,13 @@ var ( keys = secp256k1.TestKeys()[:3] // TODO: Remove [:3] addrs []ids.ShortID // addrs[i] corresponds to keys[i] + + noFeesTestConfig = &config.Config{ + DurangoTime: time.Time{}, + EUpgradeTime: mockable.MaxTime, + TxFee: 0, + CreateAssetTxFee: 0, + } ) func init() { @@ -86,6 +99,7 @@ type user struct { } type envConfig struct { + fork fork isCustomFeeAsset bool keystoreUsers []*user vmStaticConfig *config.Config @@ -146,12 +160,7 @@ func setup(tb testing.TB, c *envConfig) *environment { require.NoError(keystoreUser.Close()) } - vmStaticConfig := config.Config{ - TxFee: testTxFee, - CreateAssetTxFee: testTxFee, - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - } + vmStaticConfig := staticConfig(tb, c.fork) if c.vmStaticConfig != nil { vmStaticConfig = *c.vmStaticConfig } @@ -224,6 +233,30 @@ func setup(tb testing.TB, c *envConfig) *environment { return env } +func staticConfig(tb testing.TB, f fork) config.Config { + var ( + durangoTime = mockable.MaxTime + eUpgradeTime = mockable.MaxTime + ) + + switch f { + case eUpgrade: + eUpgradeTime = time.Time{} + fallthrough + case durango: + durangoTime = time.Time{} + default: + require.FailNow(tb, fmt.Sprintf("unhandled fork %d", f)) + } + + return config.Config{ + TxFee: testTxFee, + CreateAssetTxFee: testTxFee, + DurangoTime: durangoTime, + EUpgradeTime: eUpgradeTime, + } +} + // Returns: // // 1. tx in genesis that creates asset diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 8ed1887b693..ef8a357935a 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -6,7 +6,6 @@ package avm import ( "context" "testing" - "time" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" @@ -20,8 +19,6 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/timer/mockable" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/index" @@ -31,12 +28,7 @@ import ( func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -78,12 +70,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -129,12 +116,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -175,7 +157,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { func TestIndexer_Read(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 00ec1c93e0c..c725658f839 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -28,10 +28,8 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -47,7 +45,7 @@ import ( func TestServiceIssueTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -73,7 +71,7 @@ func TestServiceIssueTx(t *testing.T) { func TestServiceGetTxStatus(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -108,7 +106,7 @@ func TestServiceGetTxStatus(t *testing.T) { func TestServiceGetBalanceStrict(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { env.vm.ctx.Lock.Lock() require.NoError(env.vm.Shutdown(context.Background())) @@ -264,7 +262,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { func TestServiceGetTxs(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) var err error env.vm.addressTxsIndexer, err = index.NewIndexer(env.vm.db, env.vm.ctx.Log, "", prometheus.NewRegistry(), false) require.NoError(err) @@ -306,7 +304,7 @@ func TestServiceGetTxs(t *testing.T) { func TestServiceGetAllBalances(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { env.vm.ctx.Lock.Lock() require.NoError(env.vm.Shutdown(context.Background())) @@ -504,7 +502,7 @@ func TestServiceGetAllBalances(t *testing.T) { func TestServiceGetTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -532,7 +530,7 @@ func TestServiceGetTx(t *testing.T) { func TestServiceGetTxJSON_BaseTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -615,7 +613,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { func TestServiceGetTxJSON_ExportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -700,10 +698,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -819,10 +814,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -921,10 +913,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1062,10 +1051,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1168,10 +1154,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1317,10 +1300,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1420,10 +1400,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1802,7 +1779,7 @@ func buildOperationTxWithOp(chainID ids.ID, op ...*txs.Operation) *txs.Tx { func TestServiceGetNilTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -1819,7 +1796,7 @@ func TestServiceGetNilTx(t *testing.T) { func TestServiceGetUnknownTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -1834,7 +1811,7 @@ func TestServiceGetUnknownTx(t *testing.T) { } func TestServiceGetUTXOs(t *testing.T) { - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { env.vm.ctx.Lock.Lock() require.NoError(t, env.vm.Shutdown(context.Background())) @@ -2089,7 +2066,7 @@ func TestServiceGetUTXOs(t *testing.T) { func TestGetAssetDescription(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -2112,7 +2089,7 @@ func TestGetAssetDescription(t *testing.T) { func TestGetBalance(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { diff --git a/vms/avm/state_test.go b/vms/avm/state_test.go index b17604b2ba6..4496ed54d80 100644 --- a/vms/avm/state_test.go +++ b/vms/avm/state_test.go @@ -24,6 +24,7 @@ func TestSetsAndGets(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + fork: durango, additionalFxs: []*common.Fx{{ ID: ids.GenerateTestID(), Fx: &FxTest{ @@ -86,6 +87,7 @@ func TestSetsAndGets(t *testing.T) { func TestFundingNoAddresses(t *testing.T) { env := setup(t, &envConfig{ + fork: durango, additionalFxs: []*common.Fx{{ ID: ids.GenerateTestID(), Fx: &FxTest{ @@ -118,6 +120,7 @@ func TestFundingAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + fork: durango, additionalFxs: []*common.Fx{{ ID: ids.GenerateTestID(), Fx: &FxTest{ diff --git a/vms/avm/vm_benchmark_test.go b/vms/avm/vm_benchmark_test.go index 713f809f7f5..4ac65c86d7d 100644 --- a/vms/avm/vm_benchmark_test.go +++ b/vms/avm/vm_benchmark_test.go @@ -23,6 +23,7 @@ func BenchmarkLoadUser(b *testing.B) { require := require.New(b) env := setup(b, &envConfig{ + fork: durango, keystoreUsers: []*user{{ username: username, password: password, @@ -67,7 +68,7 @@ func BenchmarkLoadUser(b *testing.B) { func GetAllUTXOsBenchmark(b *testing.B, utxoCount int) { require := require.New(b) - env := setup(b, &envConfig{}) + env := setup(b, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 2412c4e9a70..34d99dcc351 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -6,15 +6,12 @@ package avm import ( "context" "testing" - "time" "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/timer/mockable" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -25,12 +22,7 @@ import ( func TestVerifyFxUsage(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index a01aefd349d..527c2e98efe 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -7,7 +7,6 @@ import ( "context" "math" "testing" - "time" "github.com/stretchr/testify/require" @@ -20,8 +19,6 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/timer/mockable" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -117,7 +114,7 @@ func TestFxInitializationFailure(t *testing.T) { func TestIssueTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -133,12 +130,7 @@ func TestIssueTx(t *testing.T) { func TestIssueNFT(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -238,10 +230,7 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -334,6 +323,7 @@ func TestIssueTxWithFeeAsset(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + fork: durango, isCustomFeeAsset: true, }) env.vm.ctx.Lock.Unlock() @@ -352,6 +342,7 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + fork: durango, isCustomFeeAsset: true, }) env.vm.ctx.Lock.Unlock() @@ -411,7 +402,7 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { } func TestVMFormat(t *testing.T) { - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(t, env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -440,6 +431,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ + fork: durango, notLinearized: true, }) defer func() { @@ -527,12 +519,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { func TestIssueImportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - }) + env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -631,11 +618,8 @@ func TestForceAcceptImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - }, - notLinearized: true, + vmStaticConfig: noFeesTestConfig, + notLinearized: true, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -711,7 +695,7 @@ func TestImportTxNotState(t *testing.T) { func TestIssueExportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -786,7 +770,7 @@ func TestIssueExportTx(t *testing.T) { func TestClearForceAcceptedExportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index 7ffdccdaaa2..a71403fa385 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -18,6 +18,7 @@ func TestWalletService_SendMultiple(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { env := setup(t, &envConfig{ + fork: durango, isCustomFeeAsset: !tc.avaxAsset, keystoreUsers: []*user{{ username: username, diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index d75b5780e53..d07ab6140c0 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -334,7 +334,7 @@ func defaultConfig(t *testing.T, f fork) *config.Config { case apricotPhase3: apricotPhase3Time = defaultValidateEndTime default: - require.NoError(t, fmt.Errorf("unhandled fork %d", f)) + require.FailNow(t, fmt.Sprintf("unhandled fork %d", f)) } return &config.Config{ diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index a2cacb0f277..26cd8bd566a 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -358,7 +358,7 @@ func defaultConfig(t *testing.T, f fork) *config.Config { case apricotPhase3: apricotPhase3Time = defaultValidateEndTime default: - require.NoError(t, fmt.Errorf("unhandled fork %d", f)) + require.FailNow(t, fmt.Sprintf("unhandled fork %d", f)) } return &config.Config{ diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index ad8acaa859e..907829f901c 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -309,7 +309,7 @@ func defaultConfig(t *testing.T, f fork) *config.Config { case apricotPhase3: apricotPhase3Time = defaultValidateEndTime default: - require.NoError(t, fmt.Errorf("unhandled fork %d", f)) + require.FailNow(t, fmt.Sprintf("unhandled fork %d", f)) } return &config.Config{ diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 7f097436576..b1d6a73b645 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -235,7 +235,7 @@ func defaultVM(t *testing.T, f fork) (*VM, database.Database, *mutableSharedMemo case apricotPhase3: apricotPhase3Time = latestForkTime default: - require.NoError(fmt.Errorf("unhandled fork %d", f)) + require.FailNow(fmt.Sprintf("unhandled fork %d", f)) } vm := &VM{Config: config.Config{ From a8d8111062f8c7c0fef03d5e7ae45904943d316f Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 22 Feb 2024 12:07:59 +0100 Subject: [PATCH 13/53] repackaged x-chain wallet backends --- indexer/examples/x-chain-blocks/main.go | 4 +- wallet/chain/x/backend.go | 9 +- wallet/chain/x/backends/backends.go | 26 ++++++ wallet/chain/x/{ => backends}/builder.go | 14 +-- wallet/chain/x/{ => backends}/constants.go | 2 +- wallet/chain/x/backends/context.go | 81 ++++++++++++++++++ wallet/chain/x/{ => backends}/signer.go | 8 +- .../chain/x/{ => backends}/signer_visitor.go | 2 +- wallet/chain/x/builder_test.go | 19 +++-- wallet/chain/x/builder_with_options.go | 7 +- wallet/chain/x/context.go | 85 ++----------------- wallet/chain/x/wallet.go | 21 ++--- wallet/chain/x/wallet_with_options.go | 3 +- wallet/subnet/primary/api.go | 5 +- .../examples/get-x-chain-balance/main.go | 4 +- wallet/subnet/primary/wallet.go | 6 +- 16 files changed, 162 insertions(+), 134 deletions(-) create mode 100644 wallet/chain/x/backends/backends.go rename wallet/chain/x/{ => backends}/builder.go (98%) rename wallet/chain/x/{ => backends}/constants.go (97%) create mode 100644 wallet/chain/x/backends/context.go rename wallet/chain/x/{ => backends}/signer.go (85%) rename wallet/chain/x/{ => backends}/signer_visitor.go (99%) diff --git a/indexer/examples/x-chain-blocks/main.go b/indexer/examples/x-chain-blocks/main.go index 2687e5a03c6..3bdbc8d00a8 100644 --- a/indexer/examples/x-chain-blocks/main.go +++ b/indexer/examples/x-chain-blocks/main.go @@ -11,7 +11,7 @@ import ( "github.com/ava-labs/avalanchego/indexer" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/avalanchego/vms/proposervm/block" - "github.com/ava-labs/avalanchego/wallet/chain/x" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary" ) @@ -38,7 +38,7 @@ func main() { } avmBlockBytes := proposerVMBlock.Block() - avmBlock, err := x.Parser.ParseBlock(avmBlockBytes) + avmBlock, err := backends.Parser.ParseBlock(avmBlockBytes) if err != nil { log.Fatalf("failed to parse avm block: %s\n", err) } diff --git a/wallet/chain/x/backend.go b/wallet/chain/x/backend.go index a87e799fa91..803387f59e7 100644 --- a/wallet/chain/x/backend.go +++ b/wallet/chain/x/backend.go @@ -5,6 +5,7 @@ package x import ( "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" stdcontext "context" @@ -15,18 +16,18 @@ var _ Backend = (*backend)(nil) // Backend defines the full interface required to support an X-chain wallet. type Backend interface { common.ChainUTXOs - BuilderBackend - SignerBackend + backends.BuilderBackend + backends.SignerBackend AcceptTx(ctx stdcontext.Context, tx *txs.Tx) error } type backend struct { - Context + backends.Context common.ChainUTXOs } -func NewBackend(ctx Context, utxos common.ChainUTXOs) Backend { +func NewBackend(ctx backends.Context, utxos common.ChainUTXOs) Backend { return &backend{ Context: ctx, ChainUTXOs: utxos, diff --git a/wallet/chain/x/backends/backends.go b/wallet/chain/x/backends/backends.go new file mode 100644 index 00000000000..86136b5de4d --- /dev/null +++ b/wallet/chain/x/backends/backends.go @@ -0,0 +1,26 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package backends + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/components/avax" + + stdcontext "context" +) + +type Backend interface { + BuilderBackend + SignerBackend +} + +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} diff --git a/wallet/chain/x/builder.go b/wallet/chain/x/backends/builder.go similarity index 98% rename from wallet/chain/x/builder.go rename to wallet/chain/x/backends/builder.go index 330ed69a250..cc216f65bb0 100644 --- a/wallet/chain/x/builder.go +++ b/wallet/chain/x/backends/builder.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package x +package backends import ( "errors" @@ -18,8 +18,6 @@ import ( "github.com/ava-labs/avalanchego/vms/propertyfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - - stdcontext "context" ) var ( @@ -154,14 +152,6 @@ type Builder interface { ) (*txs.ExportTx, error) } -// BuilderBackend specifies the required information needed to build unsigned -// X-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -} - type builder struct { addrs set.Set[ids.ShortID] backend BuilderBackend @@ -868,7 +858,7 @@ func (b *builder) burnProperty( } func (b *builder) initCtx(tx txs.UnsignedTx) error { - ctx, err := newSnowContext(b.backend) + ctx, err := NewSnowContext(b.backend) if err != nil { return err } diff --git a/wallet/chain/x/constants.go b/wallet/chain/x/backends/constants.go similarity index 97% rename from wallet/chain/x/constants.go rename to wallet/chain/x/backends/constants.go index 47efbfc2ff6..60dbec5e061 100644 --- a/wallet/chain/x/constants.go +++ b/wallet/chain/x/backends/constants.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package x +package backends import ( "time" diff --git a/wallet/chain/x/backends/context.go b/wallet/chain/x/backends/context.go new file mode 100644 index 00000000000..5100768f5bb --- /dev/null +++ b/wallet/chain/x/backends/context.go @@ -0,0 +1,81 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package backends + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/logging" +) + +const Alias = "X" + +var _ Context = (*context)(nil) + +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID + BaseTxFee() uint64 + CreateAssetTxFee() uint64 +} + +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID + baseTxFee uint64 + createAssetTxFee uint64 +} + +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, + baseTxFee uint64, + createAssetTxFee uint64, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + baseTxFee: baseTxFee, + createAssetTxFee: createAssetTxFee, + } +} + +func (c *context) NetworkID() uint32 { + return c.networkID +} + +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} + +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} + +func (c *context) BaseTxFee() uint64 { + return c.baseTxFee +} + +func (c *context) CreateAssetTxFee() uint64 { + return c.createAssetTxFee +} + +func NewSnowContext(c Context) (*snow.Context, error) { + chainID := c.BlockchainID() + lookup := ids.NewAliaser() + return &snow.Context{ + NetworkID: c.NetworkID(), + SubnetID: constants.PrimaryNetworkID, + ChainID: chainID, + XChainID: chainID, + AVAXAssetID: c.AVAXAssetID(), + Log: logging.NoLog{}, + BCLookup: lookup, + }, lookup.Alias(chainID, Alias) +} diff --git a/wallet/chain/x/signer.go b/wallet/chain/x/backends/signer.go similarity index 85% rename from wallet/chain/x/signer.go rename to wallet/chain/x/backends/signer.go index 9bc8734e46c..13b4210fbb4 100644 --- a/wallet/chain/x/signer.go +++ b/wallet/chain/x/backends/signer.go @@ -1,13 +1,11 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package x +package backends import ( - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/components/avax" stdcontext "context" ) @@ -26,10 +24,6 @@ type Signer interface { Sign(ctx stdcontext.Context, tx *txs.Tx) error } -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - type signer struct { kc keychain.Keychain backend SignerBackend diff --git a/wallet/chain/x/signer_visitor.go b/wallet/chain/x/backends/signer_visitor.go similarity index 99% rename from wallet/chain/x/signer_visitor.go rename to wallet/chain/x/backends/signer_visitor.go index be442f5511f..74f74a4e8fe 100644 --- a/wallet/chain/x/signer_visitor.go +++ b/wallet/chain/x/backends/signer_visitor.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package x +package backends import ( "errors" diff --git a/wallet/chain/x/builder_test.go b/wallet/chain/x/builder_test.go index f4eb916b693..a8cc1ec1c4d 100644 --- a/wallet/chain/x/builder_test.go +++ b/wallet/chain/x/builder_test.go @@ -18,6 +18,7 @@ import ( "github.com/ava-labs/avalanchego/vms/nftfx" "github.com/ava-labs/avalanchego/vms/propertyfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) @@ -31,7 +32,7 @@ var ( nftAssetID = ids.Empty.Prefix(2022) propertyAssetID = ids.Empty.Prefix(2023) - testCtx = NewContext( + testCtx = backends.NewContext( constants.UnitTestID, xChainID, avaxAssetID, @@ -60,7 +61,7 @@ func TestBaseTx(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction outputsToMove = []*avax.TransferableOutput{{ @@ -109,7 +110,7 @@ func TestCreateAssetTx(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction assetName = "Team Rocket" @@ -198,7 +199,7 @@ func TestMintNFTOperation(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction payload = []byte{'h', 'e', 'l', 'l', 'o'} @@ -243,7 +244,7 @@ func TestMintFTOperation(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction outputs = map[ids.ID]*secp256k1fx.TransferOutput{ @@ -290,7 +291,7 @@ func TestMintPropertyOperation(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction propertyOwner = &secp256k1fx.OutputOwners{ @@ -333,7 +334,7 @@ func TestBurnPropertyOperation(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) ) utx, err := builder.NewOperationTxBurnProperty( @@ -373,7 +374,7 @@ func TestImportTx(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction importKey = testKeys[0] @@ -421,7 +422,7 @@ func TestExportTx(t *testing.T) { // builder utxoAddr = utxosKey.Address() - builder = NewBuilder(set.Of(utxoAddr), backend) + builder = backends.NewBuilder(set.Of(utxoAddr), backend) // data to build the transaction subnetID = ids.GenerateTestID() diff --git a/wallet/chain/x/builder_with_options.go b/wallet/chain/x/builder_with_options.go index c2b65b05a63..316464079c9 100644 --- a/wallet/chain/x/builder_with_options.go +++ b/wallet/chain/x/builder_with_options.go @@ -9,13 +9,14 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) -var _ Builder = (*builderWithOptions)(nil) +var _ backends.Builder = (*builderWithOptions)(nil) type builderWithOptions struct { - Builder + backends.Builder options []common.Option } @@ -26,7 +27,7 @@ type builderWithOptions struct { // operations. // - [options] will be provided to the builder in addition to the options // provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +func NewBuilderWithOptions(builder backends.Builder, options ...common.Option) backends.Builder { return &builderWithOptions{ Builder: builder, options: options, diff --git a/wallet/chain/x/context.go b/wallet/chain/x/context.go index 7218bc8c143..d76d34a6cf3 100644 --- a/wallet/chain/x/context.go +++ b/wallet/chain/x/context.go @@ -5,38 +5,15 @@ package x import ( "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/avm" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" stdcontext "context" ) -const Alias = "X" - -var _ Context = (*context)(nil) - -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID - BaseTxFee() uint64 - CreateAssetTxFee() uint64 -} - -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID - baseTxFee uint64 - createAssetTxFee uint64 -} - -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +func NewContextFromURI(ctx stdcontext.Context, uri string) (backends.Context, error) { infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, Alias) + xChainClient := avm.NewClient(uri, backends.Alias) return NewContextFromClients(ctx, infoClient, xChainClient) } @@ -44,13 +21,13 @@ func NewContextFromClients( ctx stdcontext.Context, infoClient info.Client, xChainClient avm.Client, -) (Context, error) { +) (backends.Context, error) { networkID, err := infoClient.GetNetworkID(ctx) if err != nil { return nil, err } - chainID, err := infoClient.GetBlockchainID(ctx, Alias) + chainID, err := infoClient.GetBlockchainID(ctx, backends.Alias) if err != nil { return nil, err } @@ -65,7 +42,7 @@ func NewContextFromClients( return nil, err } - return NewContext( + return backends.NewContext( networkID, chainID, asset.AssetID, @@ -73,53 +50,3 @@ func NewContextFromClients( uint64(txFees.CreateAssetTxFee), ), nil } - -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, - baseTxFee uint64, - createAssetTxFee uint64, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - baseTxFee: baseTxFee, - createAssetTxFee: createAssetTxFee, - } -} - -func (c *context) NetworkID() uint32 { - return c.networkID -} - -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} - -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} - -func (c *context) BaseTxFee() uint64 { - return c.baseTxFee -} - -func (c *context) CreateAssetTxFee() uint64 { - return c.createAssetTxFee -} - -func newSnowContext(c Context) (*snow.Context, error) { - chainID := c.BlockchainID() - lookup := ids.NewAliaser() - return &snow.Context{ - NetworkID: c.NetworkID(), - SubnetID: constants.PrimaryNetworkID, - ChainID: chainID, - XChainID: chainID, - AVAXAssetID: c.AVAXAssetID(), - Log: logging.NoLog{}, - BCLookup: lookup, - }, lookup.Alias(chainID, Alias) -} diff --git a/wallet/chain/x/wallet.go b/wallet/chain/x/wallet.go index 13491a24134..9331f98074c 100644 --- a/wallet/chain/x/wallet.go +++ b/wallet/chain/x/wallet.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) @@ -23,13 +24,13 @@ var ( ) type Wallet interface { - Context + backends.Context // Builder returns the builder that will be used to create the transactions. - Builder() Builder + Builder() backends.Builder // Signer returns the signer that will be used to sign the transactions. - Signer() Signer + Signer() backends.Signer // IssueBaseTx creates, signs, and issues a new simple value transfer. // @@ -145,8 +146,8 @@ type Wallet interface { } func NewWallet( - builder Builder, - signer Signer, + builder backends.Builder, + signer backends.Signer, client avm.Client, backend Backend, ) Wallet { @@ -160,16 +161,16 @@ func NewWallet( type wallet struct { Backend - builder Builder - signer Signer + builder backends.Builder + signer backends.Signer client avm.Client } -func (w *wallet) Builder() Builder { +func (w *wallet) Builder() backends.Builder { return w.builder } -func (w *wallet) Signer() Signer { +func (w *wallet) Signer() backends.Signer { return w.signer } @@ -286,7 +287,7 @@ func (w *wallet) IssueUnsignedTx( ) (*txs.Tx, error) { ops := common.NewOptions(options) ctx := ops.Context() - tx, err := SignUnsigned(ctx, w.signer, utx) + tx, err := backends.SignUnsigned(ctx, w.signer, utx) if err != nil { return nil, err } diff --git a/wallet/chain/x/wallet_with_options.go b/wallet/chain/x/wallet_with_options.go index d62d02efdd4..bc6e7683fdc 100644 --- a/wallet/chain/x/wallet_with_options.go +++ b/wallet/chain/x/wallet_with_options.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) @@ -29,7 +30,7 @@ type walletWithOptions struct { options []common.Option } -func (w *walletWithOptions) Builder() Builder { +func (w *walletWithOptions) Builder() backends.Builder { return NewBuilderWithOptions( w.Wallet.Builder(), w.options..., diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3c30b60d81c..64c80fc5a38 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -24,6 +24,7 @@ import ( "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" + xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" walletcommon "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ethcommon "github.com/ethereum/go-ethereum/common" ) @@ -59,7 +60,7 @@ type AVAXState struct { PClient platformvm.Client PCTX p.Context XClient avm.Client - XCTX x.Context + XCTX xbackends.Context CClient evm.Client CCTX c.Context UTXOs walletcommon.UTXOs @@ -108,7 +109,7 @@ func FetchState( { id: xCTX.BlockchainID(), client: xClient, - codec: x.Parser.Codec(), + codec: xbackends.Parser.Codec(), }, { id: cCTX.BlockchainID(), diff --git a/wallet/subnet/primary/examples/get-x-chain-balance/main.go b/wallet/subnet/primary/examples/get-x-chain-balance/main.go index 9895546879e..03e158ccf6d 100644 --- a/wallet/subnet/primary/examples/get-x-chain-balance/main.go +++ b/wallet/subnet/primary/examples/get-x-chain-balance/main.go @@ -13,6 +13,8 @@ import ( "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ) func main() { @@ -39,7 +41,7 @@ func main() { xUTXOs := common.NewChainUTXOs(xChainID, state.UTXOs) xBackend := x.NewBackend(state.XCTX, xUTXOs) - xBuilder := x.NewBuilder(addresses, xBackend) + xBuilder := xbackends.NewBuilder(addresses, xBackend) currentBalances, err := xBuilder.GetFTBalance() if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 9aabf651cff..a51ea67098e 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -15,6 +15,8 @@ import ( "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ) var _ Wallet = (*wallet)(nil) @@ -124,8 +126,8 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xChainID := avaxState.XCTX.BlockchainID() xUTXOs := common.NewChainUTXOs(xChainID, avaxState.UTXOs) xBackend := x.NewBackend(avaxState.XCTX, xUTXOs) - xBuilder := x.NewBuilder(avaxAddrs, xBackend) - xSigner := x.NewSigner(config.AVAXKeychain, xBackend) + xBuilder := xbackends.NewBuilder(avaxAddrs, xBackend) + xSigner := xbackends.NewSigner(config.AVAXKeychain, xBackend) cChainID := avaxState.CCTX.BlockchainID() cUTXOs := common.NewChainUTXOs(cChainID, avaxState.UTXOs) From 1d61776eb2825d812935e52bd034b036aa3b3d02 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 22 Feb 2024 22:28:39 +0100 Subject: [PATCH 14/53] minor repackaging --- vms/avm/service.go | 181 ------------------------------ vms/avm/service_tx_builders.go | 196 +++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 181 deletions(-) create mode 100644 vms/avm/service_tx_builders.go diff --git a/vms/avm/service.go b/vms/avm/service.go index 99157fe1a29..54c1fff5001 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -1271,52 +1271,6 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI return buildBaseTx(s.vm, outs, memoBytes, utxos, kc, changeAddr) } -func buildBaseTx( - vm *VM, - outs []*avax.TransferableOutput, - memo []byte, - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { - uTx := &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - Memo: memo, - Outs: outs, - }, - } - - toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees - for _, out := range outs { - toBurn[out.AssetID()] += out.Out.Amount() - } - amountWithFee, err := safemath.Add64(toBurn[vm.feeAssetID], vm.TxFee) - if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) - } - toBurn[vm.feeAssetID] = amountWithFee - - ins, feeOuts, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - uTx.Ins = ins - uTx.Outs = append(uTx.Outs, feeOuts...) - codec := vm.parser.Codec() - avax.SortTransferableOutputs(uTx.Outs, codec) - - tx := &txs.Tx{Unsigned: uTx} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) -} - // MintArgs are arguments for passing into Mint requests type MintArgs struct { api.JSONSpendHeader // User, password, from addrs, change addr @@ -1418,40 +1372,6 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), opKeys) } -func buildOperation( - vm *VM, - ops []*txs.Operation, - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - changeAddr ids.ShortID, -) (*txs.Tx, error) { - uTx := &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - Ops: ops, - } - - toBurn := map[ids.ID]uint64{ - vm.feeAssetID: vm.TxFee, - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) - if err != nil { - return nil, err - } - - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) -} - // SendNFTArgs are arguments for passing into SendNFT requests type SendNFTArgs struct { api.JSONSpendHeader // User, password, from addrs, change addr @@ -1697,50 +1617,6 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return buildImportTx(s.vm, chainID, atomicUTXOs, to, utxos, kc) } -func buildImportTx( - vm *VM, - sourceChain ids.ID, - atomicUTXOs []*avax.UTXO, - to ids.ShortID, - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, -) (*txs.Tx, error) { - toBurn, importInputs, importKeys, err := vm.SpendAll(atomicUTXOs, kc) - if err != nil { - return nil, err - } - - uTx := &txs.ImportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - SourceChain: sourceChain, - ImportedIns: importInputs, - } - - if importedAmt := toBurn[vm.feeAssetID]; importedAmt < vm.TxFee { - toBurn[vm.feeAssetID] = vm.TxFee - importedAmt - } else { - toBurn[vm.feeAssetID] = importedAmt - vm.TxFee - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - to, - ) - if err != nil { - return nil, err - } - keys = append(keys, importKeys...) - - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) -} - // ExportArgs are arguments for passing into ExportAVA requests type ExportArgs struct { // User, password, from addrs, change addr @@ -1833,60 +1709,3 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return buildExportTx(s.vm, chainID, to, assetID, uint64(args.Amount), utxos, kc, changeAddr) } - -func buildExportTx( - vm *VM, - destinationChain ids.ID, - to ids.ShortID, - exportedAssetID ids.ID, - exportedAmt uint64, - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { - uTx := &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - DestinationChain: destinationChain, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: exportedAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: exportedAmt, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, - }, - }}, - } - toBurn := map[ids.ID]uint64{} - if exportedAssetID == vm.feeAssetID { - amountWithFee, err := safemath.Add64(exportedAmt, vm.TxFee) - if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) - } - toBurn[vm.feeAssetID] = amountWithFee - } else { - toBurn[exportedAssetID] = exportedAmt - toBurn[vm.feeAssetID] = vm.TxFee - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - codec := vm.parser.Codec() - - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) -} diff --git a/vms/avm/service_tx_builders.go b/vms/avm/service_tx_builders.go new file mode 100644 index 00000000000..cae7f194082 --- /dev/null +++ b/vms/avm/service_tx_builders.go @@ -0,0 +1,196 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package avm + +import ( + "fmt" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + + safemath "github.com/ava-labs/avalanchego/utils/math" +) + +func buildBaseTx( + vm *VM, + outs []*avax.TransferableOutput, + memo []byte, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + Memo: memo, + Outs: outs, + }, + } + + toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees + for _, out := range outs { + toBurn[out.AssetID()] += out.Out.Amount() + } + amountWithFee, err := safemath.Add64(toBurn[vm.feeAssetID], vm.TxFee) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) + } + toBurn[vm.feeAssetID] = amountWithFee + + ins, feeOuts, keys, err := vm.Spend( + utxos, + kc, + toBurn, + changeAddr, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + uTx.Ins = ins + uTx.Outs = append(uTx.Outs, feeOuts...) + codec := vm.parser.Codec() + avax.SortTransferableOutputs(uTx.Outs, codec) + + tx := &txs.Tx{Unsigned: uTx} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) +} + +func buildOperation( + vm *VM, + ops []*txs.Operation, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, error) { + uTx := &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + }}, + Ops: ops, + } + + toBurn := map[ids.ID]uint64{ + vm.feeAssetID: vm.TxFee, + } + ins, outs, keys, err := vm.Spend( + utxos, + kc, + toBurn, + changeAddr, + ) + if err != nil { + return nil, err + } + + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) +} + +func buildImportTx( + vm *VM, + sourceChain ids.ID, + atomicUTXOs []*avax.UTXO, + to ids.ShortID, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, +) (*txs.Tx, error) { + toBurn, importInputs, importKeys, err := vm.SpendAll(atomicUTXOs, kc) + if err != nil { + return nil, err + } + + uTx := &txs.ImportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + }}, + SourceChain: sourceChain, + ImportedIns: importInputs, + } + + if importedAmt := toBurn[vm.feeAssetID]; importedAmt < vm.TxFee { + toBurn[vm.feeAssetID] = vm.TxFee - importedAmt + } else { + toBurn[vm.feeAssetID] = importedAmt - vm.TxFee + } + ins, outs, keys, err := vm.Spend( + utxos, + kc, + toBurn, + to, + ) + if err != nil { + return nil, err + } + keys = append(keys, importKeys...) + + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) +} + +func buildExportTx( + vm *VM, + destinationChain ids.ID, + to ids.ShortID, + exportedAssetID ids.ID, + exportedAmt uint64, + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + uTx := &txs.ExportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.ChainID, + }}, + DestinationChain: destinationChain, + ExportedOuts: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: exportedAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: exportedAmt, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, + }, + }}, + } + toBurn := map[ids.ID]uint64{} + if exportedAssetID == vm.feeAssetID { + amountWithFee, err := safemath.Add64(exportedAmt, vm.TxFee) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) + } + toBurn[vm.feeAssetID] = amountWithFee + } else { + toBurn[exportedAssetID] = exportedAmt + toBurn[vm.feeAssetID] = vm.TxFee + } + ins, outs, keys, err := vm.Spend( + utxos, + kc, + toBurn, + changeAddr, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + codec := vm.parser.Codec() + + uTx.Ins = ins + uTx.Outs = outs + tx := &txs.Tx{Unsigned: uTx} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) +} From d975933d5df4d27c8c61a1aac837d96349aa7cc3 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 22 Feb 2024 23:10:23 +0100 Subject: [PATCH 15/53] wip: consolidating tx building --- vms/avm/service.go | 129 +++++--------- vms/avm/service_test.go | 139 +++++++-------- vms/avm/service_tx_builders.go | 227 +++++++++++-------------- vms/avm/service_tx_builders_backend.go | 83 +++++++++ vms/avm/tx.go | 4 +- vms/avm/vm.go | 17 +- vms/avm/vm_regression_test.go | 70 ++++---- vms/avm/vm_test.go | 141 ++++++--------- 8 files changed, 387 insertions(+), 423 deletions(-) create mode 100644 vms/avm/service_tx_builders_backend.go diff --git a/vms/avm/service.go b/vms/avm/service.go index 54c1fff5001..1cb24fa037d 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -739,7 +739,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -753,16 +753,17 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI return nil, ids.ShortEmpty, err } - initialState := &txs.InitialState{ - FxIndex: 0, // TODO: Should lookup secp256k1fx FxID - Outs: make([]verify.State, 0, len(args.InitialHolders)+len(args.MinterSets)), - } + var ( + fxIndex = uint32(0) // TODO: Should lookup secp256k1fx FxID + initialStateOuts = make([]verify.State, 0, len(args.InitialHolders)+len(args.MinterSets)) + ) + for _, holder := range args.InitialHolders { addr, err := avax.ParseServiceAddress(s.vm, holder.Address) if err != nil { return nil, ids.ShortEmpty, err } - initialState.Outs = append(initialState.Outs, &secp256k1fx.TransferOutput{ + initialStateOuts = append(initialStateOuts, &secp256k1fx.TransferOutput{ Amt: uint64(holder.Amount), OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -783,63 +784,21 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI } minter.Addrs = minterAddrsSet.List() utils.Sort(minter.Addrs) - initialState.Outs = append(initialState.Outs, minter) + initialStateOuts = append(initialStateOuts, minter) } - codec := s.vm.parser.Codec() - initialState.Sort(codec) - + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) return buildCreateAssetTx( - s.vm, + s.vm.txBuilderBackend, args.Name, args.Symbol, args.Denomination, - []*txs.InitialState{initialState}, - utxos, + map[uint32][]verify.State{fxIndex: initialStateOuts}, kc, changeAddr, ) } -func buildCreateAssetTx( - vm *VM, - name, symbol string, - denomination byte, - initialStates []*txs.InitialState, - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { - uTx := &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - Name: name, - Symbol: symbol, - Denomination: denomination, - States: initialStates, - } - - toBurn := map[ids.ID]uint64{ - vm.feeAssetID: vm.CreateAssetTxFee, - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) - if err != nil { - return nil, ids.ShortEmpty, err - } - - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, changeAddr, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) -} - // CreateFixedCapAsset returns ID of the newly created asset func (s *Service) CreateFixedCapAsset(r *http.Request, args *CreateAssetArgs, reply *AssetIDChangeAddr) error { s.vm.ctx.Log.Warn("deprecated API called", @@ -914,7 +873,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -928,10 +887,11 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh return nil, ids.ShortEmpty, err } - initialState := &txs.InitialState{ - FxIndex: 1, // TODO: Should lookup nftfx FxID - Outs: make([]verify.State, 0, len(args.MinterSets)), - } + var ( + fxIndex = uint32(1) // TODO: Should lookup nftfx FxID + initialStateOuts = make([]verify.State, 0, len(args.MinterSets)) + ) + for i, owner := range args.MinterSets { minter := &nftfx.MintOutput{ GroupID: uint32(i), @@ -945,18 +905,16 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh } minter.Addrs = minterAddrsSet.List() utils.Sort(minter.Addrs) - initialState.Outs = append(initialState.Outs, minter) + initialStateOuts = append(initialStateOuts, minter) } - codec := s.vm.parser.Codec() - initialState.Sort(codec) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) return buildCreateAssetTx( - s.vm, + s.vm.txBuilderBackend, args.Name, args.Symbol, 0, // NFTs are non-fungible - []*txs.InitialState{initialState}, - utxos, + map[uint32][]verify.State{fxIndex: initialStateOuts}, kc, changeAddr, ) @@ -1208,7 +1166,7 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI defer s.vm.ctx.Lock.Unlock() // Load user's UTXOs/keys - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1268,7 +1226,8 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - return buildBaseTx(s.vm, outs, memoBytes, utxos, kc, changeAddr) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildBaseTx(s.vm.txBuilderBackend, outs, memoBytes, kc, changeAddr) } // MintArgs are arguments for passing into Mint requests @@ -1333,7 +1292,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - feeUTXOs, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1353,7 +1312,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - ops, opKeys, err := s.vm.Mint( + ops, _, err := s.vm.Mint( utxos, kc, map[ids.ID]uint64{ @@ -1365,11 +1324,12 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - tx, err := buildOperation(s.vm, ops, feeUTXOs, feeKc, changeAddr) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildOperation(s.vm.txBuilderBackend, ops, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), opKeys) + return tx, changeAddr, nil } // SendNFTArgs are arguments for passing into SendNFT requests @@ -1440,7 +1400,7 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - ops, nftKeys, err := s.vm.SpendNFT( + ops, _, err := s.vm.SpendNFT( utxos, kc, assetID, @@ -1451,12 +1411,13 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, err := buildOperation(s.vm, ops, utxos, kc, changeAddr) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildOperation(s.vm.txBuilderBackend, ops, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys) + return tx, changeAddr, nil } // MintNFTArgs are arguments for passing into MintNFT requests @@ -1517,7 +1478,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - feeUTXOs, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1536,7 +1497,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) if err != nil { return nil, ids.ShortEmpty, err } - ops, nftKeys, err := s.vm.MintNFT( + ops, _, err := s.vm.MintNFT( utxos, kc, assetID, @@ -1547,11 +1508,12 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, err := buildOperation(s.vm, ops, feeUTXOs, feeKc, changeAddr) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildOperation(s.vm.txBuilderBackend, ops, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, tx.SignNFTFx(s.vm.parser.Codec(), nftKeys) + return tx, changeAddr, nil } // ImportArgs are arguments for passing into Import requests @@ -1604,17 +1566,13 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { s.vm.ctx.Lock.Lock() defer s.vm.ctx.Lock.Unlock() - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, err } - atomicUTXOs, _, _, err := s.vm.GetAtomicUTXOs(chainID, kc.Addrs, ids.ShortEmpty, ids.Empty, int(maxPageSize)) - if err != nil { - return nil, fmt.Errorf("problem retrieving user's atomic UTXOs: %w", err) - } - - return buildImportTx(s.vm, chainID, atomicUTXOs, to, utxos, kc) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildImportTx(s.vm.txBuilderBackend, chainID, to, kc) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1693,7 +1651,7 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1707,5 +1665,6 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - return buildExportTx(s.vm, chainID, to, assetID, uint64(args.Amount), utxos, kc, changeAddr) + s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildExportTx(s.vm.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 0fa3b8983e0..ac11dfad4c8 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -899,8 +899,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildNFTxMintOp(createAssetTx, key, 2, 1) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil) - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -1002,8 +1001,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}, nil) - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -1140,7 +1138,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildSecpMintOp(createAssetTx, key, 0) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, [][]*secp256k1.PrivateKey{{key}}) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1246,7 +1244,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { op1 := buildSecpMintOp(createAssetTx, key, 0) op2 := buildSecpMintOp(createAssetTx, key, 1) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, [][]*secp256k1.PrivateKey{{key}, {key}}) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1391,8 +1389,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildPropertyFxMintOp(createAssetTx, key, 4) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}, nil) - require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1495,8 +1492,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) op1 := buildPropertyFxMintOp(createAssetTx, key, 4) op2 := buildPropertyFxMintOp(createAssetTx, key, 5) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}, nil) - require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1619,11 +1615,10 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { kc = secp256k1fx.NewKeychain() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(t, err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildBaseTx( - env.vm, + env.vm.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.vm.feeAssetID}, Out: &secp256k1fx.TransferOutput{ @@ -1635,7 +1630,6 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { }, }}, memo, - utxos, kc, changeKey.PublicKey().Address(), ) @@ -1649,68 +1643,59 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { kc = secp256k1fx.NewKeychain() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(t, err) - tx, _, err := buildCreateAssetTx( - env.vm, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, + + initialStates := map[uint32][]verify.State{ + uint32(0): { + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - { - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - { - FxIndex: 2, - Outs: []verify.State{ - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, }, - utxos, + } + + tx, _, err := buildCreateAssetTx( + env.vm.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, kc, key.Address(), ) @@ -1725,15 +1710,14 @@ func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { to = key.PublicKey().Address() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(t, err) + + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm, + env.vm.txBuilderBackend, chainID, to, env.vm.feeAssetID, units.MicroAvax, - utxos, kc, key.Address(), ) @@ -1814,24 +1798,21 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd } } -func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation, opsKeys [][]*secp256k1.PrivateKey) *txs.Tx { +func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation) *txs.Tx { var ( key = keys[0] kc = secp256k1fx.NewKeychain() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(t, err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, ops, - utxos, kc, key.Address(), ) require.NoError(t, err) - require.NoError(t, tx.SignSECP256K1Fx(env.vm.parser.Codec(), opsKeys)) return tx } diff --git a/vms/avm/service_tx_builders.go b/vms/avm/service_tx_builders.go index cae7f194082..6d9bf3c6e4c 100644 --- a/vms/avm/service_tx_builders.go +++ b/vms/avm/service_tx_builders.go @@ -4,193 +4,172 @@ package avm import ( + "context" "fmt" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - safemath "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) +func buildCreateAssetTx( + backend *Backend, + name, symbol string, + denomination byte, + initialStates map[uint32][]verify.State, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, ids.ShortID, error) { + pBuilder, pSigner := builders(backend, kc) + + utx, err := pBuilder.NewCreateAssetTx( + name, + symbol, + denomination, + initialStates, + options(changeAddr, nil /*memo*/)..., + ) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) + } + + tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) + if err != nil { + return nil, ids.ShortEmpty, err + } + + return tx, changeAddr, nil +} + func buildBaseTx( - vm *VM, + backend *Backend, outs []*avax.TransferableOutput, memo []byte, - utxos []*avax.UTXO, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - uTx := &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - Memo: memo, - Outs: outs, - }, - } + pBuilder, pSigner := builders(backend, kc) - toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees - for _, out := range outs { - toBurn[out.AssetID()] += out.Out.Amount() - } - amountWithFee, err := safemath.Add64(toBurn[vm.feeAssetID], vm.TxFee) + utx, err := pBuilder.NewBaseTx( + outs, + options(changeAddr, memo)..., + ) if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) + return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) } - toBurn[vm.feeAssetID] = amountWithFee - ins, feeOuts, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) + tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } - uTx.Ins = ins - uTx.Outs = append(uTx.Outs, feeOuts...) - codec := vm.parser.Codec() - avax.SortTransferableOutputs(uTx.Outs, codec) - - tx := &txs.Tx{Unsigned: uTx} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) + return tx, changeAddr, nil } func buildOperation( - vm *VM, + backend *Backend, ops []*txs.Operation, - utxos []*avax.UTXO, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - uTx := &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - Ops: ops, - } + pBuilder, pSigner := builders(backend, kc) - toBurn := map[ids.ID]uint64{ - vm.feeAssetID: vm.TxFee, - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, + utx, err := pBuilder.NewOperationTx( + ops, + options(changeAddr, nil /*memo*/)..., ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed building import tx: %w", err) } - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) + return backends.SignUnsigned(context.Background(), pSigner, utx) } func buildImportTx( - vm *VM, + backend *Backend, sourceChain ids.ID, - atomicUTXOs []*avax.UTXO, to ids.ShortID, - utxos []*avax.UTXO, kc *secp256k1fx.Keychain, ) (*txs.Tx, error) { - toBurn, importInputs, importKeys, err := vm.SpendAll(atomicUTXOs, kc) - if err != nil { - return nil, err - } + pBuilder, pSigner := builders(backend, kc) - uTx := &txs.ImportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - SourceChain: sourceChain, - ImportedIns: importInputs, + outOwner := &secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, } - if importedAmt := toBurn[vm.feeAssetID]; importedAmt < vm.TxFee { - toBurn[vm.feeAssetID] = vm.TxFee - importedAmt - } else { - toBurn[vm.feeAssetID] = importedAmt - vm.TxFee - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - to, + utx, err := pBuilder.NewImportTx( + sourceChain, + outOwner, ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed building import tx: %w", err) } - keys = append(keys, importKeys...) - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, tx.SignSECP256K1Fx(vm.parser.Codec(), keys) + return backends.SignUnsigned(context.Background(), pSigner, utx) } func buildExportTx( - vm *VM, + backend *Backend, destinationChain ids.ID, to ids.ShortID, exportedAssetID ids.ID, exportedAmt uint64, - utxos []*avax.UTXO, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - uTx := &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.ChainID, - }}, - DestinationChain: destinationChain, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: exportedAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: exportedAmt, - OutputOwners: secp256k1fx.OutputOwners{ - Locktime: 0, - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, + pBuilder, pSigner := builders(backend, kc) + + outputs := []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: exportedAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: exportedAmt, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, }, - }}, - } - toBurn := map[ids.ID]uint64{} - if exportedAssetID == vm.feeAssetID { - amountWithFee, err := safemath.Add64(exportedAmt, vm.TxFee) - if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) - } - toBurn[vm.feeAssetID] = amountWithFee - } else { - toBurn[exportedAssetID] = exportedAmt - toBurn[vm.feeAssetID] = vm.TxFee - } - ins, outs, keys, err := vm.Spend( - utxos, - kc, - toBurn, - changeAddr, + }, + }} + + utx, err := pBuilder.NewExportTx( + destinationChain, + outputs, + options(changeAddr, nil /*memo*/)..., ) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("failed building export tx: %w", err) + } + + tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } + return tx, changeAddr, nil +} - codec := vm.parser.Codec() +func builders(backend *Backend, kc *secp256k1fx.Keychain) (backends.Builder, backends.Signer) { + var ( + addrs = kc.Addresses() + builder = backends.NewBuilder(addrs, backend) + signer = backends.NewSigner(kc, backend) + ) + backend.ResetAddresses(addrs) + + return builder, signer +} - uTx.Ins = ins - uTx.Outs = outs - tx := &txs.Tx{Unsigned: uTx} - return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) +func options(changeAddr ids.ShortID, memo []byte) []common.Option { + return common.UnionOptions( + []common.Option{common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + })}, + []common.Option{common.WithMemo(memo)}, + ) } diff --git a/vms/avm/service_tx_builders_backend.go b/vms/avm/service_tx_builders_backend.go new file mode 100644 index 00000000000..23b31a1ea1a --- /dev/null +++ b/vms/avm/service_tx_builders_backend.go @@ -0,0 +1,83 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package avm + +import ( + "context" + "fmt" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/avm/config" + "github.com/ava-labs/avalanchego/vms/avm/state" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" +) + +var _ backends.Backend = (*Backend)(nil) + +func NewBackend( + feeAssetID ids.ID, + ctx *snow.Context, + cfg *config.Config, + state state.State, + atomicUTXOsMan avax.AtomicUTXOManager, +) *Backend { + backendCtx := backends.NewContext( + ctx.NetworkID, + ctx.XChainID, + feeAssetID, + cfg.TxFee, + cfg.CreateAssetTxFee, + ) + return &Backend{ + Context: backendCtx, + xchainID: ctx.XChainID, + cfg: cfg, + state: state, + atomicUTXOsMan: atomicUTXOsMan, + } +} + +type Backend struct { + backends.Context + + xchainID ids.ID + cfg *config.Config + addrs set.Set[ids.ShortID] + state state.State + atomicUTXOsMan avax.AtomicUTXOManager +} + +func (b *Backend) ResetAddresses(addrs set.Set[ids.ShortID]) { + b.addrs = addrs +} + +func (b *Backend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { + if sourceChainID == b.xchainID { + return avax.GetAllUTXOs(b.state, b.addrs) + } + + atomicUTXOs, _, _, err := b.atomicUTXOsMan.GetAtomicUTXOs(sourceChainID, b.addrs, ids.ShortEmpty, ids.Empty, int(maxPageSize)) + return atomicUTXOs, err +} + +func (b *Backend) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { + if chainID == b.xchainID { + return b.state.GetUTXO(utxoID) + } + + atomicUTXOs, _, _, err := b.atomicUTXOsMan.GetAtomicUTXOs(chainID, b.addrs, ids.ShortEmpty, ids.Empty, int(maxPageSize)) + if err != nil { + return nil, fmt.Errorf("problem retrieving atomic UTXOs: %w", err) + } + for _, utxo := range atomicUTXOs { + if utxo.InputID() == utxoID { + return utxo, nil + } + } + return nil, database.ErrNotFound +} diff --git a/vms/avm/tx.go b/vms/avm/tx.go index 13064a59a18..94d47845d9f 100644 --- a/vms/avm/tx.go +++ b/vms/avm/tx.go @@ -45,7 +45,7 @@ func (tx *Tx) Accept(context.Context) error { } executor := &executor.Executor{ - Codec: tx.vm.txBackend.Codec, + Codec: tx.vm.txExecutorBackend.Codec, State: tx.vm.state, Tx: tx.tx, } @@ -126,7 +126,7 @@ func (tx *Tx) Verify(context.Context) error { return fmt.Errorf("%w: %s", errTxNotProcessing, s) } return tx.tx.Unsigned.Visit(&executor.SemanticVerifier{ - Backend: tx.vm.txBackend, + Backend: tx.vm.txExecutorBackend, State: tx.vm.state, Tx: tx.tx, }) diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 833bd6f79a4..30320ea1cd6 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -110,7 +110,8 @@ type VM struct { addressTxsIndexer index.AddressTxsIndexer - txBackend *txexecutor.Backend + txBuilderBackend *Backend + txExecutorBackend *txexecutor.Backend // Cancelled on shutdown onShutdownCtx context.Context @@ -265,7 +266,9 @@ func (vm *VM) Initialize( } } - vm.txBackend = &txexecutor.Backend{ + vm.txBuilderBackend = NewBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.AtomicUTXOManager) + + vm.txExecutorBackend = &txexecutor.Backend{ Ctx: ctx, Config: &vm.Config, Fxs: vm.fxs, @@ -282,7 +285,7 @@ func (vm *VM) Initialize( // onBootstrapStarted is called by the consensus engine when it starts bootstrapping this chain func (vm *VM) onBootstrapStarted() error { - vm.txBackend.Bootstrapped = false + vm.txExecutorBackend.Bootstrapped = false for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapping(); err != nil { return err @@ -292,7 +295,7 @@ func (vm *VM) onBootstrapStarted() error { } func (vm *VM) onNormalOperationsStarted() error { - vm.txBackend.Bootstrapped = true + vm.txExecutorBackend.Bootstrapped = true for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapped(); err != nil { return err @@ -417,13 +420,13 @@ func (vm *VM) Linearize(ctx context.Context, stopVertexID ids.ID, toEngine chan< mempool, vm.metrics, vm.state, - vm.txBackend, + vm.txExecutorBackend, &vm.clock, vm.onAccept, ) vm.Builder = blockbuilder.New( - vm.txBackend, + vm.txExecutorBackend, vm.chainManager, &vm.clock, mempool, @@ -488,7 +491,7 @@ func (vm *VM) ParseTx(_ context.Context, bytes []byte) (snowstorm.Tx, error) { } err = tx.Unsigned.Visit(&txexecutor.SyntacticVerifier{ - Backend: vm.txBackend, + Backend: vm.txExecutorBackend, Tx: tx, }) if err != nil { diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index acaacd1785f..933df7c1a25 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -12,7 +12,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/avm/config" - "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/nftfx" @@ -39,42 +38,35 @@ func TestVerifyFxUsage(t *testing.T) { kc = secp256k1fx.NewKeychain() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - // Create the asset - createAssetTx, _, err := buildCreateAssetTx( - env.vm, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, + initialStates := map[uint32][]verify.State{ + uint32(0): { + &secp256k1fx.TransferOutput{ + Amt: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, - { - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, }, - utxos, + } + + // Create the asset + createAssetTx, _, err := buildCreateAssetTx( + env.vm.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, kc, key.Address(), ) @@ -82,9 +74,9 @@ func TestVerifyFxUsage(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) - mintOp, nftKeys, err := env.vm.MintNFT( + mintOp, _, err := env.vm.MintNFT( utxos, kc, createAssetTx.ID(), @@ -93,24 +85,21 @@ func TestVerifyFxUsage(t *testing.T) { ) require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) mintNFTTx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, mintOp, - utxos, kc, key.Address(), ) require.NoError(err) - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), nftKeys)) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) // move the NFT - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - to := keys[2].PublicKey().Address() + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) spendTx, _, err := buildBaseTx( - env.vm, + env.vm.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: createAssetTx.ID()}, Out: &secp256k1fx.TransferOutput{ @@ -122,7 +111,6 @@ func TestVerifyFxUsage(t *testing.T) { }, }}, nil, // memo - utxos, kc, key.Address(), ) diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 4596789f451..2bca5fdf65a 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -150,27 +150,24 @@ func TestIssueNFT(t *testing.T) { kc.Add(key) // Create the asset - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + initialStates := map[uint32][]verify.State{ + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + } createAssetTx, _, err := buildCreateAssetTx( - env.vm, + env.vm.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination - []*txs.InitialState{{ - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - }}, - utxos, + initialStates, kc, key.Address(), ) @@ -178,9 +175,9 @@ func TestIssueNFT(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) - mintOp, nftKeys, err := env.vm.MintNFT( + mintOp, _, err := env.vm.MintNFT( utxos, kc, createAssetTx.ID(), @@ -189,21 +186,20 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) mintNFTTx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, mintOp, - utxos, kc, key.Address(), ) require.NoError(err) - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), nftKeys)) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) // Move the NFT utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) - transferOp, moveNftKeys, err := env.vm.SpendNFT( + transferOp, _, err := env.vm.SpendNFT( utxos, kc, createAssetTx.ID(), @@ -212,15 +208,14 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) transferNFTTx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, transferOp, - utxos, kc, key.Address(), ) require.NoError(err) - require.NoError(transferNFTTx.SignNFTFx(env.vm.parser.Codec(), moveNftKeys)) issueAndAccept(require, env.vm, env.issuer, transferNFTTx) } @@ -245,32 +240,29 @@ func TestIssueProperty(t *testing.T) { }() var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - codec = env.vm.parser.Codec() + key = keys[0] + kc = secp256k1fx.NewKeychain() ) kc.Add(key) // create the asset - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx, _, err := buildCreateAssetTx( - env.vm, + env.vm.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination - []*txs.InitialState{{ - FxIndex: 2, - Outs: []verify.State{ - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - }}, - utxos, + initialStates, kc, key.Address(), ) @@ -278,8 +270,6 @@ func TestIssueProperty(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // mint the property - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) mintPropertyOp := &txs.Operation{ Asset: avax.Asset{ID: createAssetTx.ID()}, UTXOIDs: []*avax.UTXOID{{ @@ -300,22 +290,17 @@ func TestIssueProperty(t *testing.T) { }, } + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) mintPropertyTx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, []*txs.Operation{mintPropertyOp}, - utxos, kc, key.Address(), ) require.NoError(err) - require.NoError(mintPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ - {keys[0]}, - })) issueAndAccept(require, env.vm, env.issuer, mintPropertyTx) // burn the property - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) burnPropertyOp := &txs.Operation{ Asset: avax.Asset{ID: createAssetTx.ID()}, UTXOIDs: []*avax.UTXOID{{ @@ -325,17 +310,14 @@ func TestIssueProperty(t *testing.T) { Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, } + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) burnPropertyTx, err := buildOperation( - env.vm, + env.vm.txBuilderBackend, []*txs.Operation{burnPropertyOp}, - utxos, kc, key.Address(), ) require.NoError(err) - require.NoError(burnPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ - {}, - })) issueAndAccept(require, env.vm, env.issuer, burnPropertyTx) } @@ -379,11 +361,10 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { createTx = getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildBaseTx( - env.vm, + env.vm.txBuilderBackend, []*avax.TransferableOutput{ { // fee asset Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, @@ -407,7 +388,6 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { }, }, nil, // memo - utxos, kc, key.Address(), ) @@ -460,11 +440,10 @@ func TestTxAcceptAfterParseTx(t *testing.T) { kc = secp256k1fx.NewKeychain() ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) firstTx, _, err := buildBaseTx( - env.vm, + env.vm.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.genesisTx.ID()}, Out: &secp256k1fx.TransferOutput{ @@ -476,7 +455,6 @@ func TestTxAcceptAfterParseTx(t *testing.T) { }, }}, nil, // memo - utxos, kc, key.Address(), ) @@ -568,18 +546,6 @@ func TestIssueImportTx(t *testing.T) { } ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - - tx, err := buildImportTx( - env.vm, - constants.PlatformChainID, // source chain - []*avax.UTXO{importedUtxo}, // atomicUTXOs - key.Address(), - utxos, - kc, - ) - require.NoError(err) // Provide the platform UTXO: utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, importedUtxo) @@ -598,6 +564,15 @@ func TestIssueImportTx(t *testing.T) { }, })) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildImportTx( + env.vm.txBuilderBackend, + constants.PlatformChainID, // source chain + key.Address(), + kc, + ) + require.NoError(err) + env.vm.ctx.Lock.Unlock() issueAndAccept(require, env.vm, env.issuer, tx) @@ -711,16 +686,14 @@ func TestIssueExportTx(t *testing.T) { ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm, + env.vm.txBuilderBackend, constants.PlatformChainID, to, // to avaxID, startBalance-env.vm.TxFee, - utxos, kc, changeAddr, ) @@ -779,16 +752,14 @@ func TestClearForceAcceptedExportTx(t *testing.T) { ) kc.Add(key) - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) + env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm, + env.vm.txBuilderBackend, constants.PlatformChainID, to, // to avaxID, startBalance-env.vm.TxFee, - utxos, kc, changeAddr, ) From 57f5b22134e81d7e4f56a8feaac022920c505888 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 23 Feb 2024 00:24:44 +0100 Subject: [PATCH 16/53] wip: some more consolidation --- vms/avm/environment_test.go | 7 +- vms/avm/service.go | 73 ++-- ...builders_backend.go => service_backend.go} | 16 +- vms/avm/service_test.go | 14 +- ...{service_tx_builders.go => tx_builders.go} | 63 +++- vms/avm/utxo/spender.go | 346 +----------------- vms/avm/vm.go | 12 +- vms/avm/vm_regression_test.go | 26 +- vms/avm/vm_test.go | 58 ++- vms/avm/wallet_service.go | 73 +--- vms/avm/wallet_service_backend.go | 104 ++++++ 11 files changed, 261 insertions(+), 531 deletions(-) rename vms/avm/{service_tx_builders_backend.go => service_backend.go} (81%) rename vms/avm/{service_tx_builders.go => tx_builders.go} (73%) create mode 100644 vms/avm/wallet_service_backend.go diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 7b8ec890207..f5648b7fbfa 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -24,7 +24,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" - "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/sampler" "github.com/ava-labs/avalanchego/vms/avm/block/executor" @@ -199,11 +198,11 @@ func setup(tb testing.TB, c *envConfig) *environment { issuer: issuer, vm: vm, service: &Service{ - vm: vm, + vm: vm, + txBuilderBackend: newServiceBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.AtomicUTXOManager), }, walletService: &WalletService{ - vm: vm, - pendingTxs: linkedhashmap.New[ids.ID, *txs.Tx](), + walletServiceBackend: NewWalletServiceBackend(vm), }, } diff --git a/vms/avm/service.go b/vms/avm/service.go index 1cb24fa037d..ec0510213f7 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -60,7 +60,10 @@ type FormattedAssetID struct { } // Service defines the base service for the asset vm -type Service struct{ vm *VM } +type Service struct { + vm *VM + txBuilderBackend *serviceBackend +} // GetBlock returns the requested block. func (s *Service) GetBlock(_ *http.Request, args *api.GetBlockArgs, reply *api.GetBlockResponse) error { @@ -787,9 +790,9 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI initialStateOuts = append(initialStateOuts, minter) } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) return buildCreateAssetTx( - s.vm.txBuilderBackend, + s.txBuilderBackend, args.Name, args.Symbol, args.Denomination, @@ -908,9 +911,9 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh initialStateOuts = append(initialStateOuts, minter) } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) return buildCreateAssetTx( - s.vm.txBuilderBackend, + s.txBuilderBackend, args.Name, args.Symbol, 0, // NFTs are non-fungible @@ -1226,8 +1229,8 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildBaseTx(s.vm.txBuilderBackend, outs, memoBytes, kc, changeAddr) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildBaseTx(s.txBuilderBackend, outs, memoBytes, kc, changeAddr) } // MintArgs are arguments for passing into Mint requests @@ -1307,25 +1310,23 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { } // Get all UTXOs/keys for the user - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, ids.ShortEmpty, err } - ops, _, err := s.vm.Mint( - utxos, - kc, - map[ids.ID]uint64{ - assetID: uint64(args.Amount), + outputs := map[ids.ID]*secp256k1fx.TransferOutput{ + assetID: { + Amt: uint64(args.Amount), + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, }, - to, - ) - if err != nil { - return nil, ids.ShortEmpty, err } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildOperation(s.vm.txBuilderBackend, ops, feeKc, changeAddr) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := mintFTs(s.txBuilderBackend, outputs, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1411,8 +1412,8 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildOperation(s.vm.txBuilderBackend, ops, kc, changeAddr) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildOperation(s.txBuilderBackend, ops, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1493,26 +1494,26 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) } // Get all UTXOs/keys - utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) + _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, ids.ShortEmpty, err } - ops, _, err := s.vm.MintNFT( - utxos, - kc, + + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := mintNFT( + s.txBuilderBackend, assetID, payloadBytes, - to, + []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{to}, + }}, + kc, + changeAddr, ) if err != nil { return nil, ids.ShortEmpty, err } - - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildOperation(s.vm.txBuilderBackend, ops, feeKc, changeAddr) - if err != nil { - return nil, ids.ShortEmpty, err - } return tx, changeAddr, nil } @@ -1571,8 +1572,8 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return nil, err } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildImportTx(s.vm.txBuilderBackend, chainID, to, kc) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildImportTx(s.txBuilderBackend, chainID, to, kc) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1665,6 +1666,6 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - s.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildExportTx(s.vm.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) + s.txBuilderBackend.ResetAddresses(kc.Addresses()) + return buildExportTx(s.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) } diff --git a/vms/avm/service_tx_builders_backend.go b/vms/avm/service_backend.go similarity index 81% rename from vms/avm/service_tx_builders_backend.go rename to vms/avm/service_backend.go index 23b31a1ea1a..158dc01d2dc 100644 --- a/vms/avm/service_tx_builders_backend.go +++ b/vms/avm/service_backend.go @@ -17,15 +17,15 @@ import ( "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ) -var _ backends.Backend = (*Backend)(nil) +var _ txBuilderBackend = (*serviceBackend)(nil) -func NewBackend( +func newServiceBackend( feeAssetID ids.ID, ctx *snow.Context, cfg *config.Config, state state.State, atomicUTXOsMan avax.AtomicUTXOManager, -) *Backend { +) *serviceBackend { backendCtx := backends.NewContext( ctx.NetworkID, ctx.XChainID, @@ -33,7 +33,7 @@ func NewBackend( cfg.TxFee, cfg.CreateAssetTxFee, ) - return &Backend{ + return &serviceBackend{ Context: backendCtx, xchainID: ctx.XChainID, cfg: cfg, @@ -42,7 +42,7 @@ func NewBackend( } } -type Backend struct { +type serviceBackend struct { backends.Context xchainID ids.ID @@ -52,11 +52,11 @@ type Backend struct { atomicUTXOsMan avax.AtomicUTXOManager } -func (b *Backend) ResetAddresses(addrs set.Set[ids.ShortID]) { +func (b *serviceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { b.addrs = addrs } -func (b *Backend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { +func (b *serviceBackend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { if sourceChainID == b.xchainID { return avax.GetAllUTXOs(b.state, b.addrs) } @@ -65,7 +65,7 @@ func (b *Backend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, return atomicUTXOs, err } -func (b *Backend) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { +func (b *serviceBackend) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { if chainID == b.xchainID { return b.state.GetUTXO(utxoID) } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index ac11dfad4c8..8d8ecac9a60 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1616,9 +1616,9 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { ) kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildBaseTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.vm.feeAssetID}, Out: &secp256k1fx.TransferOutput{ @@ -1691,7 +1691,7 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { } tx, _, err := buildCreateAssetTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination @@ -1711,9 +1711,9 @@ func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { ) kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, chainID, to, env.vm.feeAssetID, @@ -1805,9 +1805,9 @@ func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation ) kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, err := buildOperation( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, ops, kc, key.Address(), diff --git a/vms/avm/service_tx_builders.go b/vms/avm/tx_builders.go similarity index 73% rename from vms/avm/service_tx_builders.go rename to vms/avm/tx_builders.go index 6d9bf3c6e4c..9606af6069f 100644 --- a/vms/avm/service_tx_builders.go +++ b/vms/avm/tx_builders.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -16,8 +17,14 @@ import ( "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) +type txBuilderBackend interface { + backends.Backend + + ResetAddresses(addrs set.Set[ids.ShortID]) +} + func buildCreateAssetTx( - backend *Backend, + backend txBuilderBackend, name, symbol string, denomination byte, initialStates map[uint32][]verify.State, @@ -46,7 +53,7 @@ func buildCreateAssetTx( } func buildBaseTx( - backend *Backend, + backend txBuilderBackend, outs []*avax.TransferableOutput, memo []byte, kc *secp256k1fx.Keychain, @@ -70,8 +77,50 @@ func buildBaseTx( return tx, changeAddr, nil } +func mintNFT( + backend txBuilderBackend, + assetID ids.ID, + payload []byte, + owners []*secp256k1fx.OutputOwners, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, error) { + pBuilder, pSigner := builders(backend, kc) + + utx, err := pBuilder.NewOperationTxMintNFT( + assetID, + payload, + owners, + options(changeAddr, nil /*memo*/)..., + ) + if err != nil { + return nil, fmt.Errorf("failed minting NFTs: %w", err) + } + + return backends.SignUnsigned(context.Background(), pSigner, utx) +} + +func mintFTs( + backend txBuilderBackend, + outputs map[ids.ID]*secp256k1fx.TransferOutput, + kc *secp256k1fx.Keychain, + changeAddr ids.ShortID, +) (*txs.Tx, error) { + pBuilder, pSigner := builders(backend, kc) + + utx, err := pBuilder.NewOperationTxMintFT( + outputs, + options(changeAddr, nil /*memo*/)..., + ) + if err != nil { + return nil, fmt.Errorf("failed minting FTs: %w", err) + } + + return backends.SignUnsigned(context.Background(), pSigner, utx) +} + func buildOperation( - backend *Backend, + backend txBuilderBackend, ops []*txs.Operation, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, @@ -83,14 +132,14 @@ func buildOperation( options(changeAddr, nil /*memo*/)..., ) if err != nil { - return nil, fmt.Errorf("failed building import tx: %w", err) + return nil, fmt.Errorf("failed building operation tx: %w", err) } return backends.SignUnsigned(context.Background(), pSigner, utx) } func buildImportTx( - backend *Backend, + backend txBuilderBackend, sourceChain ids.ID, to ids.ShortID, kc *secp256k1fx.Keychain, @@ -115,7 +164,7 @@ func buildImportTx( } func buildExportTx( - backend *Backend, + backend txBuilderBackend, destinationChain ids.ID, to ids.ShortID, exportedAssetID ids.ID, @@ -153,7 +202,7 @@ func buildExportTx( return tx, changeAddr, nil } -func builders(backend *Backend, kc *secp256k1fx.Keychain) (backends.Builder, backends.Signer) { +func builders(backend txBuilderBackend, kc *secp256k1fx.Keychain) (backends.Builder, backends.Signer) { var ( addrs = kc.Addresses() builder = backends.NewBuilder(addrs, backend) diff --git a/vms/avm/utxo/spender.go b/vms/avm/utxo/spender.go index 1ccd4982f66..a4dce2838a6 100644 --- a/vms/avm/utxo/spender.go +++ b/vms/avm/utxo/spender.go @@ -5,13 +5,10 @@ package utxo import ( "errors" - "fmt" "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -19,34 +16,9 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var ( - errSpendOverflow = errors.New("spent amount overflows uint64") - errInsufficientFunds = errors.New("insufficient funds") - errAddressesCantMintAsset = errors.New("provided addresses don't have the authority to mint the provided asset") -) +var errInsufficientFunds = errors.New("insufficient funds") type Spender interface { - // Spend the provided amount while deducting the provided fee. - // Arguments: - // - [utxos] contains assets ID and amount to be spend for each assestID - // - [kc] are the owners of the funds - // - [toSpend] is the amount of funds that are available to be spent for each assetID - // Returns: - // - [inputs] the inputs that should be consumed to fund the outputs - // - [outputs] the outputs produced - // - [signers] the proof of ownership of the funds being moved - Spend( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - toSpend map[ids.ID]uint64, - changeAddr ids.ShortID, - ) ( - []*avax.TransferableInput, // inputs - []*avax.TransferableOutput, // outputs - [][]*secp256k1.PrivateKey, // signers - error, - ) - SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, @@ -58,39 +30,6 @@ type Spender interface { [][]*secp256k1.PrivateKey, error, ) - - SpendAll( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - ) ( - map[ids.ID]uint64, - []*avax.TransferableInput, - [][]*secp256k1.PrivateKey, - error, - ) - - Mint( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - amounts map[ids.ID]uint64, - to ids.ShortID, - ) ( - []*txs.Operation, - [][]*secp256k1.PrivateKey, - error, - ) - - MintNFT( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - assetID ids.ID, - payload []byte, - to ids.ShortID, - ) ( - []*txs.Operation, - [][]*secp256k1.PrivateKey, - error, - ) } func NewSpender( @@ -108,96 +47,6 @@ type spender struct { codec codec.Manager } -func (s *spender) Spend( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - amountsToBurn map[ids.ID]uint64, - changeAddr ids.ShortID, -) ( - inputs []*avax.TransferableInput, - outputs []*avax.TransferableOutput, - signers [][]*secp256k1.PrivateKey, - err error, -) { - var ( - minIssuanceTime = s.clock.Unix() - changeOwner = &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - } - ) - - // Iterate over the UTXOs - for _, utxo := range utxos { - assetID := utxo.AssetID() - remainingAmountToBurn := amountsToBurn[assetID] - - // If we have consumed enough of the asset, then we have no need burn - // more. - if remainingAmountToBurn == 0 { - continue - } - - outIntf := utxo.Out - out, ok := outIntf.(*secp256k1fx.TransferOutput) - if !ok { - // We only support burning [secp256k1fx.TransferOutput]s. - continue - } - - inputIntf, keys, err := kc.Spend(utxo.Out, minIssuanceTime) - if err != nil { - // this utxo can't be spent with the current keys right now - continue - } - input, ok := inputIntf.(avax.TransferableIn) - if !ok { - // this input doesn't have an amount, so I don't care about it here - continue - } - - inputs = append(inputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: avax.Asset{ID: assetID}, - In: input, - }) - signers = append(signers, keys) - - // Burn any value that should be burned - amountToBurn := min( - remainingAmountToBurn, // Amount we still need to burn - out.Amt, // Amount available to burn - ) - amountsToBurn[assetID] -= amountToBurn - if remainingAmount := out.Amt - amountToBurn; remainingAmount > 0 { - // This input had extra value, so some of it must be returned - outputs = append(outputs, &avax.TransferableOutput{ - Asset: utxo.Asset, - FxID: secp256k1fx.ID, - Out: &secp256k1fx.TransferOutput{ - Amt: remainingAmount, - OutputOwners: *changeOwner, - }, - }) - } - } - - for assetID, amount := range amountsToBurn { - if amount != 0 { - return nil, nil, nil, fmt.Errorf( - "%w: provided UTXOs need %d more units of asset %q", - errInsufficientFunds, - amount, - assetID, - ) - } - } - - utils.Sort(inputs) // sort inputs - avax.SortTransferableOutputs(outputs, s.codec) // sort the change outputs - return inputs, outputs, signers, nil -} - func (s *spender) SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, @@ -271,196 +120,3 @@ func (s *spender) SpendNFT( txs.SortOperationsWithSigners(ops, keys, s.codec) return ops, keys, nil } - -func (s *spender) SpendAll( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, -) ( - map[ids.ID]uint64, - []*avax.TransferableInput, - [][]*secp256k1.PrivateKey, - error, -) { - amountsSpent := make(map[ids.ID]uint64) - time := s.clock.Unix() - - ins := []*avax.TransferableInput{} - keys := [][]*secp256k1.PrivateKey{} - for _, utxo := range utxos { - assetID := utxo.AssetID() - amountSpent := amountsSpent[assetID] - - inputIntf, signers, err := kc.Spend(utxo.Out, time) - if err != nil { - // this utxo can't be spent with the current keys right now - continue - } - input, ok := inputIntf.(avax.TransferableIn) - if !ok { - // this input doesn't have an amount, so I don't care about it here - continue - } - newAmountSpent, err := math.Add64(amountSpent, input.Amount()) - if err != nil { - // there was an error calculating the consumed amount, just error - return nil, nil, nil, errSpendOverflow - } - amountsSpent[assetID] = newAmountSpent - - // add the new input to the array - ins = append(ins, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: avax.Asset{ID: assetID}, - In: input, - }) - // add the required keys to the array - keys = append(keys, signers) - } - - avax.SortTransferableInputsWithSigners(ins, keys) - return amountsSpent, ins, keys, nil -} - -func (s *spender) Mint( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - amounts map[ids.ID]uint64, - to ids.ShortID, -) ( - []*txs.Operation, - [][]*secp256k1.PrivateKey, - error, -) { - time := s.clock.Unix() - - ops := []*txs.Operation{} - keys := [][]*secp256k1.PrivateKey{} - - for _, utxo := range utxos { - // makes sure that the variable isn't overwritten with the next iteration - utxo := utxo - - assetID := utxo.AssetID() - amount := amounts[assetID] - if amount == 0 { - continue - } - - out, ok := utxo.Out.(*secp256k1fx.MintOutput) - if !ok { - continue - } - - inIntf, signers, err := kc.Spend(out, time) - if err != nil { - continue - } - - in, ok := inIntf.(*secp256k1fx.Input) - if !ok { - continue - } - - // add the operation to the array - ops = append(ops, &txs.Operation{ - Asset: utxo.Asset, - UTXOIDs: []*avax.UTXOID{&utxo.UTXOID}, - Op: &secp256k1fx.MintOperation{ - MintInput: *in, - MintOutput: *out, - TransferOutput: secp256k1fx.TransferOutput{ - Amt: amount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, - }, - }, - }) - // add the required keys to the array - keys = append(keys, signers) - - // remove the asset from the required amounts to mint - delete(amounts, assetID) - } - - for _, amount := range amounts { - if amount > 0 { - return nil, nil, errAddressesCantMintAsset - } - } - - txs.SortOperationsWithSigners(ops, keys, s.codec) - return ops, keys, nil -} - -func (s *spender) MintNFT( - utxos []*avax.UTXO, - kc *secp256k1fx.Keychain, - assetID ids.ID, - payload []byte, - to ids.ShortID, -) ( - []*txs.Operation, - [][]*secp256k1.PrivateKey, - error, -) { - time := s.clock.Unix() - - ops := []*txs.Operation{} - keys := [][]*secp256k1.PrivateKey{} - - for _, utxo := range utxos { - // makes sure that the variable isn't overwritten with the next iteration - utxo := utxo - - if len(ops) > 0 { - // we have already been able to create the operation needed - break - } - - if utxo.AssetID() != assetID { - // wrong asset id - continue - } - out, ok := utxo.Out.(*nftfx.MintOutput) - if !ok { - // wrong output type - continue - } - - indices, signers, ok := kc.Match(&out.OutputOwners, time) - if !ok { - // unable to spend the output - continue - } - - // add the operation to the array - ops = append(ops, &txs.Operation{ - Asset: avax.Asset{ID: assetID}, - UTXOIDs: []*avax.UTXOID{ - &utxo.UTXOID, - }, - Op: &nftfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: indices, - }, - GroupID: out.GroupID, - Payload: payload, - Outputs: []*secp256k1fx.OutputOwners{{ - Threshold: 1, - Addrs: []ids.ShortID{to}, - }}, - }, - }) - // add the required keys to the array - keys = append(keys, signers) - } - - if len(ops) == 0 { - return nil, nil, errAddressesCantMintAsset - } - - txs.SortOperationsWithSigners(ops, keys, s.codec) - return ops, keys, nil -} diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 30320ea1cd6..63955316a95 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -27,7 +27,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/json" - "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/version" @@ -110,7 +109,6 @@ type VM struct { addressTxsIndexer index.AddressTxsIndexer - txBuilderBackend *Backend txExecutorBackend *txexecutor.Backend // Cancelled on shutdown @@ -248,8 +246,7 @@ func (vm *VM) Initialize( return err } - vm.walletService.vm = vm - vm.walletService.pendingTxs = linkedhashmap.New[ids.ID, *txs.Tx]() + vm.walletService.walletServiceBackend = NewWalletServiceBackend(vm) // use no op impl when disabled in config if avmConfig.IndexTransactions { @@ -266,8 +263,6 @@ func (vm *VM) Initialize( } } - vm.txBuilderBackend = NewBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.AtomicUTXOManager) - vm.txExecutorBackend = &txexecutor.Backend{ Ctx: ctx, Config: &vm.Config, @@ -344,7 +339,10 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { rpcServer.RegisterInterceptFunc(vm.metrics.InterceptRequest) rpcServer.RegisterAfterFunc(vm.metrics.AfterRequest) // name this service "avm" - if err := rpcServer.RegisterService(&Service{vm: vm}, "avm"); err != nil { + if err := rpcServer.RegisterService(&Service{ + vm: vm, + txBuilderBackend: newServiceBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.AtomicUTXOManager), + }, "avm"); err != nil { return nil, err } diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 933df7c1a25..5c63be8afe5 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -62,7 +62,7 @@ func TestVerifyFxUsage(t *testing.T) { // Create the asset createAssetTx, _, err := buildCreateAssetTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination @@ -74,21 +74,15 @@ func TestVerifyFxUsage(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - mintOp, _, err := env.vm.MintNFT( - utxos, - kc, + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + mintNFTTx, err := mintNFT( + env.service.txBuilderBackend, createAssetTx.ID(), []byte{'h', 'e', 'l', 'l', 'o'}, // payload - key.Address(), - ) - require.NoError(err) - - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - mintNFTTx, err := buildOperation( - env.vm.txBuilderBackend, - mintOp, + []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{key.Address()}, + }}, kc, key.Address(), ) @@ -97,9 +91,9 @@ func TestVerifyFxUsage(t *testing.T) { // move the NFT to := keys[2].PublicKey().Address() - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) spendTx, _, err := buildBaseTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: createAssetTx.ID()}, Out: &secp256k1fx.TransferOutput{ diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 2bca5fdf65a..513c10841ce 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -163,7 +163,7 @@ func TestIssueNFT(t *testing.T) { } createAssetTx, _, err := buildCreateAssetTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination @@ -175,21 +175,15 @@ func TestIssueNFT(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - mintOp, _, err := env.vm.MintNFT( - utxos, - kc, + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + mintNFTTx, err := mintNFT( + env.service.txBuilderBackend, createAssetTx.ID(), []byte{'h', 'e', 'l', 'l', 'o'}, // payload - key.Address(), - ) - require.NoError(err) - - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) - mintNFTTx, err := buildOperation( - env.vm.txBuilderBackend, - mintOp, + []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{key.Address()}, + }}, kc, key.Address(), ) @@ -197,7 +191,7 @@ func TestIssueNFT(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintNFTTx) // Move the NFT - utxos, err = avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) require.NoError(err) transferOp, _, err := env.vm.SpendNFT( utxos, @@ -208,9 +202,9 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) transferNFTTx, err := buildOperation( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, transferOp, kc, key.Address(), @@ -258,7 +252,7 @@ func TestIssueProperty(t *testing.T) { } createAssetTx, _, err := buildCreateAssetTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, "Team Rocket", // name "TR", // symbol 0, // denomination @@ -290,9 +284,9 @@ func TestIssueProperty(t *testing.T) { }, } - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) mintPropertyTx, err := buildOperation( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*txs.Operation{mintPropertyOp}, kc, key.Address(), @@ -310,9 +304,9 @@ func TestIssueProperty(t *testing.T) { Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, } - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) burnPropertyTx, err := buildOperation( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*txs.Operation{burnPropertyOp}, kc, key.Address(), @@ -362,9 +356,9 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { ) kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildBaseTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*avax.TransferableOutput{ { // fee asset Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, @@ -441,9 +435,9 @@ func TestTxAcceptAfterParseTx(t *testing.T) { ) kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) firstTx, _, err := buildBaseTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.genesisTx.ID()}, Out: &secp256k1fx.TransferOutput{ @@ -564,9 +558,9 @@ func TestIssueImportTx(t *testing.T) { }, })) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, err := buildImportTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, constants.PlatformChainID, // source chain key.Address(), kc, @@ -687,9 +681,9 @@ func TestIssueExportTx(t *testing.T) { kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, constants.PlatformChainID, to, // to avaxID, @@ -753,9 +747,9 @@ func TestClearForceAcceptedExportTx(t *testing.T) { kc.Add(key) - env.vm.txBuilderBackend.ResetAddresses(kc.Addresses()) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) tx, _, err := buildExportTx( - env.vm.txBuilderBackend, + env.service.txBuilderBackend, constants.PlatformChainID, to, // to avaxID, diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index e27c0ea7df8..8a65ed568c8 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -10,12 +10,10 @@ import ( "net/http" "go.uber.org/zap" - "golang.org/x/exp/maps" "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/formatting" - "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/vms/avm/txs" @@ -27,8 +25,7 @@ import ( var errMissingUTXO = errors.New("missing utxo") type WalletService struct { - vm *VM - pendingTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx] + *walletServiceBackend } func (w *WalletService) decided(txID ids.ID) { @@ -99,35 +96,6 @@ func (w *WalletService) issue(tx *txs.Tx) (ids.ID, error) { return txID, nil } -func (w *WalletService) update(utxos []*avax.UTXO) ([]*avax.UTXO, error) { - utxoMap := make(map[ids.ID]*avax.UTXO, len(utxos)) - for _, utxo := range utxos { - utxoMap[utxo.InputID()] = utxo - } - - iter := w.pendingTxs.NewIterator() - - for iter.Next() { - tx := iter.Value() - for _, inputUTXO := range tx.Unsigned.InputUTXOs() { - if inputUTXO.Symbolic() { - continue - } - utxoID := inputUTXO.InputID() - if _, exists := utxoMap[utxoID]; !exists { - return nil, errMissingUTXO - } - delete(utxoMap, utxoID) - } - - for _, utxo := range tx.UTXOs() { - utxoMap[utxo.InputID()] = utxo - } - } - - return maps.Values(utxoMap), nil -} - // IssueTx attempts to issue a transaction into consensus func (w *WalletService) IssueTx(_ *http.Request, args *api.FormattedTx, reply *api.JSONTxID) error { w.vm.ctx.Log.Warn("deprecated API called", @@ -196,8 +164,7 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re return err } - utxos, err = w.update(utxos) - if err != nil { + if err = w.vm.walletService.update(utxos); err != nil { return err } @@ -256,44 +223,12 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re }) } - uTx := &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: w.vm.ctx.NetworkID, - BlockchainID: w.vm.ctx.ChainID, - Memo: memoBytes, - }, - } - - toBurn := make(map[ids.ID]uint64) // UTXOs to move + fees - for _, out := range outs { - toBurn[out.AssetID()] += out.Out.Amount() - } - amountWithFee, err := math.Add64(toBurn[w.vm.feeAssetID], w.vm.TxFee) - if err != nil { - return fmt.Errorf("problem calculating required spend amount: %w", err) - } - toBurn[w.vm.feeAssetID] = amountWithFee - - ins, feeOuts, keys, err := w.vm.Spend( - utxos, - kc, - toBurn, - changeAddr, - ) + w.walletServiceBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildBaseTx(w.walletServiceBackend, outs, memoBytes, kc, changeAddr) if err != nil { return err } - uTx.Ins = ins - uTx.Outs = append(uTx.Outs, feeOuts...) - codec := w.vm.parser.Codec() - avax.SortTransferableOutputs(uTx.Outs, codec) - - tx := &txs.Tx{Unsigned: uTx} - if err := tx.SignSECP256K1Fx(codec, keys); err != nil { - return err - } - txID, err := w.issue(tx) if err != nil { return fmt.Errorf("problem issuing transaction: %w", err) diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go new file mode 100644 index 00000000000..8c9eb6e55a3 --- /dev/null +++ b/vms/avm/wallet_service_backend.go @@ -0,0 +1,104 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package avm + +import ( + "context" + + "golang.org/x/exp/maps" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/linkedhashmap" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/chain/x/backends" +) + +var _ txBuilderBackend = (*walletServiceBackend)(nil) + +func NewWalletServiceBackend(vm *VM) *walletServiceBackend { + backendCtx := backends.NewContext( + vm.ctx.NetworkID, + vm.ctx.XChainID, + vm.feeAssetID, + vm.Config.TxFee, + vm.Config.CreateAssetTxFee, + ) + return &walletServiceBackend{ + Context: backendCtx, + vm: vm, + pendingTxs: linkedhashmap.New[ids.ID, *txs.Tx](), + utxos: make([]*avax.UTXO, 0), + } +} + +type walletServiceBackend struct { + backends.Context + + vm *VM + pendingTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx] + utxos []*avax.UTXO + + addrs set.Set[ids.ShortID] +} + +func (b *walletServiceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { + b.addrs = addrs +} + +func (b *walletServiceBackend) UTXOs(_ context.Context, _ ids.ID) ([]*avax.UTXO, error) { + res, err := avax.GetAllUTXOs(b.vm.state, b.addrs) + if err != nil { + return nil, err + } + res = append(res, b.utxos...) + return res, nil +} + +func (b *walletServiceBackend) GetUTXO(_ context.Context, _, utxoID ids.ID) (*avax.UTXO, error) { + allUTXOs, err := avax.GetAllUTXOs(b.vm.state, b.addrs) + if err != nil { + return nil, err + } + allUTXOs = append(allUTXOs, b.utxos...) + + for _, utxo := range allUTXOs { + if utxo.InputID() == utxoID { + return utxo, nil + } + } + return nil, database.ErrNotFound +} + +func (b *walletServiceBackend) update(utxos []*avax.UTXO) error { + utxoMap := make(map[ids.ID]*avax.UTXO, len(utxos)) + for _, utxo := range utxos { + utxoMap[utxo.InputID()] = utxo + } + + iter := b.pendingTxs.NewIterator() + + for iter.Next() { + tx := iter.Value() + for _, inputUTXO := range tx.Unsigned.InputUTXOs() { + if inputUTXO.Symbolic() { + continue + } + utxoID := inputUTXO.InputID() + if _, exists := utxoMap[utxoID]; !exists { + return errMissingUTXO + } + delete(utxoMap, utxoID) + } + + for _, utxo := range tx.UTXOs() { + utxoMap[utxo.InputID()] = utxo + } + } + + b.utxos = maps.Values(utxoMap) + return nil +} From 68f5cb79ce259bc0e2adf8ea666cc32040698be3 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 23 Feb 2024 15:16:18 +0100 Subject: [PATCH 17/53] removed noFeesTestConfg from avm unit tests --- vms/avm/environment_test.go | 7 - vms/avm/index_test.go | 14 +- vms/avm/service_test.go | 542 +++++++++++++++++++++++++++------- vms/avm/vm_regression_test.go | 2 +- vms/avm/vm_test.go | 16 +- 5 files changed, 455 insertions(+), 126 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 337a4bbf98e..a1b81b27780 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -75,13 +75,6 @@ var ( keys = secp256k1.TestKeys()[:3] // TODO: Remove [:3] addrs []ids.ShortID // addrs[i] corresponds to keys[i] - - noFeesTestConfig = &config.Config{ - DurangoTime: time.Time{}, - EUpgradeTime: mockable.MaxTime, - TxFee: 0, - CreateAssetTxFee: 0, - } ) func init() { diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index ef8a357935a..f2d78c5379a 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,7 +28,7 @@ import ( func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -70,7 +70,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -116,7 +116,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -157,7 +157,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { func TestIndexer_Read(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -251,7 +251,7 @@ func buildUTXO(utxoID avax.UTXOID, txAssetID avax.Asset, addr ids.ShortID) *avax UTXOID: utxoID, Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: startBalance, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{addr}, @@ -269,14 +269,14 @@ func buildTX(chainID ids.ID, utxoID avax.UTXOID, txAssetID avax.Asset, address . UTXOID: utxoID, Asset: txAssetID, In: &secp256k1fx.TransferInput{ - Amt: 1000, + Amt: startBalance, Input: secp256k1fx.Input{SigIndices: []uint32{0}}, }, }}, Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: startBalance - testTxFee, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: address, diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 490ddd28302..2855fb31f93 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -47,7 +47,7 @@ import ( func TestServiceIssueTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: eUpgrade}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { @@ -725,7 +725,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -738,7 +738,52 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) reply := api.GetTxReply{} @@ -756,8 +801,34 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 49000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "outputIndex": 2, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 50000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "name": "Team Rocket", "symbol": "TR", @@ -778,6 +849,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], + "groupID": 0, "locktime": 0, "threshold": 1 } @@ -827,7 +899,16 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { } ] }, - "credentials": null, + "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xbbdff720789320b7f2b47e230ba8eb2e4b72c7eea52afe4ea1ae2e78ab1b611a318d21160a83bbd5a147848b909ad3859b0b1110e2401fa1c958d42dd6800ed501" + ] + } + } + ], "id": "PLACEHOLDER_TX_ID" }` @@ -841,7 +922,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -855,10 +936,28 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildNFTxMintOp(createAssetTx, key, 2, 1) + op := buildNFTxMintOp(createAssetTx, key, 1, 1) mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) @@ -877,8 +976,34 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "rSiY2aqcahSU5vyJeMiNBnwtPwfJFxsxskAGbU3HxHvAkrdpy", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -886,7 +1011,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 1 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -912,11 +1037,19 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" + ] + } + }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "PLACEHOLDER_SIGNATURE" + "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" ] } } @@ -928,7 +1061,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -940,7 +1073,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -954,11 +1087,31 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + GroupID: 0, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) - mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2) + mintOp1 := buildNFTxMintOp(createAssetTx, key, 1, 0) + mintOp2 := buildNFTxMintOp(createAssetTx, key, 2, 1) mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) @@ -977,8 +1130,34 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "BBhSA95iv6ueXc7xrMSka1bByBqcwJxyvMiyjy5H8ccAgxy4P", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -986,7 +1165,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 1 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -996,7 +1175,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 1, + "groupID": 0, "payload": "0x68656c6c6f", "outputs": [ { @@ -1014,7 +1193,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 3 + "outputIndex": 2 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -1024,7 +1203,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 2, + "groupID": 1, "payload": "0x68656c6c6f", "outputs": [ { @@ -1041,13 +1220,21 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }, "credentials": [ { - "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ "PLACEHOLDER_SIGNATURE" ] } }, + { + "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", + "credential": { + "signatures": [ + "0xc958811e7430677ed15c40ac1d7f6232e8f5060aecf4cd8c45ef1614d9c9a5be5b5d5e697da4e40c743c010bab7bca58d9970b1cc5f3dc15b2f6d9adc712289f00" + ] + } + }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { @@ -1064,7 +1251,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1076,7 +1263,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1090,10 +1277,25 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildSecpMintOp(createAssetTx, key, 0) + op := buildSecpMintOp(createAssetTx, key, 1) mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) @@ -1112,8 +1314,34 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2YhAg3XUdub5syHHePZG7q3yFjKAy7ahsvQDxq5SMrYbN1s5Gn", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1121,7 +1349,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 0 + "outputIndex": 1 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1158,6 +1386,14 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } + }, + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xad7f3f3cd2667eda64e6f9ca3ab0db21238c20a0174f590b5d9fdf69fa009d073b50d7e0db156cb3678c23509cb7adf767fc98119a683560950a1e8f3299d17800" + ] + } } ], "id": "PLACEHOLDER_TX_ID" @@ -1179,7 +1415,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1193,11 +1429,29 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildSecpMintOp(createAssetTx, key, 0) - op2 := buildSecpMintOp(createAssetTx, key, 1) + op1 := buildSecpMintOp(createAssetTx, key, 1) + op2 := buildSecpMintOp(createAssetTx, key, 2) mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) @@ -1216,8 +1470,34 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2vxorPLUw5sneb7Mdhhjuws3H5AqaDp1V8ETz6fEuzvn835rVX", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1225,7 +1505,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 0 + "outputIndex": 1 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1257,7 +1537,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 2 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1302,6 +1582,14 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } + }, + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xeada420035b6ad5e658e96abab39622c5aa730bda266374af4ddb264696fa998584823d34f7df3a5cb03c5cec3068365ece9a5b7242193a862e9e0459a8865b801" + ] + } } ], "id": "PLACEHOLDER_TX_ID" @@ -1323,7 +1611,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1337,10 +1625,20 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildPropertyFxMintOp(createAssetTx, key, 4) + op := buildPropertyFxMintOp(createAssetTx, key, 1) mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) @@ -1359,8 +1657,34 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "nNUGBjszswU3ZmhCb8hBNWmg335UZqGWmNrYTAGyMF4bFpMXm", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1368,7 +1692,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 4 + "outputIndex": 1 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1395,6 +1719,14 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xa5c7a3fac9f87479fafc347510e270e86da9e99ad606f31342baf1440674b1b53ea836b9a1cfee11eb85b96e1b8e547e2206758d3e902d9e14f6dd784172363401" + ] + } + }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1411,7 +1743,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -1423,7 +1755,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1437,11 +1769,27 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env) + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildPropertyFxMintOp(createAssetTx, key, 4) - op2 := buildPropertyFxMintOp(createAssetTx, key, 5) + op1 := buildPropertyFxMintOp(createAssetTx, key, 1) + op2 := buildPropertyFxMintOp(createAssetTx, key, 2) mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) @@ -1460,8 +1808,34 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2NV5AGoQQHVRY6VkT8sht8bhZDHR7uwta7fk7JwAZpacqMRWCa", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1469,7 +1843,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 4 + "outputIndex": 1 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1498,7 +1872,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 5 + "outputIndex": 2 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1525,6 +1899,14 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xbf14b82775f2b260d77d4d790b0873e8cdb243e20bc95ca65bd08645f70845bd662ec4437b6599b0e4f86ad3d68ddfcd058bf0c729054aad609a26ba539b3b3300" + ] + } + }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1549,7 +1931,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1587,59 +1969,13 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { return tx } -func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment) *txs.Tx { +func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStates map[uint32][]verify.State) *txs.Tx { var ( key = keys[0] kc = secp256k1fx.NewKeychain() ) kc.Add(key) - initialStates := map[uint32][]verify.State{ - uint32(0): { - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - uint32(2): { - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - tx, _, err := buildCreateAssetTx( env.service.txBuilderBackend, "Team Rocket", // name diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 13160820cb4..473af93355e 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -19,7 +19,7 @@ import ( func TestVerifyFxUsage(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 96bd34851bb..ab316be82f0 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -129,7 +129,7 @@ func TestIssueTx(t *testing.T) { func TestIssueNFT(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -212,7 +212,7 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -260,7 +260,7 @@ func TestIssueProperty(t *testing.T) { Asset: avax.Asset{ID: createAssetTx.ID()}, UTXOIDs: []*avax.UTXOID{{ TxID: createAssetTx.ID(), - OutputIndex: 0, + OutputIndex: 1, }}, Op: &propertyfx.MintOperation{ MintInput: secp256k1fx.Input{ @@ -291,7 +291,7 @@ func TestIssueProperty(t *testing.T) { Asset: avax.Asset{ID: createAssetTx.ID()}, UTXOIDs: []*avax.UTXOID{{ TxID: mintPropertyTx.ID(), - OutputIndex: 1, + OutputIndex: 2, }}, Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, } @@ -493,7 +493,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { func TestIssueImportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{vmStaticConfig: noFeesTestConfig}) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -576,8 +576,8 @@ func TestForceAcceptImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - notLinearized: true, + fork: durango, + notLinearized: true, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -605,7 +605,7 @@ func TestForceAcceptImportTx(t *testing.T) { Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: 10, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, From f0b3c69ac409bec51331c5cab4d655cab30a9086 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 13 Mar 2024 18:36:41 +0100 Subject: [PATCH 18/53] fixed merge --- tests/antithesis/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go index 24f76613330..f59e3f763a4 100644 --- a/tests/antithesis/main.go +++ b/tests/antithesis/main.go @@ -27,12 +27,12 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/propertyfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" xtxs "github.com/ava-labs/avalanchego/vms/avm/txs" ptxs "github.com/ava-labs/avalanchego/vms/platformvm/txs" + xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ) const NumKeys = 5 @@ -579,7 +579,7 @@ func (w *workload) verifyXChainTxConsumedUTXOs(ctx context.Context, tx *xtxs.Tx) ctx, utxos, client, - x.Parser.Codec(), + xbackends.Parser.Codec(), chainID, chainID, w.addrs.List(), From 8420192e630d01560a711ca02426c766a26e10ce Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 13 Mar 2024 18:41:09 +0100 Subject: [PATCH 19/53] fixed merge --- tests/antithesis/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go index 24f76613330..f59e3f763a4 100644 --- a/tests/antithesis/main.go +++ b/tests/antithesis/main.go @@ -27,12 +27,12 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/propertyfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" xtxs "github.com/ava-labs/avalanchego/vms/avm/txs" ptxs "github.com/ava-labs/avalanchego/vms/platformvm/txs" + xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ) const NumKeys = 5 @@ -579,7 +579,7 @@ func (w *workload) verifyXChainTxConsumedUTXOs(ctx context.Context, tx *xtxs.Tx) ctx, utxos, client, - x.Parser.Codec(), + xbackends.Parser.Codec(), chainID, chainID, w.addrs.List(), From a98e9b1e0327f699fad9819953e9012f45db555b Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 12:09:27 -0400 Subject: [PATCH 20/53] merged --- wallet/subnet/primary/wallet.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index f1e8b474eeb..382a042a6be 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -18,12 +18,8 @@ import ( pbuilder "github.com/ava-labs/avalanchego/wallet/chain/p/builder" psigner "github.com/ava-labs/avalanchego/wallet/chain/p/signer" -<<<<<<< HEAD xbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" xsigner "github.com/ava-labs/avalanchego/wallet/chain/x/signer" -======= - xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" ->>>>>>> 0cd1353ea7017aa0a30c3cef9811963a46eff29a ) var _ Wallet = (*wallet)(nil) From 59a1e07564c2861a7efa1a776f974f2c893ad9df Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 19 Mar 2024 12:10:35 -0400 Subject: [PATCH 21/53] fix --- indexer/examples/x-chain-blocks/main.go | 4 ++-- tests/antithesis/main.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/indexer/examples/x-chain-blocks/main.go b/indexer/examples/x-chain-blocks/main.go index c15d5da9b0a..c118a7ad378 100644 --- a/indexer/examples/x-chain-blocks/main.go +++ b/indexer/examples/x-chain-blocks/main.go @@ -10,7 +10,7 @@ import ( "github.com/ava-labs/avalanchego/indexer" "github.com/ava-labs/avalanchego/vms/proposervm/block" - "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" "github.com/ava-labs/avalanchego/wallet/subnet/primary" ) @@ -37,7 +37,7 @@ func main() { } avmBlockBytes := proposerVMBlock.Block() - avmBlock, err := backends.Parser.ParseBlock(avmBlockBytes) + avmBlock, err := builder.Parser.ParseBlock(avmBlockBytes) if err != nil { log.Fatalf("failed to parse avm block: %s\n", err) } diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go index ce11d8eefe2..5d7d614f75c 100644 --- a/tests/antithesis/main.go +++ b/tests/antithesis/main.go @@ -32,7 +32,7 @@ import ( xtxs "github.com/ava-labs/avalanchego/vms/avm/txs" ptxs "github.com/ava-labs/avalanchego/vms/platformvm/txs" - xbackends "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + xbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) const NumKeys = 5 @@ -591,7 +591,7 @@ func (w *workload) verifyXChainTxConsumedUTXOs(ctx context.Context, tx *xtxs.Tx) ctx, utxos, client, - xbackends.Parser.Codec(), + xbuilder.Parser.Codec(), chainID, chainID, w.addrs.List(), From 5782a143716b7a86a02f1bd8ca79a9bb996fa2b9 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 19 Mar 2024 18:07:07 +0100 Subject: [PATCH 22/53] fixed merge --- vms/avm/service_backend.go | 26 +++++++++++++++----------- vms/avm/tx_builders.go | 29 +++++++++++++++++------------ vms/avm/wallet_service_backend.go | 26 +++++++++++++++----------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go index 158dc01d2dc..0b0f7b382f2 100644 --- a/vms/avm/service_backend.go +++ b/vms/avm/service_backend.go @@ -14,7 +14,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) var _ txBuilderBackend = (*serviceBackend)(nil) @@ -26,15 +26,16 @@ func newServiceBackend( state state.State, atomicUTXOsMan avax.AtomicUTXOManager, ) *serviceBackend { - backendCtx := backends.NewContext( - ctx.NetworkID, - ctx.XChainID, - feeAssetID, - cfg.TxFee, - cfg.CreateAssetTxFee, - ) + backendCtx := &builder.Context{ + NetworkID: ctx.NetworkID, + BlockchainID: ctx.XChainID, + AVAXAssetID: feeAssetID, + BaseTxFee: cfg.TxFee, + CreateAssetTxFee: cfg.CreateAssetTxFee, + } + return &serviceBackend{ - Context: backendCtx, + ctx: backendCtx, xchainID: ctx.XChainID, cfg: cfg, state: state, @@ -43,8 +44,7 @@ func newServiceBackend( } type serviceBackend struct { - backends.Context - + ctx *builder.Context xchainID ids.ID cfg *config.Config addrs set.Set[ids.ShortID] @@ -52,6 +52,10 @@ type serviceBackend struct { atomicUTXOsMan avax.AtomicUTXOManager } +func (b *serviceBackend) Context() *builder.Context { + return b.ctx +} + func (b *serviceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { b.addrs = addrs } diff --git a/vms/avm/tx_builders.go b/vms/avm/tx_builders.go index 9606af6069f..dc07c7ea959 100644 --- a/vms/avm/tx_builders.go +++ b/vms/avm/tx_builders.go @@ -13,13 +13,17 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + "github.com/ava-labs/avalanchego/wallet/chain/x/signer" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + + walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) type txBuilderBackend interface { - backends.Backend + walletbuilder.Backend + signer.Backend + Context() *walletbuilder.Context ResetAddresses(addrs set.Set[ids.ShortID]) } @@ -44,7 +48,7 @@ func buildCreateAssetTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) } - tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } @@ -69,7 +73,7 @@ func buildBaseTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) } - tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } @@ -97,7 +101,7 @@ func mintNFT( return nil, fmt.Errorf("failed minting NFTs: %w", err) } - return backends.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), pSigner, utx) } func mintFTs( @@ -116,7 +120,7 @@ func mintFTs( return nil, fmt.Errorf("failed minting FTs: %w", err) } - return backends.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), pSigner, utx) } func buildOperation( @@ -135,7 +139,7 @@ func buildOperation( return nil, fmt.Errorf("failed building operation tx: %w", err) } - return backends.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), pSigner, utx) } func buildImportTx( @@ -160,7 +164,7 @@ func buildImportTx( return nil, fmt.Errorf("failed building import tx: %w", err) } - return backends.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), pSigner, utx) } func buildExportTx( @@ -195,19 +199,20 @@ func buildExportTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building export tx: %w", err) } - tx, err := backends.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } return tx, changeAddr, nil } -func builders(backend txBuilderBackend, kc *secp256k1fx.Keychain) (backends.Builder, backends.Signer) { +func builders(backend txBuilderBackend, kc *secp256k1fx.Keychain) (walletbuilder.Builder, signer.Signer) { var ( addrs = kc.Addresses() - builder = backends.NewBuilder(addrs, backend) - signer = backends.NewSigner(kc, backend) + builder = walletbuilder.New(addrs, backend.Context(), backend) + signer = signer.New(kc, backend) ) + backend.ResetAddresses(addrs) return builder, signer diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go index 8c9eb6e55a3..babf8d02da6 100644 --- a/vms/avm/wallet_service_backend.go +++ b/vms/avm/wallet_service_backend.go @@ -14,21 +14,22 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/chain/x/backends" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) var _ txBuilderBackend = (*walletServiceBackend)(nil) func NewWalletServiceBackend(vm *VM) *walletServiceBackend { - backendCtx := backends.NewContext( - vm.ctx.NetworkID, - vm.ctx.XChainID, - vm.feeAssetID, - vm.Config.TxFee, - vm.Config.CreateAssetTxFee, - ) + backendCtx := &builder.Context{ + NetworkID: vm.ctx.NetworkID, + BlockchainID: vm.ctx.XChainID, + AVAXAssetID: vm.feeAssetID, + BaseTxFee: vm.Config.TxFee, + CreateAssetTxFee: vm.Config.CreateAssetTxFee, + } + return &walletServiceBackend{ - Context: backendCtx, + ctx: backendCtx, vm: vm, pendingTxs: linkedhashmap.New[ids.ID, *txs.Tx](), utxos: make([]*avax.UTXO, 0), @@ -36,8 +37,7 @@ func NewWalletServiceBackend(vm *VM) *walletServiceBackend { } type walletServiceBackend struct { - backends.Context - + ctx *builder.Context vm *VM pendingTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx] utxos []*avax.UTXO @@ -45,6 +45,10 @@ type walletServiceBackend struct { addrs set.Set[ids.ShortID] } +func (b *walletServiceBackend) Context() *builder.Context { + return b.ctx +} + func (b *walletServiceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { b.addrs = addrs } From c7d9274656ae0e3b29b4a85f5cab0947d862a366 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 26 Apr 2024 13:39:57 +0200 Subject: [PATCH 23/53] reverted UTs changes --- vms/avm/environment_test.go | 6 + vms/avm/index_test.go | 22 +- vms/avm/service_test.go | 786 ++++++++++------------------------ vms/avm/vm_regression_test.go | 133 +++--- vms/avm/vm_test.go | 594 +++++++++++++------------ 5 files changed, 649 insertions(+), 892 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 2d5130d5612..6045c09bd2f 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -76,6 +76,12 @@ var ( keys = secp256k1.TestKeys()[:3] // TODO: Remove [:3] addrs []ids.ShortID // addrs[i] corresponds to keys[i] + + noFeesTestConfig = &config.Config{ + EUpgradeTime: mockable.MaxTime, + TxFee: 0, + CreateAssetTxFee: 0, + } ) func init() { diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index f2d78c5379a..459d4230f32 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,7 +28,9 @@ import ( func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: durango}) + env := setup(t, &envConfig{ + vmStaticConfig: noFeesTestConfig, + }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -70,7 +72,9 @@ func TestIndexTransaction_Ordered(t *testing.T) { func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: durango}) + env := setup(t, &envConfig{ + vmStaticConfig: noFeesTestConfig, + }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -116,7 +120,9 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: durango}) + env := setup(t, &envConfig{ + vmStaticConfig: noFeesTestConfig, + }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -157,7 +163,9 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { func TestIndexer_Read(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: durango}) + env := setup(t, &envConfig{ + vmStaticConfig: noFeesTestConfig, + }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -251,7 +259,7 @@ func buildUTXO(utxoID avax.UTXOID, txAssetID avax.Asset, addr ids.ShortID) *avax UTXOID: utxoID, Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: startBalance, + Amt: 1000, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{addr}, @@ -269,14 +277,14 @@ func buildTX(chainID ids.ID, utxoID avax.UTXOID, txAssetID avax.Asset, address . UTXOID: utxoID, Asset: txAssetID, In: &secp256k1fx.TransferInput{ - Amt: startBalance, + Amt: 1000, Input: secp256k1fx.Input{SigIndices: []uint32{0}}, }, }}, Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - testTxFee, + Amt: 1000, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: address, diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 10f03fb3c5a..3fd2c5cdbd5 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -28,11 +28,8 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/timer/mockable" - "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -92,7 +89,7 @@ func TestServiceGetTxStatus(t *testing.T) { err := env.service.GetTxStatus(nil, statusArgs, statusReply) require.ErrorIs(err, errNilTxID) - newTx := newAvaxBaseTxWithOutputs(t, env) + newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) txID := newTx.ID() statusArgs = &api.JSONTxID{ @@ -555,7 +552,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := newAvaxBaseTxWithOutputs(t, env) + newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -581,19 +578,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 1000, - "locktime": 0, - "threshold": 1 - } - }, - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1d6kkj0qh4wcmus3tk59npwt3rluc6en72ngurd" - ], - "amount": 48000, + "amount": 49000, "locktime": 0, "threshold": 1 } @@ -652,7 +637,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) + newTx := newAvaxExportTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -669,20 +654,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], + "outputs": null, "inputs": [ { "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -698,7 +670,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { } ], "memo": "0x", - "destinationChain": "2mcwQKiD8VEspmMJpL1dc7okQQ5dDVAWeCBZ7FWBFAbxpv3t7w", + "destinationChain": "11111111111111111111111111111111LpoYY", "exportedOutputs": [ { "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -707,7 +679,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 1000, + "amount": 49000, "locktime": 0, "threshold": 1 } @@ -742,7 +714,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -755,52 +727,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - initialStates := map[uint32][]verify.State{ - uint32(0): { - &nftfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - uint32(2): { - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) reply := api.GetTxReply{} @@ -818,34 +745,8 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 49000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "outputIndex": 2, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 50000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "name": "Team Rocket", "symbol": "TR", @@ -866,7 +767,6 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "groupID": 0, "locktime": 0, "threshold": 1 } @@ -916,16 +816,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { } ] }, - "credentials": [ - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0xbbdff720789320b7f2b47e230ba8eb2e4b72c7eea52afe4ea1ae2e78ab1b611a318d21160a83bbd5a147848b909ad3859b0b1110e2401fa1c958d42dd6800ed501" - ] - } - } - ], + "credentials": null, "id": "PLACEHOLDER_TX_ID" }` @@ -939,7 +830,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -953,29 +844,11 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildNFTxMintOp(createAssetTx, key, 1, 1) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildNFTxMintOp(createAssetTx, key, 2, 1)) + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -993,34 +866,8 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "rSiY2aqcahSU5vyJeMiNBnwtPwfJFxsxskAGbU3HxHvAkrdpy", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1028,7 +875,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 2 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -1054,19 +901,11 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { ] }, "credentials": [ - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" - ] - } - }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" + "PLACEHOLDER_SIGNATURE" ] } } @@ -1078,7 +917,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -1090,7 +929,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1104,32 +943,14 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(0): { - &nftfx.MintOutput{ - GroupID: 0, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintOp1 := buildNFTxMintOp(createAssetTx, key, 1, 0) - mintOp2 := buildNFTxMintOp(createAssetTx, key, 2, 1) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}) + mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) + mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2) + mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, mintOp1, mintOp2) + + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -1147,34 +968,8 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "BBhSA95iv6ueXc7xrMSka1bByBqcwJxyvMiyjy5H8ccAgxy4P", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1182,7 +977,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 2 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -1192,7 +987,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 0, + "groupID": 1, "payload": "0x68656c6c6f", "outputs": [ { @@ -1210,7 +1005,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 3 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -1220,7 +1015,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 1, + "groupID": 2, "payload": "0x68656c6c6f", "outputs": [ { @@ -1236,19 +1031,11 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { ] }, "credentials": [ - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "PLACEHOLDER_SIGNATURE" - ] - } - }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "0xc958811e7430677ed15c40ac1d7f6232e8f5060aecf4cd8c45ef1614d9c9a5be5b5d5e697da4e40c743c010bab7bca58d9970b1cc5f3dc15b2f6d9adc712289f00" + "PLACEHOLDER_SIGNATURE" ] } }, @@ -1268,7 +1055,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1280,7 +1067,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1294,26 +1081,11 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(0): { - &nftfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildSecpMintOp(createAssetTx, key, 1) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildSecpMintOp(createAssetTx, key, 0)) + require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1331,34 +1103,8 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "2YhAg3XUdub5syHHePZG7q3yFjKAy7ahsvQDxq5SMrYbN1s5Gn", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1366,7 +1112,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 0 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1403,14 +1149,6 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } - }, - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0xad7f3f3cd2667eda64e6f9ca3ab0db21238c20a0174f590b5d9fdf69fa009d073b50d7e0db156cb3678c23509cb7adf767fc98119a683560950a1e8f3299d17800" - ] - } } ], "id": "PLACEHOLDER_TX_ID" @@ -1432,7 +1170,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: durango, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1446,30 +1184,14 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(0): { - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - uint32(1): { - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildSecpMintOp(createAssetTx, key, 1) - op2 := buildSecpMintOp(createAssetTx, key, 2) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) + op1 := buildSecpMintOp(createAssetTx, key, 0) + op2 := buildSecpMintOp(createAssetTx, key, 1) + mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) + + require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1487,34 +1209,8 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "2vxorPLUw5sneb7Mdhhjuws3H5AqaDp1V8ETz6fEuzvn835rVX", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1522,7 +1218,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 0 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1554,7 +1250,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 1 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1599,14 +1295,6 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } - }, - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0xeada420035b6ad5e658e96abab39622c5aa730bda266374af4ddb264696fa998584823d34f7df3a5cb03c5cec3068365ece9a5b7242193a862e9e0459a8865b801" - ] - } } ], "id": "PLACEHOLDER_TX_ID" @@ -1628,7 +1316,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1642,21 +1330,11 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(2): { - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op := buildPropertyFxMintOp(createAssetTx, key, 1) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildPropertyFxMintOp(createAssetTx, key, 4)) + require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1674,34 +1352,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "nNUGBjszswU3ZmhCb8hBNWmg335UZqGWmNrYTAGyMF4bFpMXm", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1709,7 +1361,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 4 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1736,14 +1388,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { ] }, "credentials": [ - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0xa5c7a3fac9f87479fafc347510e270e86da9e99ad606f31342baf1440674b1b53ea836b9a1cfee11eb85b96e1b8e547e2206758d3e902d9e14f6dd784172363401" - ] - } - }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1760,7 +1404,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -1772,7 +1416,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1786,28 +1430,14 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }() key := keys[0] - initialStates := map[uint32][]verify.State{ - uint32(2): { - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - } - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildPropertyFxMintOp(createAssetTx, key, 1) - op2 := buildPropertyFxMintOp(createAssetTx, key, 2) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) + op1 := buildPropertyFxMintOp(createAssetTx, key, 4) + op2 := buildPropertyFxMintOp(createAssetTx, key, 5) + mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) + + require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1825,34 +1455,8 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": [ - { - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "output": { - "addresses": [ - "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" - ], - "amount": 48000, - "locktime": 0, - "threshold": 1 - } - } - ], - "inputs": [ - { - "txID": "2NV5AGoQQHVRY6VkT8sht8bhZDHR7uwta7fk7JwAZpacqMRWCa", - "outputIndex": 0, - "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "input": { - "amount": 49000, - "signatureIndices": [ - 0 - ] - } - } - ], + "outputs": null, + "inputs": null, "memo": "0x", "operations": [ { @@ -1860,7 +1464,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 4 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1889,7 +1493,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 5 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1916,14 +1520,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) ] }, "credentials": [ - { - "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", - "credential": { - "signatures": [ - "0xbf14b82775f2b260d77d4d790b0873e8cdb243e20bc95ca65bd08645f70845bd662ec4437b6599b0e4f86ad3d68ddfcd058bf0c729054aad609a26ba539b3b3300" - ] - } - }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1948,7 +1544,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1956,76 +1552,161 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require.Equal(expectedReplyTxString, string(replyTxBytes)) } -func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { - var ( - memo = []byte{1, 2, 3, 4, 5, 6, 7, 8} - key = keys[0] - changeKey = keys[1] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildBaseTx( - env.service.txBuilderBackend, - []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: env.vm.feeAssetID}, +func newAvaxBaseTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { + avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") + key := keys[0] + tx := buildTestBaseTx(avaxTx, chainID, fee, key) + require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + return tx +} + +func newAvaxExportTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { + avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") + key := keys[0] + tx := buildTestExportTx(avaxTx, chainID, fee, key) + require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + return tx +} + +func newAvaxCreateAssetTxWithOutputs(t *testing.T, chainID ids.ID, parser txs.Parser) *txs.Tx { + key := keys[0] + tx := buildTestCreateAssetTx(chainID, key) + require.NoError(t, tx.Initialize(parser.Codec())) + return tx +} + +func buildTestBaseTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { + return &txs.Tx{Unsigned: &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: chainID, + Memo: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: avaxTx.ID(), + OutputIndex: 2, + }, + Asset: avax.Asset{ID: avaxTx.ID()}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{ + SigIndices: []uint32{ + 0, + }, + }, + }, + }}, + Outs: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - fee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }}, + }, + }} +} + +func buildTestExportTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { + return &txs.Tx{Unsigned: &txs.ExportTx{ + BaseTx: txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: chainID, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: avaxTx.ID(), + OutputIndex: 2, + }, + Asset: avax.Asset{ID: avaxTx.ID()}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{SigIndices: []uint32{0}}, + }, + }}, + }, + }, + DestinationChain: constants.PlatformChainID, + ExportedOuts: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxTx.ID()}, Out: &secp256k1fx.TransferOutput{ - Amt: units.MicroAvax, + Amt: startBalance - fee, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, }}, - memo, - kc, - changeKey.PublicKey().Address(), - ) - require.NoError(t, err) - return tx -} - -func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStates map[uint32][]verify.State) *txs.Tx { - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - tx, _, err := buildCreateAssetTx( - env.service.txBuilderBackend, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - initialStates, - kc, - key.Address(), - ) - require.NoError(t, err) - return tx + }} } -func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - to = key.PublicKey().Address() - ) - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildExportTx( - env.service.txBuilderBackend, - chainID, - to, - env.vm.feeAssetID, - units.MicroAvax, - kc, - key.Address(), - ) - require.NoError(t, err) - return tx +func buildTestCreateAssetTx(chainID ids.ID, key *secp256k1.PrivateKey) *txs.Tx { + return &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: chainID, + }}, + Name: "Team Rocket", + Symbol: "TR", + Denomination: 0, + States: []*txs.InitialState{ + { + FxIndex: 0, + Outs: []verify.State{ + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + }, + { + FxIndex: 1, + Outs: []verify.State{ + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + }, + { + FxIndex: 2, + Outs: []verify.State{ + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + }, + }, + }} } func buildNFTxMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputIndex, groupID uint32) *txs.Operation { @@ -2101,22 +1782,14 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd } } -func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation) *txs.Tx { - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildOperation( - env.service.txBuilderBackend, - ops, - kc, - key.Address(), - ) - require.NoError(t, err) - return tx +func buildOperationTxWithOp(chainID ids.ID, op ...*txs.Operation) *txs.Tx { + return &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: chainID, + }}, + Ops: op, + }} } func TestServiceGetNilTx(t *testing.T) { @@ -2888,9 +2561,6 @@ func TestSendMultiple(t *testing.T) { password: password, initialKeys: keys, }}, - vmStaticConfig: &config.Config{ - EUpgradeTime: mockable.MaxTime, - }, }) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 0c4940d2460..0151ccaf6da 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -10,6 +10,9 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/nftfx" @@ -19,7 +22,9 @@ import ( func TestVerifyFxUsage(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: latest}) + env := setup(t, &envConfig{ + vmStaticConfig: noFeesTestConfig, + }) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -27,81 +32,85 @@ func TestVerifyFxUsage(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - initialStates := map[uint32][]verify.State{ - uint32(0): { - &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + }}, + Name: "Team Rocket", + Symbol: "TR", + Denomination: 0, + States: []*txs.InitialState{ + { + FxIndex: 0, + Outs: []verify.State{ + &secp256k1fx.TransferOutput{ + Amt: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, }, }, - }, - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + { + FxIndex: 1, + Outs: []verify.State{ + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, }, }, }, - } - - // Create the asset - createAssetTx, _, err := buildCreateAssetTx( - env.service.txBuilderBackend, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - initialStates, - kc, - key.Address(), - ) - require.NoError(err) + }} + require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - // Mint the NFT - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - mintNFTTx, err := mintNFT( - env.service.txBuilderBackend, - createAssetTx.ID(), - []byte{'h', 'e', 'l', 'l', 'o'}, // payload - []*secp256k1fx.OutputOwners{{ - Threshold: 1, - Addrs: []ids.ShortID{key.Address()}, + mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, }}, - kc, - key.Address(), - ) - require.NoError(err) + Ops: []*txs.Operation{{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: createAssetTx.ID(), + OutputIndex: 1, + }}, + Op: &nftfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: []uint32{0}, + }, + GroupID: 1, + Payload: []byte{'h', 'e', 'l', 'l', 'o'}, + Outputs: []*secp256k1fx.OutputOwners{{}}, + }, + }}, + }} + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - // move the NFT - to := keys[2].PublicKey().Address() - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - spendTx, _, err := buildBaseTx( - env.service.txBuilderBackend, - []*avax.TransferableOutput{{ + spendTx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: createAssetTx.ID(), + OutputIndex: 0, + }, Asset: avax.Asset{ID: createAssetTx.ID()}, - Out: &secp256k1fx.TransferOutput{ + In: &secp256k1fx.TransferInput{ Amt: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{to}, + Input: secp256k1fx.Input{ + SigIndices: []uint32{0}, }, }, }}, - nil, // memo - kc, - key.Address(), - ) - require.NoError(err) + }}} + require.NoError(spendTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) issueAndAccept(require, env.vm, env.issuer, spendTx) } diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 9ca514c53bb..25824f4d009 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -19,6 +19,7 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -132,7 +133,7 @@ func TestIssueNFT(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, }) env.vm.ctx.Lock.Unlock() defer func() { @@ -141,73 +142,90 @@ func TestIssueNFT(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - // Create the asset - initialStates := map[uint32][]verify.State{ - uint32(1): { - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, + createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + }}, + Name: "Team Rocket", + Symbol: "TR", + Denomination: 0, + States: []*txs.InitialState{{ + FxIndex: 1, + Outs: []verify.State{ + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, }, }, - }, - } - - createAssetTx, _, err := buildCreateAssetTx( - env.service.txBuilderBackend, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - initialStates, - kc, - key.Address(), - ) - require.NoError(err) + }}, + }} + require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - // Mint the NFT - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - mintNFTTx, err := mintNFT( - env.service.txBuilderBackend, - createAssetTx.ID(), - []byte{'h', 'e', 'l', 'l', 'o'}, // payload - []*secp256k1fx.OutputOwners{{ - Threshold: 1, - Addrs: []ids.ShortID{key.Address()}, + mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, }}, - kc, - key.Address(), - ) - require.NoError(err) + Ops: []*txs.Operation{{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: createAssetTx.ID(), + OutputIndex: 0, + }}, + Op: &nftfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: []uint32{0}, + }, + GroupID: 1, + Payload: []byte{'h', 'e', 'l', 'l', 'o'}, + Outputs: []*secp256k1fx.OutputOwners{{}}, + }, + }}, + }} + require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - // Move the NFT - utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) - require.NoError(err) - transferOp, _, err := env.vm.SpendNFT( - utxos, - kc, - createAssetTx.ID(), - 1, - keys[2].Address(), - ) - require.NoError(err) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - transferNFTTx, err := buildOperation( - env.service.txBuilderBackend, - transferOp, - kc, - key.Address(), - ) - require.NoError(err) + transferNFTTx := &txs.Tx{ + Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + }}, + Ops: []*txs.Operation{{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: mintNFTTx.ID(), + OutputIndex: 0, + }}, + Op: &nftfx.TransferOperation{ + Input: secp256k1fx.Input{}, + Output: nftfx.TransferOutput{ + GroupID: 1, + Payload: []byte{'h', 'e', 'l', 'l', 'o'}, + OutputOwners: secp256k1fx.OutputOwners{}, + }, + }, + }}, + }, + Creds: []*fxs.FxCredential{ + { + Credential: &nftfx.Credential{}, + }, + }, + } + require.NoError(transferNFTTx.Initialize(env.vm.parser.Codec())) issueAndAccept(require, env.vm, env.issuer, transferNFTTx) } @@ -216,7 +234,7 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: latest, + vmStaticConfig: noFeesTestConfig, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -229,85 +247,79 @@ func TestIssueProperty(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - // create the asset - initialStates := map[uint32][]verify.State{ - uint32(2): { - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + }}, + Name: "Team Rocket", + Symbol: "TR", + Denomination: 0, + States: []*txs.InitialState{{ + FxIndex: 2, + Outs: []verify.State{ + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, }, }, - }, - } - - createAssetTx, _, err := buildCreateAssetTx( - env.service.txBuilderBackend, - "Team Rocket", // name - "TR", // symbol - 0, // denomination - initialStates, - kc, - key.Address(), - ) - require.NoError(err) + }}, + }} + require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - // mint the property - mintPropertyOp := &txs.Operation{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 1, + mintPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, }}, - Op: &propertyfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - MintOutput: propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + Ops: []*txs.Operation{{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: createAssetTx.ID(), + OutputIndex: 0, + }}, + Op: &propertyfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: []uint32{0}, + }, + MintOutput: propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, }, + OwnedOutput: propertyfx.OwnedOutput{}, }, - OwnedOutput: propertyfx.OwnedOutput{}, - }, - } + }}, + }} - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - mintPropertyTx, err := buildOperation( - env.service.txBuilderBackend, - []*txs.Operation{mintPropertyOp}, - kc, - key.Address(), - ) - require.NoError(err) + codec := env.vm.parser.Codec() + require.NoError(mintPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ + {keys[0]}, + })) issueAndAccept(require, env.vm, env.issuer, mintPropertyTx) - // burn the property - burnPropertyOp := &txs.Operation{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: mintPropertyTx.ID(), - OutputIndex: 2, + burnPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, }}, - Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, - } + Ops: []*txs.Operation{{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: mintPropertyTx.ID(), + OutputIndex: 1, + }}, + Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, + }}, + }} - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - burnPropertyTx, err := buildOperation( - env.service.txBuilderBackend, - []*txs.Operation{burnPropertyOp}, - kc, - key.Address(), - ) - require.NoError(err) + require.NoError(burnPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ + {}, + })) issueAndAccept(require, env.vm, env.issuer, burnPropertyTx) } @@ -345,45 +357,51 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { }() // send second asset - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() + feeAssetCreateTx := getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) + createTx := getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) - feeAssetCreateTx = getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) - createTx = getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) - ) - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildBaseTx( - env.service.txBuilderBackend, - []*avax.TransferableOutput{ - { // fee asset - Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, + tx := &txs.Tx{Unsigned: &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Ins: []*avax.TransferableInput{ + // fee asset + { + UTXOID: avax.UTXOID{ + TxID: feeAssetCreateTx.ID(), + OutputIndex: 2, + }, + Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{ + SigIndices: []uint32{ + 0, + }, + }, }, }, - }, - { // issued asset - Asset: avax.Asset{ID: createTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, + // issued asset + { + UTXOID: avax.UTXOID{ + TxID: createTx.ID(), + OutputIndex: 2, + }, + Asset: avax.Asset{ID: createTx.ID()}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{ + SigIndices: []uint32{ + 0, + }, + }, }, }, }, }, - nil, // memo - kc, - key.Address(), - ) - require.NoError(err) + }} + require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}, {keys[0]}})) + issueAndAccept(require, env.vm, env.issuer, tx) } @@ -427,32 +445,40 @@ func TestTxAcceptAfterParseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() - ) - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - firstTx, _, err := buildBaseTx( - env.service.txBuilderBackend, - []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: env.genesisTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, + key := keys[0] + firstTx := &txs.Tx{Unsigned: &txs.BaseTx{ + BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: env.genesisTx.ID(), + OutputIndex: 2, }, - }, - }}, - nil, // memo - kc, - key.Address(), - ) - require.NoError(err) + Asset: avax.Asset{ID: env.genesisTx.ID()}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{ + SigIndices: []uint32{ + 0, + }, + }, + }, + }}, + Outs: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: env.genesisTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }}, + }, + }} + require.NoError(firstTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - // let secondTx spend firstTx outputs secondTx := &txs.Tx{Unsigned: &txs.BaseTx{ BaseTx: avax.BaseTx{ NetworkID: constants.UnitTestID, @@ -500,7 +526,7 @@ func TestIssueImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: durango, + vmStaticConfig: noFeesTestConfig, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -512,38 +538,63 @@ func TestIssueImportTx(t *testing.T) { genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() - var ( - key = keys[0] - kc = secp256k1fx.NewKeychain() + key := keys[0] + utxoID := avax.UTXOID{ + TxID: ids.ID{ + 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, + 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, + 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, + 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, + }, + } - utxoID = avax.UTXOID{ - TxID: ids.ID{ - 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, - 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, - 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, - 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, - }, - } - txAssetID = avax.Asset{ID: avaxID} - importedUtxo = &avax.UTXO{ + txAssetID := avax.Asset{ID: avaxID} + tx := &txs.Tx{Unsigned: &txs.ImportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Outs: []*avax.TransferableOutput{{ + Asset: txAssetID, + Out: &secp256k1fx.TransferOutput{ + Amt: 1000, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }}, + }}, + SourceChain: constants.PlatformChainID, + ImportedIns: []*avax.TransferableInput{{ UTXOID: utxoID, Asset: txAssetID, - Out: &secp256k1fx.TransferOutput{ + In: &secp256k1fx.TransferInput{ Amt: 1010, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, + Input: secp256k1fx.Input{ + SigIndices: []uint32{0}, }, }, - } - ) - kc.Add(key) + }}, + }} + require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) // Provide the platform UTXO: - utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, importedUtxo) + utxo := &avax.UTXO{ + UTXOID: utxoID, + Asset: txAssetID, + Out: &secp256k1fx.TransferOutput{ + Amt: 1010, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + } + + utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, utxo) require.NoError(err) - inputID := importedUtxo.InputID() + inputID := utxo.InputID() require.NoError(peerSharedMemory.Apply(map[ids.ID]*atomic.Requests{ env.vm.ctx.ChainID: { PutRequests: []*atomic.Element{{ @@ -556,15 +607,6 @@ func TestIssueImportTx(t *testing.T) { }, })) - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildImportTx( - env.service.txBuilderBackend, - constants.PlatformChainID, // source chain - key.Address(), - kc, - ) - require.NoError(err) - env.vm.ctx.Lock.Unlock() issueAndAccept(require, env.vm, env.issuer, tx) @@ -584,8 +626,8 @@ func TestForceAcceptImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - fork: durango, - notLinearized: true, + vmStaticConfig: noFeesTestConfig, + notLinearized: true, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -613,7 +655,7 @@ func TestForceAcceptImportTx(t *testing.T) { Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 10, + Amt: 1000, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, @@ -661,35 +703,47 @@ func TestImportTxNotState(t *testing.T) { func TestIssueExportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{fork: durango}) + env := setup(t, &envConfig{ + fork: latest, + }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") + avaxID := genesisTx.ID() - var ( - avaxID = genesisTx.ID() - key = keys[0] - kc = secp256k1fx.NewKeychain() - to = key.PublicKey().Address() - changeAddr = to - ) - - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildExportTx( - env.service.txBuilderBackend, - constants.PlatformChainID, - to, // to - avaxID, - startBalance-env.vm.TxFee, - kc, - changeAddr, - ) - require.NoError(err) + key := keys[0] + tx := &txs.Tx{Unsigned: &txs.ExportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: avaxID, + OutputIndex: 2, + }, + Asset: avax.Asset{ID: avaxID}, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{SigIndices: []uint32{0}}, + }, + }}, + }}, + DestinationChain: constants.PlatformChainID, + ExportedOuts: []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxID}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }}, + }} + require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) utxoBytes, _, _, err := peerSharedMemory.Indexed( @@ -735,29 +789,39 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") + avaxID := genesisTx.ID() - var ( - avaxID = genesisTx.ID() - assetID = avax.Asset{ID: avaxID} - key = keys[0] - kc = secp256k1fx.NewKeychain() - to = key.PublicKey().Address() - changeAddr = to - ) - - kc.Add(key) - - env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildExportTx( - env.service.txBuilderBackend, - constants.PlatformChainID, - to, // to - avaxID, - startBalance-env.vm.TxFee, - kc, - changeAddr, - ) - require.NoError(err) + key := keys[0] + assetID := avax.Asset{ID: avaxID} + tx := &txs.Tx{Unsigned: &txs.ExportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: constants.UnitTestID, + BlockchainID: env.vm.ctx.XChainID, + Ins: []*avax.TransferableInput{{ + UTXOID: avax.UTXOID{ + TxID: avaxID, + OutputIndex: 2, + }, + Asset: assetID, + In: &secp256k1fx.TransferInput{ + Amt: startBalance, + Input: secp256k1fx.Input{SigIndices: []uint32{0}}, + }, + }}, + }}, + DestinationChain: constants.PlatformChainID, + ExportedOuts: []*avax.TransferableOutput{{ + Asset: assetID, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }}, + }} + require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) utxo := avax.UTXOID{ TxID: tx.ID(), @@ -772,7 +836,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }, })) - _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) + _, err := peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) env.vm.ctx.Lock.Unlock() From 1bd4b3a7dc56a735b432ab4f32a94127295c6094 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 26 Apr 2024 13:45:07 +0200 Subject: [PATCH 24/53] reduced diff --- vms/avm/tx.go | 4 ++-- vms/avm/vm.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vms/avm/tx.go b/vms/avm/tx.go index 94d47845d9f..13064a59a18 100644 --- a/vms/avm/tx.go +++ b/vms/avm/tx.go @@ -45,7 +45,7 @@ func (tx *Tx) Accept(context.Context) error { } executor := &executor.Executor{ - Codec: tx.vm.txExecutorBackend.Codec, + Codec: tx.vm.txBackend.Codec, State: tx.vm.state, Tx: tx.tx, } @@ -126,7 +126,7 @@ func (tx *Tx) Verify(context.Context) error { return fmt.Errorf("%w: %s", errTxNotProcessing, s) } return tx.tx.Unsigned.Visit(&executor.SemanticVerifier{ - Backend: tx.vm.txExecutorBackend, + Backend: tx.vm.txBackend, State: tx.vm.state, Tx: tx.tx, }) diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 245b97d72e9..5b74efe88dc 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -108,7 +108,7 @@ type VM struct { addressTxsIndexer index.AddressTxsIndexer - txExecutorBackend *txexecutor.Backend + txBackend *txexecutor.Backend // Cancelled on shutdown onShutdownCtx context.Context @@ -260,7 +260,7 @@ func (vm *VM) Initialize( } } - vm.txExecutorBackend = &txexecutor.Backend{ + vm.txBackend = &txexecutor.Backend{ Ctx: ctx, Config: &vm.Config, Fxs: vm.fxs, @@ -277,7 +277,7 @@ func (vm *VM) Initialize( // onBootstrapStarted is called by the consensus engine when it starts bootstrapping this chain func (vm *VM) onBootstrapStarted() error { - vm.txExecutorBackend.Bootstrapped = false + vm.txBackend.Bootstrapped = false for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapping(); err != nil { return err @@ -287,7 +287,7 @@ func (vm *VM) onBootstrapStarted() error { } func (vm *VM) onNormalOperationsStarted() error { - vm.txExecutorBackend.Bootstrapped = true + vm.txBackend.Bootstrapped = true for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapped(); err != nil { return err @@ -411,13 +411,13 @@ func (vm *VM) Linearize(ctx context.Context, stopVertexID ids.ID, toEngine chan< mempool, vm.metrics, vm.state, - vm.txExecutorBackend, + vm.txBackend, &vm.clock, vm.onAccept, ) vm.Builder = blockbuilder.New( - vm.txExecutorBackend, + vm.txBackend, vm.chainManager, &vm.clock, mempool, @@ -480,7 +480,7 @@ func (vm *VM) ParseTx(_ context.Context, bytes []byte) (snowstorm.Tx, error) { } err = tx.Unsigned.Visit(&txexecutor.SyntacticVerifier{ - Backend: vm.txExecutorBackend, + Backend: vm.txBackend, Tx: tx, }) if err != nil { From 900022857221479fef7fb3c9719c73827d5a8916 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 26 Apr 2024 14:13:12 +0200 Subject: [PATCH 25/53] nit --- vms/avm/tx.go | 4 ++-- vms/avm/vm.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vms/avm/tx.go b/vms/avm/tx.go index 94d47845d9f..13064a59a18 100644 --- a/vms/avm/tx.go +++ b/vms/avm/tx.go @@ -45,7 +45,7 @@ func (tx *Tx) Accept(context.Context) error { } executor := &executor.Executor{ - Codec: tx.vm.txExecutorBackend.Codec, + Codec: tx.vm.txBackend.Codec, State: tx.vm.state, Tx: tx.tx, } @@ -126,7 +126,7 @@ func (tx *Tx) Verify(context.Context) error { return fmt.Errorf("%w: %s", errTxNotProcessing, s) } return tx.tx.Unsigned.Visit(&executor.SemanticVerifier{ - Backend: tx.vm.txExecutorBackend, + Backend: tx.vm.txBackend, State: tx.vm.state, Tx: tx.tx, }) diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 245b97d72e9..5b74efe88dc 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -108,7 +108,7 @@ type VM struct { addressTxsIndexer index.AddressTxsIndexer - txExecutorBackend *txexecutor.Backend + txBackend *txexecutor.Backend // Cancelled on shutdown onShutdownCtx context.Context @@ -260,7 +260,7 @@ func (vm *VM) Initialize( } } - vm.txExecutorBackend = &txexecutor.Backend{ + vm.txBackend = &txexecutor.Backend{ Ctx: ctx, Config: &vm.Config, Fxs: vm.fxs, @@ -277,7 +277,7 @@ func (vm *VM) Initialize( // onBootstrapStarted is called by the consensus engine when it starts bootstrapping this chain func (vm *VM) onBootstrapStarted() error { - vm.txExecutorBackend.Bootstrapped = false + vm.txBackend.Bootstrapped = false for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapping(); err != nil { return err @@ -287,7 +287,7 @@ func (vm *VM) onBootstrapStarted() error { } func (vm *VM) onNormalOperationsStarted() error { - vm.txExecutorBackend.Bootstrapped = true + vm.txBackend.Bootstrapped = true for _, fx := range vm.fxs { if err := fx.Fx.Bootstrapped(); err != nil { return err @@ -411,13 +411,13 @@ func (vm *VM) Linearize(ctx context.Context, stopVertexID ids.ID, toEngine chan< mempool, vm.metrics, vm.state, - vm.txExecutorBackend, + vm.txBackend, &vm.clock, vm.onAccept, ) vm.Builder = blockbuilder.New( - vm.txExecutorBackend, + vm.txBackend, vm.chainManager, &vm.clock, mempool, @@ -480,7 +480,7 @@ func (vm *VM) ParseTx(_ context.Context, bytes []byte) (snowstorm.Tx, error) { } err = tx.Unsigned.Visit(&txexecutor.SyntacticVerifier{ - Backend: vm.txExecutorBackend, + Backend: vm.txBackend, Tx: tx, }) if err != nil { From 309a42ec713e2681662d537b4fb1e9ae9d7a4928 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 26 Apr 2024 14:17:19 +0200 Subject: [PATCH 26/53] consolidated tx creation in UTs --- vms/avm/environment_test.go | 6 - vms/avm/index_test.go | 22 +- vms/avm/service_test.go | 786 ++++++++++++++++++++++++---------- vms/avm/vm_regression_test.go | 133 +++--- vms/avm/vm_test.go | 594 ++++++++++++------------- 5 files changed, 892 insertions(+), 649 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 6045c09bd2f..2d5130d5612 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -76,12 +76,6 @@ var ( keys = secp256k1.TestKeys()[:3] // TODO: Remove [:3] addrs []ids.ShortID // addrs[i] corresponds to keys[i] - - noFeesTestConfig = &config.Config{ - EUpgradeTime: mockable.MaxTime, - TxFee: 0, - CreateAssetTxFee: 0, - } ) func init() { diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 459d4230f32..f2d78c5379a 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,9 +28,7 @@ import ( func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - }) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -72,9 +70,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - }) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -120,9 +116,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - }) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -163,9 +157,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { func TestIndexer_Read(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - }) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() @@ -259,7 +251,7 @@ func buildUTXO(utxoID avax.UTXOID, txAssetID avax.Asset, addr ids.ShortID) *avax UTXOID: utxoID, Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: startBalance, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{addr}, @@ -277,14 +269,14 @@ func buildTX(chainID ids.ID, utxoID avax.UTXOID, txAssetID avax.Asset, address . UTXOID: utxoID, Asset: txAssetID, In: &secp256k1fx.TransferInput{ - Amt: 1000, + Amt: startBalance, Input: secp256k1fx.Input{SigIndices: []uint32{0}}, }, }}, Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: startBalance - testTxFee, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: address, diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 3fd2c5cdbd5..10f03fb3c5a 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -28,8 +28,11 @@ import ( "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/timer/mockable" + "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" + "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -89,7 +92,7 @@ func TestServiceGetTxStatus(t *testing.T) { err := env.service.GetTxStatus(nil, statusArgs, statusReply) require.ErrorIs(err, errNilTxID) - newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := newAvaxBaseTxWithOutputs(t, env) txID := newTx.ID() statusArgs = &api.JSONTxID{ @@ -552,7 +555,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := newAvaxBaseTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := newAvaxBaseTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -578,7 +581,19 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 49000, + "amount": 1000, + "locktime": 0, + "threshold": 1 + } + }, + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1d6kkj0qh4wcmus3tk59npwt3rluc6en72ngurd" + ], + "amount": 48000, "locktime": 0, "threshold": 1 } @@ -637,7 +652,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - newTx := newAvaxExportTxWithOutputs(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.TxFee, env.vm.parser) + newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} @@ -654,7 +669,20 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], "inputs": [ { "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -670,7 +698,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { } ], "memo": "0x", - "destinationChain": "11111111111111111111111111111111LpoYY", + "destinationChain": "2mcwQKiD8VEspmMJpL1dc7okQQ5dDVAWeCBZ7FWBFAbxpv3t7w", "exportedOutputs": [ { "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", @@ -679,7 +707,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], - "amount": 49000, + "amount": 1000, "locktime": 0, "threshold": 1 } @@ -714,7 +742,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -727,7 +755,52 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) reply := api.GetTxReply{} @@ -745,8 +818,34 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 49000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "outputIndex": 2, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 50000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "name": "Team Rocket", "symbol": "TR", @@ -767,6 +866,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "addresses": [ "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" ], + "groupID": 0, "locktime": 0, "threshold": 1 } @@ -816,7 +916,16 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { } ] }, - "credentials": null, + "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xbbdff720789320b7f2b47e230ba8eb2e4b72c7eea52afe4ea1ae2e78ab1b611a318d21160a83bbd5a147848b909ad3859b0b1110e2401fa1c958d42dd6800ed501" + ] + } + } + ], "id": "PLACEHOLDER_TX_ID" }` @@ -830,7 +939,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -844,11 +953,29 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &nftfx.MintOutput{ + GroupID: 2, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildNFTxMintOp(createAssetTx, key, 2, 1)) - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + op := buildNFTxMintOp(createAssetTx, key, 1, 1) + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -866,8 +993,34 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "rSiY2aqcahSU5vyJeMiNBnwtPwfJFxsxskAGbU3HxHvAkrdpy", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -875,7 +1028,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 1 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -901,11 +1054,19 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" + ] + } + }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "PLACEHOLDER_SIGNATURE" + "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" ] } } @@ -917,7 +1078,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -929,7 +1090,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -943,14 +1104,32 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + GroupID: 0, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintOp1 := buildNFTxMintOp(createAssetTx, key, 2, 1) - mintOp2 := buildNFTxMintOp(createAssetTx, key, 3, 2) - mintNFTTx := buildOperationTxWithOp(env.vm.ctx.ChainID, mintOp1, mintOp2) - - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + mintOp1 := buildNFTxMintOp(createAssetTx, key, 1, 0) + mintOp2 := buildNFTxMintOp(createAssetTx, key, 2, 1) + mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -968,8 +1147,34 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "BBhSA95iv6ueXc7xrMSka1bByBqcwJxyvMiyjy5H8ccAgxy4P", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -977,7 +1182,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 2 + "outputIndex": 1 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -987,7 +1192,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 1, + "groupID": 0, "payload": "0x68656c6c6f", "outputs": [ { @@ -1005,7 +1210,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 3 + "outputIndex": 2 } ], "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", @@ -1015,7 +1220,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { 0 ] }, - "groupID": 2, + "groupID": 1, "payload": "0x68656c6c6f", "outputs": [ { @@ -1032,13 +1237,21 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }, "credentials": [ { - "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ "PLACEHOLDER_SIGNATURE" ] } }, + { + "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", + "credential": { + "signatures": [ + "0xc958811e7430677ed15c40ac1d7f6232e8f5060aecf4cd8c45ef1614d9c9a5be5b5d5e697da4e40c743c010bab7bca58d9970b1cc5f3dc15b2f6d9adc712289f00" + ] + } + }, { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { @@ -1055,7 +1268,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintNFTTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintNFTTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[0].Credential.(*nftfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1067,7 +1280,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1081,11 +1294,26 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &nftfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildSecpMintOp(createAssetTx, key, 0)) - require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + op := buildSecpMintOp(createAssetTx, key, 1) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1103,8 +1331,34 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2YhAg3XUdub5syHHePZG7q3yFjKAy7ahsvQDxq5SMrYbN1s5Gn", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1112,7 +1366,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 0 + "outputIndex": 1 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1149,6 +1403,14 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } + }, + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xad7f3f3cd2667eda64e6f9ca3ab0db21238c20a0174f590b5d9fdf69fa009d073b50d7e0db156cb3678c23509cb7adf767fc98119a683560950a1e8f3299d17800" + ] + } } ], "id": "PLACEHOLDER_TX_ID" @@ -1170,7 +1432,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1184,14 +1446,30 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(0): { + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + uint32(1): { + &secp256k1fx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildSecpMintOp(createAssetTx, key, 0) - op2 := buildSecpMintOp(createAssetTx, key, 1) - mintSecpOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) - - require.NoError(mintSecpOpTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + op1 := buildSecpMintOp(createAssetTx, key, 1) + op2 := buildSecpMintOp(createAssetTx, key, 2) + mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1209,8 +1487,34 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2vxorPLUw5sneb7Mdhhjuws3H5AqaDp1V8ETz6fEuzvn835rVX", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1218,7 +1522,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 0 + "outputIndex": 1 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1250,7 +1554,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 1 + "outputIndex": 2 } ], "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", @@ -1295,6 +1599,14 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "PLACEHOLDER_SIGNATURE" ] } + }, + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xeada420035b6ad5e658e96abab39622c5aa730bda266374af4ddb264696fa998584823d34f7df3a5cb03c5cec3068365ece9a5b7242193a862e9e0459a8865b801" + ] + } } ], "id": "PLACEHOLDER_TX_ID" @@ -1316,7 +1628,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1330,11 +1642,21 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, buildPropertyFxMintOp(createAssetTx, key, 4)) - require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + op := buildPropertyFxMintOp(createAssetTx, key, 1) + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1352,8 +1674,34 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "nNUGBjszswU3ZmhCb8hBNWmg335UZqGWmNrYTAGyMF4bFpMXm", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1361,7 +1709,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 4 + "outputIndex": 1 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1388,6 +1736,14 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xa5c7a3fac9f87479fafc347510e270e86da9e99ad606f31342baf1440674b1b53ea836b9a1cfee11eb85b96e1b8e547e2206758d3e902d9e14f6dd784172363401" + ] + } + }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1404,7 +1760,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) @@ -1416,7 +1772,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -1430,14 +1786,28 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }() key := keys[0] - createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env.vm.ctx.ChainID, env.vm.parser) + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, + }, + }, + }, + } + createAssetTx := newAvaxCreateAssetTxWithOutputs(t, env, initialStates) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - op1 := buildPropertyFxMintOp(createAssetTx, key, 4) - op2 := buildPropertyFxMintOp(createAssetTx, key, 5) - mintPropertyFxOpTx := buildOperationTxWithOp(env.vm.ctx.ChainID, op1, op2) - - require.NoError(mintPropertyFxOpTx.SignPropertyFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}, {key}})) + op1 := buildPropertyFxMintOp(createAssetTx, key, 1) + op2 := buildPropertyFxMintOp(createAssetTx, key, 2) + mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1455,8 +1825,34 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "unsignedTx": { "networkID": 10, "blockchainID": "PLACEHOLDER_BLOCKCHAIN_ID", - "outputs": null, - "inputs": null, + "outputs": [ + { + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "output": { + "addresses": [ + "X-testing1lnk637g0edwnqc2tn8tel39652fswa3xk4r65e" + ], + "amount": 48000, + "locktime": 0, + "threshold": 1 + } + } + ], + "inputs": [ + { + "txID": "2NV5AGoQQHVRY6VkT8sht8bhZDHR7uwta7fk7JwAZpacqMRWCa", + "outputIndex": 0, + "assetID": "2XGxUr7VF7j1iwUp2aiGe4b6Ue2yyNghNS1SuNTNmZ77dPpXFZ", + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "input": { + "amount": 49000, + "signatureIndices": [ + 0 + ] + } + } + ], "memo": "0x", "operations": [ { @@ -1464,7 +1860,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 4 + "outputIndex": 1 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1493,7 +1889,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "inputIDs": [ { "txID": "PLACEHOLDER_CREATE_ASSET_TX_ID", - "outputIndex": 5 + "outputIndex": 2 } ], "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", @@ -1520,6 +1916,14 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) ] }, "credentials": [ + { + "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", + "credential": { + "signatures": [ + "0xbf14b82775f2b260d77d4d790b0873e8cdb243e20bc95ca65bd08645f70845bd662ec4437b6599b0e4f86ad3d68ddfcd058bf0c729054aad609a26ba539b3b3300" + ] + } + }, { "fxID": "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy", "credential": { @@ -1544,7 +1948,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", mintPropertyFxOpTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", mintPropertyFxOpTx.Unsigned.(*txs.OperationTx).BlockchainID.String(), 1) - sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[0].Credential.(*propertyfx.Credential).Sigs[0][:]) + sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) @@ -1552,161 +1956,76 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) require.Equal(expectedReplyTxString, string(replyTxBytes)) } -func newAvaxBaseTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { - avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") - key := keys[0] - tx := buildTestBaseTx(avaxTx, chainID, fee, key) - require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - return tx -} - -func newAvaxExportTxWithOutputs(t *testing.T, genesisBytes []byte, chainID ids.ID, fee uint64, parser txs.Parser) *txs.Tx { - avaxTx := getCreateTxFromGenesisTest(t, genesisBytes, "AVAX") - key := keys[0] - tx := buildTestExportTx(avaxTx, chainID, fee, key) - require.NoError(t, tx.SignSECP256K1Fx(parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - return tx -} - -func newAvaxCreateAssetTxWithOutputs(t *testing.T, chainID ids.ID, parser txs.Parser) *txs.Tx { - key := keys[0] - tx := buildTestCreateAssetTx(chainID, key) - require.NoError(t, tx.Initialize(parser.Codec())) - return tx -} - -func buildTestBaseTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - Memo: []byte{1, 2, 3, 4, 5, 6, 7, 8}, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, - }, - }}, - Outs: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - fee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }, - }} -} - -func buildTestExportTx(avaxTx *txs.Tx, chainID ids.ID, fee uint64, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }, - }, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxTx.ID()}, +func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { + var ( + memo = []byte{1, 2, 3, 4, 5, 6, 7, 8} + key = keys[0] + changeKey = keys[1] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildBaseTx( + env.service.txBuilderBackend, + []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: env.vm.feeAssetID}, Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - fee, + Amt: units.MicroAvax, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, }}, - }} + memo, + kc, + changeKey.PublicKey().Address(), + ) + require.NoError(t, err) + return tx } -func buildTestCreateAssetTx(chainID ids.ID, key *secp256k1.PrivateKey) *txs.Tx { - return &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, &secp256k1fx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - }, - { - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }, - }, - { - FxIndex: 2, - Outs: []verify.State{ - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }, - }, - }, - }} +func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStates map[uint32][]verify.State) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + tx, _, err := buildCreateAssetTx( + env.service.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, + kc, + key.Address(), + ) + require.NoError(t, err) + return tx +} + +func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + ) + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildExportTx( + env.service.txBuilderBackend, + chainID, + to, + env.vm.feeAssetID, + units.MicroAvax, + kc, + key.Address(), + ) + require.NoError(t, err) + return tx } func buildNFTxMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputIndex, groupID uint32) *txs.Operation { @@ -1782,14 +2101,22 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd } } -func buildOperationTxWithOp(chainID ids.ID, op ...*txs.Operation) *txs.Tx { - return &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: chainID, - }}, - Ops: op, - }} +func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation) *txs.Tx { + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildOperation( + env.service.txBuilderBackend, + ops, + kc, + key.Address(), + ) + require.NoError(t, err) + return tx } func TestServiceGetNilTx(t *testing.T) { @@ -2561,6 +2888,9 @@ func TestSendMultiple(t *testing.T) { password: password, initialKeys: keys, }}, + vmStaticConfig: &config.Config{ + EUpgradeTime: mockable.MaxTime, + }, }) env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 0151ccaf6da..0c4940d2460 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -10,9 +10,6 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/nftfx" @@ -22,9 +19,7 @@ import ( func TestVerifyFxUsage(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - }) + env := setup(t, &envConfig{fork: latest}) env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -32,85 +27,81 @@ func TestVerifyFxUsage(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{ - { - FxIndex: 0, - Outs: []verify.State{ - &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + initialStates := map[uint32][]verify.State{ + uint32(0): { + &secp256k1fx.TransferOutput{ + Amt: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, - { - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, + }, + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, }, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + } + + // Create the asset + createAssetTx, _, err := buildCreateAssetTx( + env.service.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, + // Mint the NFT + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + mintNFTTx, err := mintNFT( + env.service.txBuilderBackend, + createAssetTx.ID(), + []byte{'h', 'e', 'l', 'l', 'o'}, // payload + []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{key.Address()}, }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 1, - }}, - Op: &nftfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - Outputs: []*secp256k1fx.OutputOwners{{}}, - }, - }}, - }} - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - spendTx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }, + // move the NFT + to := keys[2].PublicKey().Address() + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + spendTx, _, err := buildBaseTx( + env.service.txBuilderBackend, + []*avax.TransferableOutput{{ Asset: avax.Asset{ID: createAssetTx.ID()}, - In: &secp256k1fx.TransferInput{ + Out: &secp256k1fx.TransferOutput{ Amt: 1, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{to}, }, }, }}, - }}} - require.NoError(spendTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + nil, // memo + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, spendTx) } diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 25824f4d009..9ca514c53bb 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -19,7 +19,6 @@ import ( "github.com/ava-labs/avalanchego/snow/snowtest" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -133,7 +132,7 @@ func TestIssueNFT(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, }) env.vm.ctx.Lock.Unlock() defer func() { @@ -142,90 +141,73 @@ func TestIssueNFT(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{{ - FxIndex: 1, - Outs: []verify.State{ - &nftfx.MintOutput{ - GroupID: 1, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - &nftfx.MintOutput{ - GroupID: 2, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + // Create the asset + initialStates := map[uint32][]verify.State{ + uint32(1): { + &nftfx.MintOutput{ + GroupID: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - }}, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + }, + } + + createAssetTx, _, err := buildCreateAssetTx( + env.service.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintNFTTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, + // Mint the NFT + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + mintNFTTx, err := mintNFT( + env.service.txBuilderBackend, + createAssetTx.ID(), + []byte{'h', 'e', 'l', 'l', 'o'}, // payload + []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{key.Address()}, }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }}, - Op: &nftfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - Outputs: []*secp256k1fx.OutputOwners{{}}, - }, - }}, - }} - require.NoError(mintNFTTx.SignNFTFx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}})) + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) - transferNFTTx := &txs.Tx{ - Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: mintNFTTx.ID(), - OutputIndex: 0, - }}, - Op: &nftfx.TransferOperation{ - Input: secp256k1fx.Input{}, - Output: nftfx.TransferOutput{ - GroupID: 1, - Payload: []byte{'h', 'e', 'l', 'l', 'o'}, - OutputOwners: secp256k1fx.OutputOwners{}, - }, - }, - }}, - }, - Creds: []*fxs.FxCredential{ - { - Credential: &nftfx.Credential{}, - }, - }, - } - require.NoError(transferNFTTx.Initialize(env.vm.parser.Codec())) + // Move the NFT + utxos, err := avax.GetAllUTXOs(env.vm.state, kc.Addresses()) + require.NoError(err) + transferOp, _, err := env.vm.SpendNFT( + utxos, + kc, + createAssetTx.ID(), + 1, + keys[2].Address(), + ) + require.NoError(err) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + transferNFTTx, err := buildOperation( + env.service.txBuilderBackend, + transferOp, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, transferNFTTx) } @@ -234,7 +216,7 @@ func TestIssueProperty(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: latest, additionalFxs: []*common.Fx{{ ID: propertyfx.ID, Fx: &propertyfx.Fx{}, @@ -247,79 +229,85 @@ func TestIssueProperty(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - createAssetTx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - }}, - Name: "Team Rocket", - Symbol: "TR", - Denomination: 0, - States: []*txs.InitialState{{ - FxIndex: 2, - Outs: []verify.State{ - &propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + // create the asset + initialStates := map[uint32][]verify.State{ + uint32(2): { + &propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, }, - }}, - }} - require.NoError(createAssetTx.Initialize(env.vm.parser.Codec())) + }, + } + + createAssetTx, _, err := buildCreateAssetTx( + env.service.txBuilderBackend, + "Team Rocket", // name + "TR", // symbol + 0, // denomination + initialStates, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, createAssetTx) - mintPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, + // mint the property + mintPropertyOp := &txs.Operation{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: createAssetTx.ID(), + OutputIndex: 1, }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: createAssetTx.ID(), - OutputIndex: 0, - }}, - Op: &propertyfx.MintOperation{ - MintInput: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - MintOutput: propertyfx.MintOutput{ - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, + Op: &propertyfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: []uint32{0}, + }, + MintOutput: propertyfx.MintOutput{ + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, }, - OwnedOutput: propertyfx.OwnedOutput{}, }, - }}, - }} + OwnedOutput: propertyfx.OwnedOutput{}, + }, + } - codec := env.vm.parser.Codec() - require.NoError(mintPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ - {keys[0]}, - })) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + mintPropertyTx, err := buildOperation( + env.service.txBuilderBackend, + []*txs.Operation{mintPropertyOp}, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, mintPropertyTx) - burnPropertyTx := &txs.Tx{Unsigned: &txs.OperationTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, + // burn the property + burnPropertyOp := &txs.Operation{ + Asset: avax.Asset{ID: createAssetTx.ID()}, + UTXOIDs: []*avax.UTXOID{{ + TxID: mintPropertyTx.ID(), + OutputIndex: 2, }}, - Ops: []*txs.Operation{{ - Asset: avax.Asset{ID: createAssetTx.ID()}, - UTXOIDs: []*avax.UTXOID{{ - TxID: mintPropertyTx.ID(), - OutputIndex: 1, - }}, - Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, - }}, - }} + Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, + } - require.NoError(burnPropertyTx.SignPropertyFx(codec, [][]*secp256k1.PrivateKey{ - {}, - })) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + burnPropertyTx, err := buildOperation( + env.service.txBuilderBackend, + []*txs.Operation{burnPropertyOp}, + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, burnPropertyTx) } @@ -357,51 +345,45 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { }() // send second asset - feeAssetCreateTx := getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) - createTx := getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() - tx := &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{ - // fee asset - { - UTXOID: avax.UTXOID{ - TxID: feeAssetCreateTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, + feeAssetCreateTx = getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) + createTx = getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) + ) + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildBaseTx( + env.service.txBuilderBackend, + []*avax.TransferableOutput{ + { // fee asset + Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - // issued asset - { - UTXOID: avax.UTXOID{ - TxID: createTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: createTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, + }, + { // issued asset + Asset: avax.Asset{ID: createTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, }, }, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{keys[0]}, {keys[0]}})) - + nil, // memo + kc, + key.Address(), + ) + require.NoError(err) issueAndAccept(require, env.vm, env.issuer, tx) } @@ -445,40 +427,32 @@ func TestTxAcceptAfterParseTx(t *testing.T) { env.vm.ctx.Lock.Unlock() }() - key := keys[0] - firstTx := &txs.Tx{Unsigned: &txs.BaseTx{ - BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: env.genesisTx.ID(), - OutputIndex: 2, - }, - Asset: avax.Asset{ID: env.genesisTx.ID()}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{ - SigIndices: []uint32{ - 0, - }, - }, - }, - }}, - Outs: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: env.genesisTx.ID()}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() + ) + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + firstTx, _, err := buildBaseTx( + env.service.txBuilderBackend, + []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: env.genesisTx.ID()}, + Out: &secp256k1fx.TransferOutput{ + Amt: startBalance - env.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, - }}, - }, - }} - require.NoError(firstTx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + }, + }}, + nil, // memo + kc, + key.Address(), + ) + require.NoError(err) + // let secondTx spend firstTx outputs secondTx := &txs.Tx{Unsigned: &txs.BaseTx{ BaseTx: avax.BaseTx{ NetworkID: constants.UnitTestID, @@ -526,7 +500,7 @@ func TestIssueImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, + fork: durango, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -538,63 +512,38 @@ func TestIssueImportTx(t *testing.T) { genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() - key := keys[0] - utxoID := avax.UTXOID{ - TxID: ids.ID{ - 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, - 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, - 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, - 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, - }, - } + var ( + key = keys[0] + kc = secp256k1fx.NewKeychain() - txAssetID := avax.Asset{ID: avaxID} - tx := &txs.Tx{Unsigned: &txs.ImportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Outs: []*avax.TransferableOutput{{ - Asset: txAssetID, - Out: &secp256k1fx.TransferOutput{ - Amt: 1000, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, - }, - }, - }}, - }}, - SourceChain: constants.PlatformChainID, - ImportedIns: []*avax.TransferableInput{{ + utxoID = avax.UTXOID{ + TxID: ids.ID{ + 0x0f, 0x2f, 0x4f, 0x6f, 0x8e, 0xae, 0xce, 0xee, + 0x0d, 0x2d, 0x4d, 0x6d, 0x8c, 0xac, 0xcc, 0xec, + 0x0b, 0x2b, 0x4b, 0x6b, 0x8a, 0xaa, 0xca, 0xea, + 0x09, 0x29, 0x49, 0x69, 0x88, 0xa8, 0xc8, 0xe8, + }, + } + txAssetID = avax.Asset{ID: avaxID} + importedUtxo = &avax.UTXO{ UTXOID: utxoID, Asset: txAssetID, - In: &secp256k1fx.TransferInput{ + Out: &secp256k1fx.TransferOutput{ Amt: 1010, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{key.PublicKey().Address()}, }, }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + } + ) + kc.Add(key) // Provide the platform UTXO: - utxo := &avax.UTXO{ - UTXOID: utxoID, - Asset: txAssetID, - Out: &secp256k1fx.TransferOutput{ - Amt: 1010, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - } - - utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, utxo) + utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, importedUtxo) require.NoError(err) - inputID := utxo.InputID() + inputID := importedUtxo.InputID() require.NoError(peerSharedMemory.Apply(map[ids.ID]*atomic.Requests{ env.vm.ctx.ChainID: { PutRequests: []*atomic.Element{{ @@ -607,6 +556,15 @@ func TestIssueImportTx(t *testing.T) { }, })) + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, err := buildImportTx( + env.service.txBuilderBackend, + constants.PlatformChainID, // source chain + key.Address(), + kc, + ) + require.NoError(err) + env.vm.ctx.Lock.Unlock() issueAndAccept(require, env.vm, env.issuer, tx) @@ -626,8 +584,8 @@ func TestForceAcceptImportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{ - vmStaticConfig: noFeesTestConfig, - notLinearized: true, + fork: durango, + notLinearized: true, }) defer func() { require.NoError(env.vm.Shutdown(context.Background())) @@ -655,7 +613,7 @@ func TestForceAcceptImportTx(t *testing.T) { Outs: []*avax.TransferableOutput{{ Asset: txAssetID, Out: &secp256k1fx.TransferOutput{ - Amt: 1000, + Amt: 10, OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{keys[0].PublicKey().Address()}, @@ -703,47 +661,35 @@ func TestImportTxNotState(t *testing.T) { func TestIssueExportTx(t *testing.T) { require := require.New(t) - env := setup(t, &envConfig{ - fork: latest, - }) + env := setup(t, &envConfig{fork: durango}) defer func() { require.NoError(env.vm.Shutdown(context.Background())) env.vm.ctx.Lock.Unlock() }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") - avaxID := genesisTx.ID() - key := keys[0] - tx := &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxID, - OutputIndex: 2, - }, - Asset: avax.Asset{ID: avaxID}, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }}, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxID}, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + var ( + avaxID = genesisTx.ID() + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + changeAddr = to + ) + + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildExportTx( + env.service.txBuilderBackend, + constants.PlatformChainID, + to, // to + avaxID, + startBalance-env.vm.TxFee, + kc, + changeAddr, + ) + require.NoError(err) peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) utxoBytes, _, _, err := peerSharedMemory.Indexed( @@ -789,39 +735,29 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") - avaxID := genesisTx.ID() - key := keys[0] - assetID := avax.Asset{ID: avaxID} - tx := &txs.Tx{Unsigned: &txs.ExportTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ - NetworkID: constants.UnitTestID, - BlockchainID: env.vm.ctx.XChainID, - Ins: []*avax.TransferableInput{{ - UTXOID: avax.UTXOID{ - TxID: avaxID, - OutputIndex: 2, - }, - Asset: assetID, - In: &secp256k1fx.TransferInput{ - Amt: startBalance, - Input: secp256k1fx.Input{SigIndices: []uint32{0}}, - }, - }}, - }}, - DestinationChain: constants.PlatformChainID, - ExportedOuts: []*avax.TransferableOutput{{ - Asset: assetID, - Out: &secp256k1fx.TransferOutput{ - Amt: startBalance - env.vm.TxFee, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{key.PublicKey().Address()}, - }, - }, - }}, - }} - require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + var ( + avaxID = genesisTx.ID() + assetID = avax.Asset{ID: avaxID} + key = keys[0] + kc = secp256k1fx.NewKeychain() + to = key.PublicKey().Address() + changeAddr = to + ) + + kc.Add(key) + + env.service.txBuilderBackend.ResetAddresses(kc.Addresses()) + tx, _, err := buildExportTx( + env.service.txBuilderBackend, + constants.PlatformChainID, + to, // to + avaxID, + startBalance-env.vm.TxFee, + kc, + changeAddr, + ) + require.NoError(err) utxo := avax.UTXOID{ TxID: tx.ID(), @@ -836,7 +772,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { }, })) - _, err := peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) + _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) env.vm.ctx.Lock.Unlock() From 3aba33c40c2593debd9356e8fe396b4c3a00ccc5 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 8 May 2024 18:53:42 +0200 Subject: [PATCH 27/53] cleanup --- vms/avm/service.go | 17 ++--- vms/avm/service_backend.go | 12 ++-- vms/avm/{ => txs/builder}/tx_builders.go | 85 ++++++++++++------------ vms/avm/wallet_service.go | 3 +- vms/avm/wallet_service_backend.go | 12 ++-- 5 files changed, 67 insertions(+), 62 deletions(-) rename vms/avm/{ => txs/builder}/tx_builders.go (68%) diff --git a/vms/avm/service.go b/vms/avm/service.go index 28961c18e7a..903db39f379 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -22,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/keystore" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -793,7 +794,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildCreateAssetTx( + return builder.BuildCreateAssetTx( s.txBuilderBackend, args.Name, args.Symbol, @@ -914,7 +915,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildCreateAssetTx( + return builder.BuildCreateAssetTx( s.txBuilderBackend, args.Name, args.Symbol, @@ -1232,7 +1233,7 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildBaseTx(s.txBuilderBackend, outs, memoBytes, kc, changeAddr) + return builder.BuildBaseTx(s.txBuilderBackend, outs, memoBytes, kc, changeAddr) } // MintArgs are arguments for passing into Mint requests @@ -1328,7 +1329,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := mintFTs(s.txBuilderBackend, outputs, feeKc, changeAddr) + tx, err := builder.MintFTs(s.txBuilderBackend, outputs, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1415,7 +1416,7 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := buildOperation(s.txBuilderBackend, ops, kc, changeAddr) + tx, err := builder.BuildOperation(s.txBuilderBackend, ops, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1502,7 +1503,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := mintNFT( + tx, err := builder.MintNFT( s.txBuilderBackend, assetID, payloadBytes, @@ -1574,7 +1575,7 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return nil, err } - return buildImportTx(s.txBuilderBackend, chainID, to, kc) + return builder.BuildImportTx(s.txBuilderBackend, chainID, to, kc) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1668,5 +1669,5 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { } s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return buildExportTx(s.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) + return builder.BuildExportTx(s.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) } diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go index aa40cf349f6..ee1a350d5f8 100644 --- a/vms/avm/service_backend.go +++ b/vms/avm/service_backend.go @@ -15,11 +15,13 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/chain/x/builder" + + walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) -var _ txBuilderBackend = (*serviceBackend)(nil) +var _ builder.TxBuilderBackend = (*serviceBackend)(nil) func newServiceBackend( feeAssetID ids.ID, @@ -29,7 +31,7 @@ func newServiceBackend( sharedMemory atomic.SharedMemory, codec codec.Manager, ) *serviceBackend { - backendCtx := &builder.Context{ + backendCtx := &walletbuilder.Context{ NetworkID: ctx.NetworkID, BlockchainID: ctx.XChainID, AVAXAssetID: feeAssetID, @@ -48,7 +50,7 @@ func newServiceBackend( } type serviceBackend struct { - ctx *builder.Context + ctx *walletbuilder.Context xchainID ids.ID cfg *config.Config addrs set.Set[ids.ShortID] @@ -57,7 +59,7 @@ type serviceBackend struct { codec codec.Manager } -func (b *serviceBackend) Context() *builder.Context { +func (b *serviceBackend) Context() *walletbuilder.Context { return b.ctx } diff --git a/vms/avm/tx_builders.go b/vms/avm/txs/builder/tx_builders.go similarity index 68% rename from vms/avm/tx_builders.go rename to vms/avm/txs/builder/tx_builders.go index dc07c7ea959..e432f61d2ae 100644 --- a/vms/avm/tx_builders.go +++ b/vms/avm/txs/builder/tx_builders.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package avm +package builder import ( "context" @@ -13,31 +13,30 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" "github.com/ava-labs/avalanchego/wallet/chain/x/signer" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" - - walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) -type txBuilderBackend interface { - walletbuilder.Backend +type TxBuilderBackend interface { + builder.Backend signer.Backend - Context() *walletbuilder.Context + Context() *builder.Context ResetAddresses(addrs set.Set[ids.ShortID]) } -func buildCreateAssetTx( - backend txBuilderBackend, +func BuildCreateAssetTx( + backend TxBuilderBackend, name, symbol string, denomination byte, initialStates map[uint32][]verify.State, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) - utx, err := pBuilder.NewCreateAssetTx( + utx, err := xBuilder.NewCreateAssetTx( name, symbol, denomination, @@ -48,7 +47,7 @@ func buildCreateAssetTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } @@ -56,16 +55,16 @@ func buildCreateAssetTx( return tx, changeAddr, nil } -func buildBaseTx( - backend txBuilderBackend, +func BuildBaseTx( + backend TxBuilderBackend, outs []*avax.TransferableOutput, memo []byte, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) - utx, err := pBuilder.NewBaseTx( + utx, err := xBuilder.NewBaseTx( outs, options(changeAddr, memo)..., ) @@ -73,7 +72,7 @@ func buildBaseTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } @@ -81,17 +80,17 @@ func buildBaseTx( return tx, changeAddr, nil } -func mintNFT( - backend txBuilderBackend, +func MintNFT( + backend TxBuilderBackend, assetID ids.ID, payload []byte, owners []*secp256k1fx.OutputOwners, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) - utx, err := pBuilder.NewOperationTxMintNFT( + utx, err := xBuilder.NewOperationTxMintNFT( assetID, payload, owners, @@ -101,18 +100,18 @@ func mintNFT( return nil, fmt.Errorf("failed minting NFTs: %w", err) } - return signer.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), xSigner, utx) } -func mintFTs( - backend txBuilderBackend, +func MintFTs( + backend TxBuilderBackend, outputs map[ids.ID]*secp256k1fx.TransferOutput, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) - utx, err := pBuilder.NewOperationTxMintFT( + utx, err := xBuilder.NewOperationTxMintFT( outputs, options(changeAddr, nil /*memo*/)..., ) @@ -120,18 +119,18 @@ func mintFTs( return nil, fmt.Errorf("failed minting FTs: %w", err) } - return signer.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), xSigner, utx) } -func buildOperation( - backend txBuilderBackend, +func BuildOperation( + backend TxBuilderBackend, ops []*txs.Operation, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) - utx, err := pBuilder.NewOperationTx( + utx, err := xBuilder.NewOperationTx( ops, options(changeAddr, nil /*memo*/)..., ) @@ -139,16 +138,16 @@ func buildOperation( return nil, fmt.Errorf("failed building operation tx: %w", err) } - return signer.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), xSigner, utx) } -func buildImportTx( - backend txBuilderBackend, +func BuildImportTx( + backend TxBuilderBackend, sourceChain ids.ID, to ids.ShortID, kc *secp256k1fx.Keychain, ) (*txs.Tx, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) outOwner := &secp256k1fx.OutputOwners{ Locktime: 0, @@ -156,7 +155,7 @@ func buildImportTx( Addrs: []ids.ShortID{to}, } - utx, err := pBuilder.NewImportTx( + utx, err := xBuilder.NewImportTx( sourceChain, outOwner, ) @@ -164,11 +163,11 @@ func buildImportTx( return nil, fmt.Errorf("failed building import tx: %w", err) } - return signer.SignUnsigned(context.Background(), pSigner, utx) + return signer.SignUnsigned(context.Background(), xSigner, utx) } -func buildExportTx( - backend txBuilderBackend, +func BuildExportTx( + backend TxBuilderBackend, destinationChain ids.ID, to ids.ShortID, exportedAssetID ids.ID, @@ -176,7 +175,7 @@ func buildExportTx( kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - pBuilder, pSigner := builders(backend, kc) + xBuilder, xSigner := builders(backend, kc) outputs := []*avax.TransferableOutput{{ Asset: avax.Asset{ID: exportedAssetID}, @@ -190,7 +189,7 @@ func buildExportTx( }, }} - utx, err := pBuilder.NewExportTx( + utx, err := xBuilder.NewExportTx( destinationChain, outputs, options(changeAddr, nil /*memo*/)..., @@ -199,17 +198,17 @@ func buildExportTx( return nil, ids.ShortEmpty, fmt.Errorf("failed building export tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), pSigner, utx) + tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { return nil, ids.ShortEmpty, err } return tx, changeAddr, nil } -func builders(backend txBuilderBackend, kc *secp256k1fx.Keychain) (walletbuilder.Builder, signer.Signer) { +func builders(backend TxBuilderBackend, kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { var ( addrs = kc.Addresses() - builder = walletbuilder.New(addrs, backend.Context(), backend) + builder = builder.New(addrs, backend.Context(), backend) signer = signer.New(kc, backend) ) diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index 9ccf9e42d5b..8bcf9cde3d5 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/secp256k1fx" @@ -223,7 +224,7 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re } w.walletServiceBackend.ResetAddresses(kc.Addresses()) - tx, _, err := buildBaseTx(w.walletServiceBackend, outs, memoBytes, kc, changeAddr) + tx, _, err := builder.BuildBaseTx(w.walletServiceBackend, outs, memoBytes, kc, changeAddr) if err != nil { return err } diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go index 195cfb71248..110458cf6e2 100644 --- a/vms/avm/wallet_service_backend.go +++ b/vms/avm/wallet_service_backend.go @@ -13,14 +13,16 @@ import ( "github.com/ava-labs/avalanchego/utils/linked" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/chain/x/builder" + + walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) -var _ txBuilderBackend = (*walletServiceBackend)(nil) +var _ builder.TxBuilderBackend = (*walletServiceBackend)(nil) func NewWalletServiceBackend(vm *VM) *walletServiceBackend { - backendCtx := &builder.Context{ + backendCtx := &walletbuilder.Context{ NetworkID: vm.ctx.NetworkID, BlockchainID: vm.ctx.XChainID, AVAXAssetID: vm.feeAssetID, @@ -37,7 +39,7 @@ func NewWalletServiceBackend(vm *VM) *walletServiceBackend { } type walletServiceBackend struct { - ctx *builder.Context + ctx *walletbuilder.Context vm *VM pendingTxs *linked.Hashmap[ids.ID, *txs.Tx] utxos []*avax.UTXO @@ -45,7 +47,7 @@ type walletServiceBackend struct { addrs set.Set[ids.ShortID] } -func (b *walletServiceBackend) Context() *builder.Context { +func (b *walletServiceBackend) Context() *walletbuilder.Context { return b.ctx } From 3fea872db3dc3bfc5cb501da6a1d81034611ed6d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 9 May 2024 09:30:17 +0200 Subject: [PATCH 28/53] cleanup --- vms/avm/environment_test.go | 23 +++++++++-- vms/avm/service.go | 36 +++++------------ vms/avm/service_backend.go | 17 -------- vms/avm/txs/builder/context.go | 25 ++++++++++++ vms/avm/txs/builder/tx_builders.go | 62 +++++++++++++++++------------- vms/avm/vm.go | 21 ++++++++-- vms/avm/wallet_service.go | 4 +- vms/avm/wallet_service_backend.go | 16 -------- 8 files changed, 111 insertions(+), 93 deletions(-) create mode 100644 vms/avm/txs/builder/context.go diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 6045c09bd2f..59d27b40636 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -31,6 +31,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/nftfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" @@ -203,6 +204,11 @@ func setup(tb testing.TB, c *envConfig) *environment { stopVertexID := ids.GenerateTestID() issuer := make(chan common.Message, 1) + var ( + serviceBackend = newServiceBackend(vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) + walletBackend = NewWalletServiceBackend(vm) + ) + env := &environment{ genesisBytes: genesisBytes, genesisTx: getCreateTxFromGenesisTest(tb, genesisBytes, assetName), @@ -210,11 +216,22 @@ func setup(tb testing.TB, c *envConfig) *environment { issuer: issuer, vm: vm, service: &Service{ - vm: vm, - txBuilderBackend: newServiceBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), + vm: vm, + b: builder.NewBuilder( + vm.ctx, + &vm.Config, + vm.feeAssetID, + serviceBackend, + ), }, walletService: &WalletService{ - walletServiceBackend: NewWalletServiceBackend(vm), + walletServiceBackend: walletBackend, + b: builder.NewBuilder( + vm.ctx, + &vm.Config, + vm.feeAssetID, + walletBackend, + ), }, } diff --git a/vms/avm/service.go b/vms/avm/service.go index 903db39f379..214c12cdf3c 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -62,8 +62,8 @@ type FormattedAssetID struct { // Service defines the base service for the asset vm type Service struct { - vm *VM - txBuilderBackend *serviceBackend + vm *VM + b *builder.Builder } // GetBlock returns the requested block. @@ -793,9 +793,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI initialStateOuts = append(initialStateOuts, minter) } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return builder.BuildCreateAssetTx( - s.txBuilderBackend, + return s.b.BuildCreateAssetTx( args.Name, args.Symbol, args.Denomination, @@ -914,9 +912,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh initialStateOuts = append(initialStateOuts, minter) } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return builder.BuildCreateAssetTx( - s.txBuilderBackend, + return s.b.BuildCreateAssetTx( args.Name, args.Symbol, 0, // NFTs are non-fungible @@ -1232,8 +1228,7 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return builder.BuildBaseTx(s.txBuilderBackend, outs, memoBytes, kc, changeAddr) + return s.b.BuildBaseTx(outs, memoBytes, kc, changeAddr) } // MintArgs are arguments for passing into Mint requests @@ -1312,12 +1307,6 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - // Get all UTXOs/keys for the user - _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) - if err != nil { - return nil, ids.ShortEmpty, err - } - outputs := map[ids.ID]*secp256k1fx.TransferOutput{ assetID: { Amt: uint64(args.Amount), @@ -1328,8 +1317,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { }, } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := builder.MintFTs(s.txBuilderBackend, outputs, feeKc, changeAddr) + tx, err := s.b.MintFTs(outputs, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1415,8 +1403,7 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := builder.BuildOperation(s.txBuilderBackend, ops, kc, changeAddr) + tx, err := s.b.BuildOperation(ops, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1502,9 +1489,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - tx, err := builder.MintNFT( - s.txBuilderBackend, + tx, err := s.b.MintNFT( assetID, payloadBytes, []*secp256k1fx.OutputOwners{{ @@ -1575,7 +1560,7 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return nil, err } - return builder.BuildImportTx(s.txBuilderBackend, chainID, to, kc) + return s.b.BuildImportTx(chainID, to, kc) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1668,6 +1653,5 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - s.txBuilderBackend.ResetAddresses(kc.Addresses()) - return builder.BuildExportTx(s.txBuilderBackend, chainID, to, assetID, uint64(args.Amount), kc, changeAddr) + return s.b.BuildExportTx(chainID, to, assetID, uint64(args.Amount), kc, changeAddr) } diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go index ee1a350d5f8..da892857fed 100644 --- a/vms/avm/service_backend.go +++ b/vms/avm/service_backend.go @@ -17,30 +17,18 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" - - walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) var _ builder.TxBuilderBackend = (*serviceBackend)(nil) func newServiceBackend( - feeAssetID ids.ID, ctx *snow.Context, cfg *config.Config, state state.State, sharedMemory atomic.SharedMemory, codec codec.Manager, ) *serviceBackend { - backendCtx := &walletbuilder.Context{ - NetworkID: ctx.NetworkID, - BlockchainID: ctx.XChainID, - AVAXAssetID: feeAssetID, - BaseTxFee: cfg.TxFee, - CreateAssetTxFee: cfg.CreateAssetTxFee, - } - return &serviceBackend{ - ctx: backendCtx, xchainID: ctx.XChainID, cfg: cfg, state: state, @@ -50,7 +38,6 @@ func newServiceBackend( } type serviceBackend struct { - ctx *walletbuilder.Context xchainID ids.ID cfg *config.Config addrs set.Set[ids.ShortID] @@ -59,10 +46,6 @@ type serviceBackend struct { codec codec.Manager } -func (b *serviceBackend) Context() *walletbuilder.Context { - return b.ctx -} - func (b *serviceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { b.addrs = addrs } diff --git a/vms/avm/txs/builder/context.go b/vms/avm/txs/builder/context.go new file mode 100644 index 00000000000..9408fd04efa --- /dev/null +++ b/vms/avm/txs/builder/context.go @@ -0,0 +1,25 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package builder + +import ( + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/vms/avm/config" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" +) + +func newContext( + ctx *snow.Context, + cfg *config.Config, + feeAssetID ids.ID, +) *builder.Context { + return &builder.Context{ + NetworkID: ctx.NetworkID, + BlockchainID: ctx.XChainID, + AVAXAssetID: feeAssetID, + BaseTxFee: cfg.TxFee, + CreateAssetTxFee: cfg.CreateAssetTxFee, + } +} diff --git a/vms/avm/txs/builder/tx_builders.go b/vms/avm/txs/builder/tx_builders.go index e432f61d2ae..b1c994ed5bf 100644 --- a/vms/avm/txs/builder/tx_builders.go +++ b/vms/avm/txs/builder/tx_builders.go @@ -8,7 +8,9 @@ import ( "fmt" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -22,19 +24,34 @@ type TxBuilderBackend interface { builder.Backend signer.Backend - Context() *builder.Context ResetAddresses(addrs set.Set[ids.ShortID]) } -func BuildCreateAssetTx( +type Builder struct { + backend TxBuilderBackend + ctx *builder.Context +} + +func NewBuilder( + ctx *snow.Context, + cfg *config.Config, + feeAssetID ids.ID, backend TxBuilderBackend, +) *Builder { + return &Builder{ + backend: backend, + ctx: newContext(ctx, cfg, feeAssetID), + } +} + +func (b *Builder) BuildCreateAssetTx( name, symbol string, denomination byte, initialStates map[uint32][]verify.State, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewCreateAssetTx( name, @@ -55,14 +72,13 @@ func BuildCreateAssetTx( return tx, changeAddr, nil } -func BuildBaseTx( - backend TxBuilderBackend, +func (b *Builder) BuildBaseTx( outs []*avax.TransferableOutput, memo []byte, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewBaseTx( outs, @@ -80,15 +96,14 @@ func BuildBaseTx( return tx, changeAddr, nil } -func MintNFT( - backend TxBuilderBackend, +func (b *Builder) MintNFT( assetID ids.ID, payload []byte, owners []*secp256k1fx.OutputOwners, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewOperationTxMintNFT( assetID, @@ -103,13 +118,12 @@ func MintNFT( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func MintFTs( - backend TxBuilderBackend, +func (b *Builder) MintFTs( outputs map[ids.ID]*secp256k1fx.TransferOutput, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewOperationTxMintFT( outputs, @@ -122,13 +136,12 @@ func MintFTs( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func BuildOperation( - backend TxBuilderBackend, +func (b *Builder) BuildOperation( ops []*txs.Operation, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewOperationTx( ops, @@ -141,13 +154,12 @@ func BuildOperation( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func BuildImportTx( - backend TxBuilderBackend, +func (b *Builder) BuildImportTx( sourceChain ids.ID, to ids.ShortID, kc *secp256k1fx.Keychain, ) (*txs.Tx, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) outOwner := &secp256k1fx.OutputOwners{ Locktime: 0, @@ -166,8 +178,7 @@ func BuildImportTx( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func BuildExportTx( - backend TxBuilderBackend, +func (b *Builder) BuildExportTx( destinationChain ids.ID, to ids.ShortID, exportedAssetID ids.ID, @@ -175,7 +186,7 @@ func BuildExportTx( kc *secp256k1fx.Keychain, changeAddr ids.ShortID, ) (*txs.Tx, ids.ShortID, error) { - xBuilder, xSigner := builders(backend, kc) + xBuilder, xSigner := b.builders(kc) outputs := []*avax.TransferableOutput{{ Asset: avax.Asset{ID: exportedAssetID}, @@ -205,14 +216,13 @@ func BuildExportTx( return tx, changeAddr, nil } -func builders(backend TxBuilderBackend, kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { +func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { var ( addrs = kc.Addresses() - builder = builder.New(addrs, backend.Context(), backend) - signer = signer.New(kc, backend) + builder = builder.New(addrs, b.ctx, b.backend) + signer = signer.New(kc, b.backend) ) - - backend.ResetAddresses(addrs) + b.backend.ResetAddresses(addrs) return builder, signer } diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 5b74efe88dc..1c58cc36740 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -36,6 +36,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/network" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" "github.com/ava-labs/avalanchego/vms/avm/utxo" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -243,7 +244,16 @@ func (vm *VM) Initialize( return err } - vm.walletService.walletServiceBackend = NewWalletServiceBackend(vm) + walletServiceBackend := NewWalletServiceBackend(vm) + vm.walletService = WalletService{ + walletServiceBackend: walletServiceBackend, + b: builder.NewBuilder( + vm.ctx, + &vm.Config, + vm.feeAssetID, + walletServiceBackend, + ), + } // use no op impl when disabled in config if avmConfig.IndexTransactions { @@ -337,8 +347,13 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { rpcServer.RegisterAfterFunc(vm.metrics.AfterRequest) // name this service "avm" if err := rpcServer.RegisterService(&Service{ - vm: vm, - txBuilderBackend: newServiceBackend(vm.feeAssetID, vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), + vm: vm, + b: builder.NewBuilder( + vm.ctx, + &vm.Config, + vm.feeAssetID, + newServiceBackend(vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), + ), }, "avm"); err != nil { return nil, err } diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index 8bcf9cde3d5..fdea5debed7 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -26,6 +26,7 @@ var errMissingUTXO = errors.New("missing utxo") type WalletService struct { *walletServiceBackend + b *builder.Builder } func (w *WalletService) decided(txID ids.ID) { @@ -223,8 +224,7 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re }) } - w.walletServiceBackend.ResetAddresses(kc.Addresses()) - tx, _, err := builder.BuildBaseTx(w.walletServiceBackend, outs, memoBytes, kc, changeAddr) + tx, _, err := w.b.BuildBaseTx(outs, memoBytes, kc, changeAddr) if err != nil { return err } diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go index 110458cf6e2..5a0088cdc13 100644 --- a/vms/avm/wallet_service_backend.go +++ b/vms/avm/wallet_service_backend.go @@ -15,23 +15,12 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" - - walletbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) var _ builder.TxBuilderBackend = (*walletServiceBackend)(nil) func NewWalletServiceBackend(vm *VM) *walletServiceBackend { - backendCtx := &walletbuilder.Context{ - NetworkID: vm.ctx.NetworkID, - BlockchainID: vm.ctx.XChainID, - AVAXAssetID: vm.feeAssetID, - BaseTxFee: vm.Config.TxFee, - CreateAssetTxFee: vm.Config.CreateAssetTxFee, - } - return &walletServiceBackend{ - ctx: backendCtx, vm: vm, pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), utxos: make([]*avax.UTXO, 0), @@ -39,7 +28,6 @@ func NewWalletServiceBackend(vm *VM) *walletServiceBackend { } type walletServiceBackend struct { - ctx *walletbuilder.Context vm *VM pendingTxs *linked.Hashmap[ids.ID, *txs.Tx] utxos []*avax.UTXO @@ -47,10 +35,6 @@ type walletServiceBackend struct { addrs set.Set[ids.ShortID] } -func (b *walletServiceBackend) Context() *walletbuilder.Context { - return b.ctx -} - func (b *walletServiceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { b.addrs = addrs } From 2894f7cc35032f384b44122a53836cad7ae4769d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 9 May 2024 10:18:26 +0200 Subject: [PATCH 29/53] nit --- vms/avm/txs/builder/tx_builders.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/vms/avm/txs/builder/tx_builders.go b/vms/avm/txs/builder/tx_builders.go index b1c994ed5bf..58f93305646 100644 --- a/vms/avm/txs/builder/tx_builders.go +++ b/vms/avm/txs/builder/tx_builders.go @@ -217,13 +217,11 @@ func (b *Builder) BuildExportTx( } func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { - var ( - addrs = kc.Addresses() - builder = builder.New(addrs, b.ctx, b.backend) - signer = signer.New(kc, b.backend) - ) + addrs := kc.Addresses() b.backend.ResetAddresses(addrs) + builder := builder.New(addrs, b.ctx, b.backend) + signer := signer.New(kc, b.backend) return builder, signer } From 0758ec0332d94f3b9d8f0911c63006a55eaa76bf Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 9 May 2024 10:35:51 +0200 Subject: [PATCH 30/53] Some more cleanup Signed-off-by: Alberto Benegiamo --- vms/avm/environment_test.go | 6 +++--- vms/avm/service.go | 24 ++++++++++++--------- vms/avm/service_backend.go | 4 ---- vms/avm/txs/builder/tx_builders.go | 34 +++++++++++++++--------------- vms/avm/vm.go | 6 +++--- vms/avm/wallet_service.go | 4 ++-- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 59d27b40636..0117741377e 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -205,7 +205,7 @@ func setup(tb testing.TB, c *envConfig) *environment { issuer := make(chan common.Message, 1) var ( - serviceBackend = newServiceBackend(vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) + serviceBackend = newServiceBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) walletBackend = NewWalletServiceBackend(vm) ) @@ -217,7 +217,7 @@ func setup(tb testing.TB, c *envConfig) *environment { vm: vm, service: &Service{ vm: vm, - b: builder.NewBuilder( + builder: builder.NewBuilder( vm.ctx, &vm.Config, vm.feeAssetID, @@ -226,7 +226,7 @@ func setup(tb testing.TB, c *envConfig) *environment { }, walletService: &WalletService{ walletServiceBackend: walletBackend, - b: builder.NewBuilder( + builder: builder.NewBuilder( vm.ctx, &vm.Config, vm.feeAssetID, diff --git a/vms/avm/service.go b/vms/avm/service.go index 214c12cdf3c..bda95424053 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -62,8 +62,8 @@ type FormattedAssetID struct { // Service defines the base service for the asset vm type Service struct { - vm *VM - b *builder.Builder + vm *VM + builder *builder.Builder } // GetBlock returns the requested block. @@ -793,7 +793,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI initialStateOuts = append(initialStateOuts, minter) } - return s.b.BuildCreateAssetTx( + tx, err := s.builder.CreateAssetTx( args.Name, args.Symbol, args.Denomination, @@ -801,6 +801,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI kc, changeAddr, ) + return tx, changeAddr, err } // CreateFixedCapAsset returns ID of the newly created asset @@ -912,7 +913,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh initialStateOuts = append(initialStateOuts, minter) } - return s.b.BuildCreateAssetTx( + tx, err := s.builder.CreateAssetTx( args.Name, args.Symbol, 0, // NFTs are non-fungible @@ -920,6 +921,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh kc, changeAddr, ) + return tx, changeAddr, err } // CreateAddress creates an address for the user [args.Username] @@ -1228,7 +1230,8 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - return s.b.BuildBaseTx(outs, memoBytes, kc, changeAddr) + tx, err := s.builder.BaseTx(outs, memoBytes, kc, changeAddr) + return tx, changeAddr, err } // MintArgs are arguments for passing into Mint requests @@ -1317,7 +1320,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { }, } - tx, err := s.b.MintFTs(outputs, feeKc, changeAddr) + tx, err := s.builder.MintFTs(outputs, feeKc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1403,7 +1406,7 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, err := s.b.BuildOperation(ops, kc, changeAddr) + tx, err := s.builder.Operation(ops, kc, changeAddr) if err != nil { return nil, ids.ShortEmpty, err } @@ -1489,7 +1492,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, err := s.b.MintNFT( + tx, err := s.builder.MintNFT( assetID, payloadBytes, []*secp256k1fx.OutputOwners{{ @@ -1560,7 +1563,7 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { return nil, err } - return s.b.BuildImportTx(chainID, to, kc) + return s.builder.ImportTx(chainID, to, kc) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1653,5 +1656,6 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - return s.b.BuildExportTx(chainID, to, assetID, uint64(args.Amount), kc, changeAddr) + tx, err := s.builder.ExportTx(chainID, to, assetID, uint64(args.Amount), kc, changeAddr) + return tx, changeAddr, err } diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go index da892857fed..51ade946efc 100644 --- a/vms/avm/service_backend.go +++ b/vms/avm/service_backend.go @@ -13,7 +13,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -23,14 +22,12 @@ var _ builder.TxBuilderBackend = (*serviceBackend)(nil) func newServiceBackend( ctx *snow.Context, - cfg *config.Config, state state.State, sharedMemory atomic.SharedMemory, codec codec.Manager, ) *serviceBackend { return &serviceBackend{ xchainID: ctx.XChainID, - cfg: cfg, state: state, sharedMemory: sharedMemory, codec: codec, @@ -39,7 +36,6 @@ func newServiceBackend( type serviceBackend struct { xchainID ids.ID - cfg *config.Config addrs set.Set[ids.ShortID] state state.State sharedMemory atomic.SharedMemory diff --git a/vms/avm/txs/builder/tx_builders.go b/vms/avm/txs/builder/tx_builders.go index 58f93305646..94e0fdc169c 100644 --- a/vms/avm/txs/builder/tx_builders.go +++ b/vms/avm/txs/builder/tx_builders.go @@ -44,13 +44,13 @@ func NewBuilder( } } -func (b *Builder) BuildCreateAssetTx( +func (b *Builder) CreateAssetTx( name, symbol string, denomination byte, initialStates map[uint32][]verify.State, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { +) (*txs.Tx, error) { xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewCreateAssetTx( @@ -61,23 +61,23 @@ func (b *Builder) BuildCreateAssetTx( options(changeAddr, nil /*memo*/)..., ) if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) + return nil, fmt.Errorf("failed building base tx: %w", err) } tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { - return nil, ids.ShortEmpty, err + return nil, err } - return tx, changeAddr, nil + return tx, nil } -func (b *Builder) BuildBaseTx( +func (b *Builder) BaseTx( outs []*avax.TransferableOutput, memo []byte, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { +) (*txs.Tx, error) { xBuilder, xSigner := b.builders(kc) utx, err := xBuilder.NewBaseTx( @@ -85,15 +85,15 @@ func (b *Builder) BuildBaseTx( options(changeAddr, memo)..., ) if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("failed building base tx: %w", err) + return nil, fmt.Errorf("failed building base tx: %w", err) } tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { - return nil, ids.ShortEmpty, err + return nil, err } - return tx, changeAddr, nil + return tx, nil } func (b *Builder) MintNFT( @@ -136,7 +136,7 @@ func (b *Builder) MintFTs( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func (b *Builder) BuildOperation( +func (b *Builder) Operation( ops []*txs.Operation, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, @@ -154,7 +154,7 @@ func (b *Builder) BuildOperation( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func (b *Builder) BuildImportTx( +func (b *Builder) ImportTx( sourceChain ids.ID, to ids.ShortID, kc *secp256k1fx.Keychain, @@ -178,14 +178,14 @@ func (b *Builder) BuildImportTx( return signer.SignUnsigned(context.Background(), xSigner, utx) } -func (b *Builder) BuildExportTx( +func (b *Builder) ExportTx( destinationChain ids.ID, to ids.ShortID, exportedAssetID ids.ID, exportedAmt uint64, kc *secp256k1fx.Keychain, changeAddr ids.ShortID, -) (*txs.Tx, ids.ShortID, error) { +) (*txs.Tx, error) { xBuilder, xSigner := b.builders(kc) outputs := []*avax.TransferableOutput{{ @@ -206,14 +206,14 @@ func (b *Builder) BuildExportTx( options(changeAddr, nil /*memo*/)..., ) if err != nil { - return nil, ids.ShortEmpty, fmt.Errorf("failed building export tx: %w", err) + return nil, fmt.Errorf("failed building export tx: %w", err) } tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) if err != nil { - return nil, ids.ShortEmpty, err + return nil, err } - return tx, changeAddr, nil + return tx, nil } func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 1c58cc36740..3692b0a95a9 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -247,7 +247,7 @@ func (vm *VM) Initialize( walletServiceBackend := NewWalletServiceBackend(vm) vm.walletService = WalletService{ walletServiceBackend: walletServiceBackend, - b: builder.NewBuilder( + builder: builder.NewBuilder( vm.ctx, &vm.Config, vm.feeAssetID, @@ -348,11 +348,11 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { // name this service "avm" if err := rpcServer.RegisterService(&Service{ vm: vm, - b: builder.NewBuilder( + builder: builder.NewBuilder( vm.ctx, &vm.Config, vm.feeAssetID, - newServiceBackend(vm.ctx, &vm.Config, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), + newServiceBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), ), }, "avm"); err != nil { return nil, err diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index fdea5debed7..5548a200615 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -26,7 +26,7 @@ var errMissingUTXO = errors.New("missing utxo") type WalletService struct { *walletServiceBackend - b *builder.Builder + builder *builder.Builder } func (w *WalletService) decided(txID ids.ID) { @@ -224,7 +224,7 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re }) } - tx, _, err := w.b.BuildBaseTx(outs, memoBytes, kc, changeAddr) + tx, err := w.builder.BaseTx(outs, memoBytes, kc, changeAddr) if err != nil { return err } From 1fc71051786b5f1484891941efae50f0d7cf162d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 9 May 2024 10:54:30 +0200 Subject: [PATCH 31/53] simplified AVM backend interface --- vms/avm/environment_test.go | 4 +-- vms/avm/service_backend.go | 18 ++++------- vms/avm/txs/builder/backends.go | 30 +++++++++++++++++++ .../builder/{tx_builders.go => builder.go} | 28 ++++++++--------- vms/avm/vm.go | 4 +-- vms/avm/wallet_service_backend.go | 18 ++++------- 6 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 vms/avm/txs/builder/backends.go rename vms/avm/txs/builder/{tx_builders.go => builder.go} (92%) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 0117741377e..b5358d4cc1e 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -217,7 +217,7 @@ func setup(tb testing.TB, c *envConfig) *environment { vm: vm, service: &Service{ vm: vm, - builder: builder.NewBuilder( + builder: builder.New( vm.ctx, &vm.Config, vm.feeAssetID, @@ -226,7 +226,7 @@ func setup(tb testing.TB, c *envConfig) *environment { }, walletService: &WalletService{ walletServiceBackend: walletBackend, - builder: builder.NewBuilder( + builder: builder.New( vm.ctx, &vm.Config, vm.feeAssetID, diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go index 51ade946efc..a422b4dc827 100644 --- a/vms/avm/service_backend.go +++ b/vms/avm/service_backend.go @@ -4,7 +4,6 @@ package avm import ( - "context" "fmt" "github.com/ava-labs/avalanchego/chains/atomic" @@ -18,7 +17,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" ) -var _ builder.TxBuilderBackend = (*serviceBackend)(nil) +var _ builder.AVMBuilderBackend = (*serviceBackend)(nil) func newServiceBackend( ctx *snow.Context, @@ -36,26 +35,21 @@ func newServiceBackend( type serviceBackend struct { xchainID ids.ID - addrs set.Set[ids.ShortID] state state.State sharedMemory atomic.SharedMemory codec codec.Manager } -func (b *serviceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { - b.addrs = addrs -} - -func (b *serviceBackend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { +func (b *serviceBackend) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { if sourceChainID == b.xchainID { - return avax.GetAllUTXOs(b.state, b.addrs) + return avax.GetAllUTXOs(b.state, addrs) } atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( b.sharedMemory, b.codec, sourceChainID, - b.addrs, + addrs, ids.ShortEmpty, ids.Empty, int(maxPageSize), @@ -63,7 +57,7 @@ func (b *serviceBackend) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax return atomicUTXOs, err } -func (b *serviceBackend) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { +func (b *serviceBackend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { if chainID == b.xchainID { return b.state.GetUTXO(utxoID) } @@ -72,7 +66,7 @@ func (b *serviceBackend) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*av b.sharedMemory, b.codec, chainID, - b.addrs, + addrs, ids.ShortEmpty, ids.Empty, int(maxPageSize), diff --git a/vms/avm/txs/builder/backends.go b/vms/avm/txs/builder/backends.go new file mode 100644 index 00000000000..ebd5c59f954 --- /dev/null +++ b/vms/avm/txs/builder/backends.go @@ -0,0 +1,30 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package builder + +import ( + "context" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" +) + +type AVMBuilderBackend interface { + UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) + GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type walletBackendAdapter struct { + b AVMBuilderBackend + addrs set.Set[ids.ShortID] +} + +func (wa *walletBackendAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { + return wa.b.UTXOs(wa.addrs, sourceChainID) +} + +func (wa *walletBackendAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { + return wa.b.GetUTXO(wa.addrs, chainID, utxoID) +} diff --git a/vms/avm/txs/builder/tx_builders.go b/vms/avm/txs/builder/builder.go similarity index 92% rename from vms/avm/txs/builder/tx_builders.go rename to vms/avm/txs/builder/builder.go index 94e0fdc169c..f936c855f7f 100644 --- a/vms/avm/txs/builder/tx_builders.go +++ b/vms/avm/txs/builder/builder.go @@ -9,7 +9,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -20,23 +19,16 @@ import ( "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" ) -type TxBuilderBackend interface { - builder.Backend - signer.Backend - - ResetAddresses(addrs set.Set[ids.ShortID]) -} - type Builder struct { - backend TxBuilderBackend + backend AVMBuilderBackend ctx *builder.Context } -func NewBuilder( +func New( ctx *snow.Context, cfg *config.Config, feeAssetID ids.ID, - backend TxBuilderBackend, + backend AVMBuilderBackend, ) *Builder { return &Builder{ backend: backend, @@ -217,11 +209,15 @@ func (b *Builder) ExportTx( } func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { - addrs := kc.Addresses() - b.backend.ResetAddresses(addrs) - - builder := builder.New(addrs, b.ctx, b.backend) - signer := signer.New(kc, b.backend) + var ( + addrs = kc.Addresses() + wa = &walletBackendAdapter{ + b: b.backend, + addrs: addrs, + } + builder = builder.New(addrs, b.ctx, wa) + signer = signer.New(kc, wa) + ) return builder, signer } diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 3692b0a95a9..5876a2ccc6b 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -247,7 +247,7 @@ func (vm *VM) Initialize( walletServiceBackend := NewWalletServiceBackend(vm) vm.walletService = WalletService{ walletServiceBackend: walletServiceBackend, - builder: builder.NewBuilder( + builder: builder.New( vm.ctx, &vm.Config, vm.feeAssetID, @@ -348,7 +348,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { // name this service "avm" if err := rpcServer.RegisterService(&Service{ vm: vm, - builder: builder.NewBuilder( + builder: builder.New( vm.ctx, &vm.Config, vm.feeAssetID, diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go index 5a0088cdc13..954b385dd56 100644 --- a/vms/avm/wallet_service_backend.go +++ b/vms/avm/wallet_service_backend.go @@ -4,8 +4,6 @@ package avm import ( - "context" - "golang.org/x/exp/maps" "github.com/ava-labs/avalanchego/database" @@ -17,7 +15,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" ) -var _ builder.TxBuilderBackend = (*walletServiceBackend)(nil) +var _ builder.AVMBuilderBackend = (*walletServiceBackend)(nil) func NewWalletServiceBackend(vm *VM) *walletServiceBackend { return &walletServiceBackend{ @@ -31,16 +29,10 @@ type walletServiceBackend struct { vm *VM pendingTxs *linked.Hashmap[ids.ID, *txs.Tx] utxos []*avax.UTXO - - addrs set.Set[ids.ShortID] -} - -func (b *walletServiceBackend) ResetAddresses(addrs set.Set[ids.ShortID]) { - b.addrs = addrs } -func (b *walletServiceBackend) UTXOs(_ context.Context, _ ids.ID) ([]*avax.UTXO, error) { - res, err := avax.GetAllUTXOs(b.vm.state, b.addrs) +func (b *walletServiceBackend) UTXOs(addrs set.Set[ids.ShortID], _ ids.ID) ([]*avax.UTXO, error) { + res, err := avax.GetAllUTXOs(b.vm.state, addrs) if err != nil { return nil, err } @@ -48,8 +40,8 @@ func (b *walletServiceBackend) UTXOs(_ context.Context, _ ids.ID) ([]*avax.UTXO, return res, nil } -func (b *walletServiceBackend) GetUTXO(_ context.Context, _, utxoID ids.ID) (*avax.UTXO, error) { - allUTXOs, err := avax.GetAllUTXOs(b.vm.state, b.addrs) +func (b *walletServiceBackend) GetUTXO(addrs set.Set[ids.ShortID], _, utxoID ids.ID) (*avax.UTXO, error) { + allUTXOs, err := avax.GetAllUTXOs(b.vm.state, addrs) if err != nil { return nil, err } From ecfbd6a3849a5128c1274b330f56a73aac2e9f60 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 14 May 2024 14:28:39 +0200 Subject: [PATCH 32/53] nit --- vms/avm/txs/builder/backends.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vms/avm/txs/builder/backends.go b/vms/avm/txs/builder/backends.go index ebd5c59f954..6e54491e767 100644 --- a/vms/avm/txs/builder/backends.go +++ b/vms/avm/txs/builder/backends.go @@ -9,8 +9,11 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" ) +var _ builder.Backend = (*walletBackendAdapter)(nil) + type AVMBuilderBackend interface { UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) From 06628d60518b8847831f07f7dd10d9f6fa15ae2a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 13:21:26 -0400 Subject: [PATCH 33/53] wip: reverted prod code changes --- vms/avm/service.go | 490 ++++++++++++++++++++++++++---- vms/avm/service_backend.go | 83 ----- vms/avm/utxo/spender.go | 320 ++++++++++++++++++- vms/avm/vm.go | 24 +- vms/avm/wallet_service.go | 86 +++++- vms/avm/wallet_service_backend.go | 86 ------ 6 files changed, 827 insertions(+), 262 deletions(-) delete mode 100644 vms/avm/service_backend.go delete mode 100644 vms/avm/wallet_service_backend.go diff --git a/vms/avm/service.go b/vms/avm/service.go index bda95424053..bc6dadd8705 100644 --- a/vms/avm/service.go +++ b/vms/avm/service.go @@ -22,7 +22,6 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/keystore" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -61,10 +60,7 @@ type FormattedAssetID struct { } // Service defines the base service for the asset vm -type Service struct { - vm *VM - builder *builder.Builder -} +type Service struct{ vm *VM } // GetBlock returns the requested block. func (s *Service) GetBlock(_ *http.Request, args *api.GetBlockArgs, reply *api.GetBlockResponse) error { @@ -745,7 +741,7 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -759,17 +755,42 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI return nil, ids.ShortEmpty, err } - var ( - fxIndex = uint32(0) // TODO: Should lookup secp256k1fx FxID - initialStateOuts = make([]verify.State, 0, len(args.InitialHolders)+len(args.MinterSets)) + amountsSpent, ins, keys, err := s.vm.Spend( + utxos, + kc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.CreateAssetTxFee, + }, ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + outs := []*avax.TransferableOutput{} + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.CreateAssetTxFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: s.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - s.vm.CreateAssetTxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + initialState := &txs.InitialState{ + FxIndex: 0, // TODO: Should lookup secp256k1fx FxID + Outs: make([]verify.State, 0, len(args.InitialHolders)+len(args.MinterSets)), + } for _, holder := range args.InitialHolders { addr, err := avax.ParseServiceAddress(s.vm, holder.Address) if err != nil { return nil, ids.ShortEmpty, err } - initialStateOuts = append(initialStateOuts, &secp256k1fx.TransferOutput{ + initialState.Outs = append(initialState.Outs, &secp256k1fx.TransferOutput{ Amt: uint64(holder.Amount), OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -790,18 +811,25 @@ func (s *Service) buildCreateAssetTx(args *CreateAssetArgs) (*txs.Tx, ids.ShortI } minter.Addrs = minterAddrsSet.List() utils.Sort(minter.Addrs) - initialStateOuts = append(initialStateOuts, minter) + initialState.Outs = append(initialState.Outs, minter) } - tx, err := s.builder.CreateAssetTx( - args.Name, - args.Symbol, - args.Denomination, - map[uint32][]verify.State{fxIndex: initialStateOuts}, - kc, - changeAddr, - ) - return tx, changeAddr, err + codec := s.vm.parser.Codec() + initialState.Sort(codec) + + tx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + Name: args.Name, + Symbol: args.Symbol, + Denomination: args.Denomination, + States: []*txs.InitialState{initialState}, + }} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } // CreateFixedCapAsset returns ID of the newly created asset @@ -878,7 +906,7 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -892,11 +920,36 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh return nil, ids.ShortEmpty, err } - var ( - fxIndex = uint32(1) // TODO: Should lookup nftfx FxID - initialStateOuts = make([]verify.State, 0, len(args.MinterSets)) + amountsSpent, ins, keys, err := s.vm.Spend( + utxos, + kc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.CreateAssetTxFee, + }, ) + if err != nil { + return nil, ids.ShortEmpty, err + } + outs := []*avax.TransferableOutput{} + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.CreateAssetTxFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: s.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - s.vm.CreateAssetTxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + + initialState := &txs.InitialState{ + FxIndex: 1, // TODO: Should lookup nftfx FxID + Outs: make([]verify.State, 0, len(args.MinterSets)), + } for i, owner := range args.MinterSets { minter := &nftfx.MintOutput{ GroupID: uint32(i), @@ -910,18 +963,25 @@ func (s *Service) buildCreateNFTAsset(args *CreateNFTAssetArgs) (*txs.Tx, ids.Sh } minter.Addrs = minterAddrsSet.List() utils.Sort(minter.Addrs) - initialStateOuts = append(initialStateOuts, minter) + initialState.Outs = append(initialState.Outs, minter) } - tx, err := s.builder.CreateAssetTx( - args.Name, - args.Symbol, - 0, // NFTs are non-fungible - map[uint32][]verify.State{fxIndex: initialStateOuts}, - kc, - changeAddr, - ) - return tx, changeAddr, err + codec := s.vm.parser.Codec() + initialState.Sort(codec) + + tx := &txs.Tx{Unsigned: &txs.CreateAssetTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + Name: args.Name, + Symbol: args.Symbol, + Denomination: 0, // NFTs are non-fungible + States: []*txs.InitialState{initialState}, + }} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } // CreateAddress creates an address for the user [args.Username] @@ -1170,7 +1230,7 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI defer s.vm.ctx.Lock.Unlock() // Load user's UTXOs/keys - _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1230,8 +1290,56 @@ func (s *Service) buildSendMultiple(args *SendMultipleArgs) (*txs.Tx, ids.ShortI }) } - tx, err := s.builder.BaseTx(outs, memoBytes, kc, changeAddr) - return tx, changeAddr, err + amountsWithFee := make(map[ids.ID]uint64, len(amounts)+1) + for assetID, amount := range amounts { + amountsWithFee[assetID] = amount + } + + amountWithFee, err := safemath.Add64(amounts[s.vm.feeAssetID], s.vm.TxFee) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) + } + amountsWithFee[s.vm.feeAssetID] = amountWithFee + + amountsSpent, ins, keys, err := s.vm.Spend( + utxos, + kc, + amountsWithFee, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + // Add the required change outputs + for assetID, amountWithFee := range amountsWithFee { + amountSpent := amountsSpent[assetID] + + if amountSpent > amountWithFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: assetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - amountWithFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + } + + codec := s.vm.parser.Codec() + avax.SortTransferableOutputs(outs, codec) + + tx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + Memo: memoBytes, + }}} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } // MintArgs are arguments for passing into Mint requests @@ -1296,7 +1404,7 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - _, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + feeUTXOs, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1310,21 +1418,61 @@ func (s *Service) buildMint(args *MintArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - outputs := map[ids.ID]*secp256k1fx.TransferOutput{ - assetID: { - Amt: uint64(args.Amount), - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{to}, - }, + amountsSpent, ins, keys, err := s.vm.Spend( + feeUTXOs, + feeKc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.TxFee, }, + ) + if err != nil { + return nil, ids.ShortEmpty, err } - tx, err := s.builder.MintFTs(outputs, feeKc, changeAddr) + outs := []*avax.TransferableOutput{} + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: s.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - s.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + + // Get all UTXOs/keys for the user + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, nil + + ops, opKeys, err := s.vm.Mint( + utxos, + kc, + map[ids.ID]uint64{ + assetID: uint64(args.Amount), + }, + to, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + keys = append(keys, opKeys...) + + tx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + Ops: ops, + }} + return tx, changeAddr, tx.SignSECP256K1Fx(s.vm.parser.Codec(), keys) } // SendNFTArgs are arguments for passing into SendNFT requests @@ -1395,7 +1543,33 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - ops, _, err := s.vm.SpendNFT( + amountsSpent, ins, secpKeys, err := s.vm.Spend( + utxos, + kc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.TxFee, + }, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + outs := []*avax.TransferableOutput{} + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: s.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - s.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + + ops, nftKeys, err := s.vm.SpendNFT( utxos, kc, assetID, @@ -1406,12 +1580,21 @@ func (s *Service) buildSendNFT(args *SendNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } - tx, err := s.builder.Operation(ops, kc, changeAddr) - if err != nil { + tx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + Ops: ops, + }} + + codec := s.vm.parser.Codec() + if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil { return nil, ids.ShortEmpty, err } - - return tx, changeAddr, nil + return tx, changeAddr, tx.SignNFTFx(codec, nftKeys) } // MintNFTArgs are arguments for passing into MintNFT requests @@ -1472,7 +1655,7 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - _, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + feeUTXOs, feeKc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1486,26 +1669,64 @@ func (s *Service) buildMintNFT(args *MintNFTArgs) (*txs.Tx, ids.ShortID, error) return nil, ids.ShortEmpty, err } + amountsSpent, ins, secpKeys, err := s.vm.Spend( + feeUTXOs, + feeKc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.TxFee, + }, + ) + if err != nil { + return nil, ids.ShortEmpty, err + } + + outs := []*avax.TransferableOutput{} + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent > s.vm.TxFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: s.vm.feeAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - s.vm.TxFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + // Get all UTXOs/keys - _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, ids.ShortEmpty, err } - tx, err := s.builder.MintNFT( + ops, nftKeys, err := s.vm.MintNFT( + utxos, + kc, assetID, payloadBytes, - []*secp256k1fx.OutputOwners{{ - Threshold: 1, - Addrs: []ids.ShortID{to}, - }}, - kc, - changeAddr, + to, ) if err != nil { return nil, ids.ShortEmpty, err } - return tx, changeAddr, nil + + tx := &txs.Tx{Unsigned: &txs.OperationTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + Ops: ops, + }} + + codec := s.vm.parser.Codec() + if err := tx.SignSECP256K1Fx(codec, secpKeys); err != nil { + return nil, ids.ShortEmpty, err + } + return tx, changeAddr, tx.SignNFTFx(codec, nftKeys) } // ImportArgs are arguments for passing into Import requests @@ -1558,12 +1779,88 @@ func (s *Service) buildImport(args *ImportArgs) (*txs.Tx, error) { s.vm.ctx.Lock.Lock() defer s.vm.ctx.Lock.Unlock() - _, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, nil) if err != nil { return nil, err } - return s.builder.ImportTx(chainID, to, kc) + atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( + s.vm.ctx.SharedMemory, + s.vm.parser.Codec(), + chainID, + kc.Addrs, + ids.ShortEmpty, + ids.Empty, + int(maxPageSize), + ) + if err != nil { + return nil, fmt.Errorf("problem retrieving user's atomic UTXOs: %w", err) + } + + amountsSpent, importInputs, importKeys, err := s.vm.SpendAll(atomicUTXOs, kc) + if err != nil { + return nil, err + } + + ins := []*avax.TransferableInput{} + keys := [][]*secp256k1.PrivateKey{} + + if amountSpent := amountsSpent[s.vm.feeAssetID]; amountSpent < s.vm.TxFee { + var localAmountsSpent map[ids.ID]uint64 + localAmountsSpent, ins, keys, err = s.vm.Spend( + utxos, + kc, + map[ids.ID]uint64{ + s.vm.feeAssetID: s.vm.TxFee - amountSpent, + }, + ) + if err != nil { + return nil, err + } + for asset, amount := range localAmountsSpent { + newAmount, err := safemath.Add64(amountsSpent[asset], amount) + if err != nil { + return nil, fmt.Errorf("problem calculating required spend amount: %w", err) + } + amountsSpent[asset] = newAmount + } + } + + // Because we ensured that we had enough inputs for the fee, we can + // safely just remove it without concern for underflow. + amountsSpent[s.vm.feeAssetID] -= s.vm.TxFee + + keys = append(keys, importKeys...) + + outs := []*avax.TransferableOutput{} + for assetID, amount := range amountsSpent { + if amount > 0 { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: assetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amount, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, + }, + }) + } + } + avax.SortTransferableOutputs(outs, s.vm.parser.Codec()) + + tx := &txs.Tx{Unsigned: &txs.ImportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + SourceChain: chainID, + ImportedIns: importInputs, + }} + return tx, tx.SignSECP256K1Fx(s.vm.parser.Codec(), keys) } // ExportArgs are arguments for passing into ExportAVA requests @@ -1642,7 +1939,7 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { defer s.vm.ctx.Lock.Unlock() // Get the UTXOs/keys for the from addresses - _, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) + utxos, kc, err := s.vm.LoadUser(args.Username, args.Password, fromAddrs) if err != nil { return nil, ids.ShortEmpty, err } @@ -1656,6 +1953,65 @@ func (s *Service) buildExport(args *ExportArgs) (*txs.Tx, ids.ShortID, error) { return nil, ids.ShortEmpty, err } - tx, err := s.builder.ExportTx(chainID, to, assetID, uint64(args.Amount), kc, changeAddr) - return tx, changeAddr, err + amounts := map[ids.ID]uint64{} + if assetID == s.vm.feeAssetID { + amountWithFee, err := safemath.Add64(uint64(args.Amount), s.vm.TxFee) + if err != nil { + return nil, ids.ShortEmpty, fmt.Errorf("problem calculating required spend amount: %w", err) + } + amounts[s.vm.feeAssetID] = amountWithFee + } else { + amounts[s.vm.feeAssetID] = s.vm.TxFee + amounts[assetID] = uint64(args.Amount) + } + + amountsSpent, ins, keys, err := s.vm.Spend(utxos, kc, amounts) + if err != nil { + return nil, ids.ShortEmpty, err + } + + exportOuts := []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: assetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: uint64(args.Amount), + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, + }, + }} + + outs := []*avax.TransferableOutput{} + for assetID, amountSpent := range amountsSpent { + amountToSend := amounts[assetID] + if amountSpent > amountToSend { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: assetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - amountToSend, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + } + + codec := s.vm.parser.Codec() + avax.SortTransferableOutputs(outs, codec) + + tx := &txs.Tx{Unsigned: &txs.ExportTx{ + BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: s.vm.ctx.NetworkID, + BlockchainID: s.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + }}, + DestinationChain: chainID, + ExportedOuts: exportOuts, + }} + return tx, changeAddr, tx.SignSECP256K1Fx(codec, keys) } diff --git a/vms/avm/service_backend.go b/vms/avm/service_backend.go deleted file mode 100644 index a422b4dc827..00000000000 --- a/vms/avm/service_backend.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package avm - -import ( - "fmt" - - "github.com/ava-labs/avalanchego/chains/atomic" - "github.com/ava-labs/avalanchego/codec" - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/avm/state" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" - "github.com/ava-labs/avalanchego/vms/components/avax" -) - -var _ builder.AVMBuilderBackend = (*serviceBackend)(nil) - -func newServiceBackend( - ctx *snow.Context, - state state.State, - sharedMemory atomic.SharedMemory, - codec codec.Manager, -) *serviceBackend { - return &serviceBackend{ - xchainID: ctx.XChainID, - state: state, - sharedMemory: sharedMemory, - codec: codec, - } -} - -type serviceBackend struct { - xchainID ids.ID - state state.State - sharedMemory atomic.SharedMemory - codec codec.Manager -} - -func (b *serviceBackend) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { - if sourceChainID == b.xchainID { - return avax.GetAllUTXOs(b.state, addrs) - } - - atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( - b.sharedMemory, - b.codec, - sourceChainID, - addrs, - ids.ShortEmpty, - ids.Empty, - int(maxPageSize), - ) - return atomicUTXOs, err -} - -func (b *serviceBackend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { - if chainID == b.xchainID { - return b.state.GetUTXO(utxoID) - } - - atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( - b.sharedMemory, - b.codec, - chainID, - addrs, - ids.ShortEmpty, - ids.Empty, - int(maxPageSize), - ) - if err != nil { - return nil, fmt.Errorf("problem retrieving atomic UTXOs: %w", err) - } - for _, utxo := range atomicUTXOs { - if utxo.InputID() == utxoID { - return utxo, nil - } - } - return nil, database.ErrNotFound -} diff --git a/vms/avm/utxo/spender.go b/vms/avm/utxo/spender.go index a4dce2838a6..02ade0d92ea 100644 --- a/vms/avm/utxo/spender.go +++ b/vms/avm/utxo/spender.go @@ -5,10 +5,12 @@ package utxo import ( "errors" + "fmt" "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -16,9 +18,33 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var errInsufficientFunds = errors.New("insufficient funds") +var ( + errSpendOverflow = errors.New("spent amount overflows uint64") + errInsufficientFunds = errors.New("insufficient funds") + errAddressesCantMintAsset = errors.New("provided addresses don't have the authority to mint the provided asset") +) type Spender interface { + // Spend the provided amount while deducting the provided fee. + // Arguments: + // - [utxos] contains assets ID and amount to be spend for each assestID + // - [kc] are the owners of the funds + // - [amounts] is the amount of funds that are available to be spent for each assetID + // Returns: + // - [amountsSpent] the amount of funds that are spent + // - [inputs] the inputs that should be consumed to fund the outputs + // - [signers] the proof of ownership of the funds being moved + Spend( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + amounts map[ids.ID]uint64, + ) ( + map[ids.ID]uint64, // amountsSpent + []*avax.TransferableInput, // inputs + [][]*secp256k1.PrivateKey, // signers + error, + ) + SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, @@ -30,6 +56,39 @@ type Spender interface { [][]*secp256k1.PrivateKey, error, ) + + SpendAll( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + ) ( + map[ids.ID]uint64, + []*avax.TransferableInput, + [][]*secp256k1.PrivateKey, + error, + ) + + Mint( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + amounts map[ids.ID]uint64, + to ids.ShortID, + ) ( + []*txs.Operation, + [][]*secp256k1.PrivateKey, + error, + ) + + MintNFT( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + assetID ids.ID, + payload []byte, + to ids.ShortID, + ) ( + []*txs.Operation, + [][]*secp256k1.PrivateKey, + error, + ) } func NewSpender( @@ -47,6 +106,72 @@ type spender struct { codec codec.Manager } +func (s *spender) Spend( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + amounts map[ids.ID]uint64, +) ( + map[ids.ID]uint64, // amountsSpent + []*avax.TransferableInput, // inputs + [][]*secp256k1.PrivateKey, // signers + error, +) { + amountsSpent := make(map[ids.ID]uint64, len(amounts)) + time := s.clock.Unix() + + ins := []*avax.TransferableInput{} + keys := [][]*secp256k1.PrivateKey{} + for _, utxo := range utxos { + assetID := utxo.AssetID() + amount := amounts[assetID] + amountSpent := amountsSpent[assetID] + + if amountSpent >= amount { + // we already have enough inputs allocated to this asset + continue + } + + inputIntf, signers, err := kc.Spend(utxo.Out, time) + if err != nil { + // this utxo can't be spent with the current keys right now + continue + } + input, ok := inputIntf.(avax.TransferableIn) + if !ok { + // this input doesn't have an amount, so I don't care about it here + continue + } + newAmountSpent, err := math.Add64(amountSpent, input.Amount()) + if err != nil { + // there was an error calculating the consumed amount, just error + return nil, nil, nil, errSpendOverflow + } + amountsSpent[assetID] = newAmountSpent + + // add the new input to the array + ins = append(ins, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: avax.Asset{ID: assetID}, + In: input, + }) + // add the required keys to the array + keys = append(keys, signers) + } + + for asset, amount := range amounts { + if amountsSpent[asset] < amount { + return nil, nil, nil, fmt.Errorf("want to spend %d of asset %s but only have %d", + amount, + asset, + amountsSpent[asset], + ) + } + } + + avax.SortTransferableInputsWithSigners(ins, keys) + return amountsSpent, ins, keys, nil +} + func (s *spender) SpendNFT( utxos []*avax.UTXO, kc *secp256k1fx.Keychain, @@ -120,3 +245,196 @@ func (s *spender) SpendNFT( txs.SortOperationsWithSigners(ops, keys, s.codec) return ops, keys, nil } + +func (s *spender) SpendAll( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, +) ( + map[ids.ID]uint64, + []*avax.TransferableInput, + [][]*secp256k1.PrivateKey, + error, +) { + amountsSpent := make(map[ids.ID]uint64) + time := s.clock.Unix() + + ins := []*avax.TransferableInput{} + keys := [][]*secp256k1.PrivateKey{} + for _, utxo := range utxos { + assetID := utxo.AssetID() + amountSpent := amountsSpent[assetID] + + inputIntf, signers, err := kc.Spend(utxo.Out, time) + if err != nil { + // this utxo can't be spent with the current keys right now + continue + } + input, ok := inputIntf.(avax.TransferableIn) + if !ok { + // this input doesn't have an amount, so I don't care about it here + continue + } + newAmountSpent, err := math.Add64(amountSpent, input.Amount()) + if err != nil { + // there was an error calculating the consumed amount, just error + return nil, nil, nil, errSpendOverflow + } + amountsSpent[assetID] = newAmountSpent + + // add the new input to the array + ins = append(ins, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: avax.Asset{ID: assetID}, + In: input, + }) + // add the required keys to the array + keys = append(keys, signers) + } + + avax.SortTransferableInputsWithSigners(ins, keys) + return amountsSpent, ins, keys, nil +} + +func (s *spender) Mint( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + amounts map[ids.ID]uint64, + to ids.ShortID, +) ( + []*txs.Operation, + [][]*secp256k1.PrivateKey, + error, +) { + time := s.clock.Unix() + + ops := []*txs.Operation{} + keys := [][]*secp256k1.PrivateKey{} + + for _, utxo := range utxos { + // makes sure that the variable isn't overwritten with the next iteration + utxo := utxo + + assetID := utxo.AssetID() + amount := amounts[assetID] + if amount == 0 { + continue + } + + out, ok := utxo.Out.(*secp256k1fx.MintOutput) + if !ok { + continue + } + + inIntf, signers, err := kc.Spend(out, time) + if err != nil { + continue + } + + in, ok := inIntf.(*secp256k1fx.Input) + if !ok { + continue + } + + // add the operation to the array + ops = append(ops, &txs.Operation{ + Asset: utxo.Asset, + UTXOIDs: []*avax.UTXOID{&utxo.UTXOID}, + Op: &secp256k1fx.MintOperation{ + MintInput: *in, + MintOutput: *out, + TransferOutput: secp256k1fx.TransferOutput{ + Amt: amount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{to}, + }, + }, + }, + }) + // add the required keys to the array + keys = append(keys, signers) + + // remove the asset from the required amounts to mint + delete(amounts, assetID) + } + + for _, amount := range amounts { + if amount > 0 { + return nil, nil, errAddressesCantMintAsset + } + } + + txs.SortOperationsWithSigners(ops, keys, s.codec) + return ops, keys, nil +} + +func (s *spender) MintNFT( + utxos []*avax.UTXO, + kc *secp256k1fx.Keychain, + assetID ids.ID, + payload []byte, + to ids.ShortID, +) ( + []*txs.Operation, + [][]*secp256k1.PrivateKey, + error, +) { + time := s.clock.Unix() + + ops := []*txs.Operation{} + keys := [][]*secp256k1.PrivateKey{} + + for _, utxo := range utxos { + // makes sure that the variable isn't overwritten with the next iteration + utxo := utxo + + if len(ops) > 0 { + // we have already been able to create the operation needed + break + } + + if utxo.AssetID() != assetID { + // wrong asset id + continue + } + out, ok := utxo.Out.(*nftfx.MintOutput) + if !ok { + // wrong output type + continue + } + + indices, signers, ok := kc.Match(&out.OutputOwners, time) + if !ok { + // unable to spend the output + continue + } + + // add the operation to the array + ops = append(ops, &txs.Operation{ + Asset: avax.Asset{ID: assetID}, + UTXOIDs: []*avax.UTXOID{ + &utxo.UTXOID, + }, + Op: &nftfx.MintOperation{ + MintInput: secp256k1fx.Input{ + SigIndices: indices, + }, + GroupID: out.GroupID, + Payload: payload, + Outputs: []*secp256k1fx.OutputOwners{{ + Threshold: 1, + Addrs: []ids.ShortID{to}, + }}, + }, + }) + // add the required keys to the array + keys = append(keys, signers) + } + + if len(ops) == 0 { + return nil, nil, errAddressesCantMintAsset + } + + txs.SortOperationsWithSigners(ops, keys, s.codec) + return ops, keys, nil +} diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 7387dde9627..c2dce8d2705 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -27,6 +27,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/json" + "github.com/ava-labs/avalanchego/utils/linked" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/version" @@ -36,7 +37,6 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/network" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/avm/utxo" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/index" @@ -245,16 +245,8 @@ func (vm *VM) Initialize( return err } - walletServiceBackend := NewWalletServiceBackend(vm) - vm.walletService = WalletService{ - walletServiceBackend: walletServiceBackend, - builder: builder.New( - vm.ctx, - &vm.Config, - vm.feeAssetID, - walletServiceBackend, - ), - } + vm.walletService.vm = vm + vm.walletService.pendingTxs = linked.NewHashmap[ids.ID, *txs.Tx]() // use no op impl when disabled in config if avmConfig.IndexTransactions { @@ -347,15 +339,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { rpcServer.RegisterInterceptFunc(vm.metrics.InterceptRequest) rpcServer.RegisterAfterFunc(vm.metrics.AfterRequest) // name this service "avm" - if err := rpcServer.RegisterService(&Service{ - vm: vm, - builder: builder.New( - vm.ctx, - &vm.Config, - vm.feeAssetID, - newServiceBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()), - ), - }, "avm"); err != nil { + if err := rpcServer.RegisterService(&Service{vm: vm}, "avm"); err != nil { return nil, err } diff --git a/vms/avm/wallet_service.go b/vms/avm/wallet_service.go index 5ce736a2aaf..871d81580a5 100644 --- a/vms/avm/wallet_service.go +++ b/vms/avm/wallet_service.go @@ -9,14 +9,15 @@ import ( "net/http" "go.uber.org/zap" + "golang.org/x/exp/maps" "github.com/ava-labs/avalanchego/api" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/formatting" + "github.com/ava-labs/avalanchego/utils/linked" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/vms/txs/mempool" @@ -25,8 +26,8 @@ import ( var errMissingUTXO = errors.New("missing utxo") type WalletService struct { - *walletServiceBackend - builder *builder.Builder + vm *VM + pendingTxs *linked.Hashmap[ids.ID, *txs.Tx] } func (w *WalletService) decided(txID ids.ID) { @@ -97,6 +98,35 @@ func (w *WalletService) issue(tx *txs.Tx) (ids.ID, error) { return txID, nil } +func (w *WalletService) update(utxos []*avax.UTXO) ([]*avax.UTXO, error) { + utxoMap := make(map[ids.ID]*avax.UTXO, len(utxos)) + for _, utxo := range utxos { + utxoMap[utxo.InputID()] = utxo + } + + iter := w.pendingTxs.NewIterator() + + for iter.Next() { + tx := iter.Value() + for _, inputUTXO := range tx.Unsigned.InputUTXOs() { + if inputUTXO.Symbolic() { + continue + } + utxoID := inputUTXO.InputID() + if _, exists := utxoMap[utxoID]; !exists { + return nil, errMissingUTXO + } + delete(utxoMap, utxoID) + } + + for _, utxo := range tx.UTXOs() { + utxoMap[utxo.InputID()] = utxo + } + } + + return maps.Values(utxoMap), nil +} + // IssueTx attempts to issue a transaction into consensus func (w *WalletService) IssueTx(_ *http.Request, args *api.FormattedTx, reply *api.JSONTxID) error { w.vm.ctx.Log.Warn("deprecated API called", @@ -165,7 +195,8 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re return err } - if err = w.vm.walletService.update(utxos); err != nil { + utxos, err = w.update(utxos) + if err != nil { return err } @@ -224,11 +255,56 @@ func (w *WalletService) SendMultiple(_ *http.Request, args *SendMultipleArgs, re }) } - tx, err := w.builder.BaseTx(outs, memoBytes, kc, changeAddr) + amountsWithFee := maps.Clone(amounts) + + amountWithFee, err := math.Add64(amounts[w.vm.feeAssetID], w.vm.TxFee) + if err != nil { + return fmt.Errorf("problem calculating required spend amount: %w", err) + } + amountsWithFee[w.vm.feeAssetID] = amountWithFee + + amountsSpent, ins, keys, err := w.vm.Spend( + utxos, + kc, + amountsWithFee, + ) if err != nil { return err } + // Add the required change outputs + for assetID, amountWithFee := range amountsWithFee { + amountSpent := amountsSpent[assetID] + + if amountSpent > amountWithFee { + outs = append(outs, &avax.TransferableOutput{ + Asset: avax.Asset{ID: assetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: amountSpent - amountWithFee, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }, + }, + }) + } + } + + codec := w.vm.parser.Codec() + avax.SortTransferableOutputs(outs, codec) + + tx := &txs.Tx{Unsigned: &txs.BaseTx{BaseTx: avax.BaseTx{ + NetworkID: w.vm.ctx.NetworkID, + BlockchainID: w.vm.ctx.ChainID, + Outs: outs, + Ins: ins, + Memo: memoBytes, + }}} + if err := tx.SignSECP256K1Fx(codec, keys); err != nil { + return err + } + txID, err := w.issue(tx) if err != nil { return fmt.Errorf("problem issuing transaction: %w", err) diff --git a/vms/avm/wallet_service_backend.go b/vms/avm/wallet_service_backend.go deleted file mode 100644 index 954b385dd56..00000000000 --- a/vms/avm/wallet_service_backend.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package avm - -import ( - "golang.org/x/exp/maps" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/linked" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" - "github.com/ava-labs/avalanchego/vms/components/avax" -) - -var _ builder.AVMBuilderBackend = (*walletServiceBackend)(nil) - -func NewWalletServiceBackend(vm *VM) *walletServiceBackend { - return &walletServiceBackend{ - vm: vm, - pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), - utxos: make([]*avax.UTXO, 0), - } -} - -type walletServiceBackend struct { - vm *VM - pendingTxs *linked.Hashmap[ids.ID, *txs.Tx] - utxos []*avax.UTXO -} - -func (b *walletServiceBackend) UTXOs(addrs set.Set[ids.ShortID], _ ids.ID) ([]*avax.UTXO, error) { - res, err := avax.GetAllUTXOs(b.vm.state, addrs) - if err != nil { - return nil, err - } - res = append(res, b.utxos...) - return res, nil -} - -func (b *walletServiceBackend) GetUTXO(addrs set.Set[ids.ShortID], _, utxoID ids.ID) (*avax.UTXO, error) { - allUTXOs, err := avax.GetAllUTXOs(b.vm.state, addrs) - if err != nil { - return nil, err - } - allUTXOs = append(allUTXOs, b.utxos...) - - for _, utxo := range allUTXOs { - if utxo.InputID() == utxoID { - return utxo, nil - } - } - return nil, database.ErrNotFound -} - -func (b *walletServiceBackend) update(utxos []*avax.UTXO) error { - utxoMap := make(map[ids.ID]*avax.UTXO, len(utxos)) - for _, utxo := range utxos { - utxoMap[utxo.InputID()] = utxo - } - - iter := b.pendingTxs.NewIterator() - - for iter.Next() { - tx := iter.Value() - for _, inputUTXO := range tx.Unsigned.InputUTXOs() { - if inputUTXO.Symbolic() { - continue - } - utxoID := inputUTXO.InputID() - if _, exists := utxoMap[utxoID]; !exists { - return errMissingUTXO - } - delete(utxoMap, utxoID) - } - - for _, utxo := range tx.UTXOs() { - utxoMap[utxo.InputID()] = utxo - } - } - - b.utxos = maps.Values(utxoMap) - return nil -} From adb9c2d2d8db6c448ad6d594d4630f559d00adcb Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 13:38:51 -0400 Subject: [PATCH 34/53] wip: move UTs to use their own backend --- vms/avm/environment_test.go | 24 +++------- vms/avm/service_test.go | 8 ++-- vms/avm/txs/builder/backend.go | 84 +++++++++++++++++++++++++++++++++ vms/avm/txs/builder/backends.go | 6 ++- vms/avm/vm_regression_test.go | 6 +-- vms/avm/vm_test.go | 22 ++++----- 6 files changed, 113 insertions(+), 37 deletions(-) create mode 100644 vms/avm/txs/builder/backend.go diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 165b600b75e..2b2dec7021d 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -24,6 +24,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/utils/linked" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/sampler" "github.com/ava-labs/avalanchego/utils/timer/mockable" @@ -109,6 +110,7 @@ type environment struct { sharedMemory *atomic.Memory issuer chan common.Message vm *VM + txBuilder *builder.Builder service *Service walletService *WalletService } @@ -198,34 +200,20 @@ func setup(tb testing.TB, c *envConfig) *environment { stopVertexID := ids.GenerateTestID() issuer := make(chan common.Message, 1) - var ( - serviceBackend = newServiceBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) - walletBackend = NewWalletServiceBackend(vm) - ) - + backend := builder.NewBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) env := &environment{ genesisBytes: genesisBytes, genesisTx: getCreateTxFromGenesisTest(tb, genesisBytes, assetName), sharedMemory: m, issuer: issuer, vm: vm, + txBuilder: builder.New(vm.ctx, &vm.Config, vm.feeAssetID, backend), service: &Service{ vm: vm, - builder: builder.New( - vm.ctx, - &vm.Config, - vm.feeAssetID, - serviceBackend, - ), }, walletService: &WalletService{ - walletServiceBackend: walletBackend, - builder: builder.New( - vm.ctx, - &vm.Config, - vm.feeAssetID, - walletBackend, - ), + vm: vm, + pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), }, } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 59716230e39..d004f0d8ae2 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1965,7 +1965,7 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { ) kc.Add(key) - tx, err := env.service.builder.BaseTx( + tx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.vm.feeAssetID}, Out: &secp256k1fx.TransferOutput{ @@ -1991,7 +1991,7 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStat ) kc.Add(key) - tx, err := env.service.builder.CreateAssetTx( + tx, err := env.txBuilder.CreateAssetTx( "Team Rocket", // name "TR", // symbol 0, // denomination @@ -2011,7 +2011,7 @@ func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { ) kc.Add(key) - tx, err := env.service.builder.ExportTx( + tx, err := env.txBuilder.ExportTx( chainID, to, env.vm.feeAssetID, @@ -2103,7 +2103,7 @@ func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation ) kc.Add(key) - tx, err := env.service.builder.Operation( + tx, err := env.txBuilder.Operation( ops, kc, key.Address(), diff --git a/vms/avm/txs/builder/backend.go b/vms/avm/txs/builder/backend.go new file mode 100644 index 00000000000..f4dc11578c9 --- /dev/null +++ b/vms/avm/txs/builder/backend.go @@ -0,0 +1,84 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package builder + +import ( + "fmt" + + "github.com/ava-labs/avalanchego/chains/atomic" + "github.com/ava-labs/avalanchego/codec" + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/avm/state" + "github.com/ava-labs/avalanchego/vms/components/avax" +) + +const maxPageSize uint64 = 1024 // TODO ABENEGIA: remove duplication + +var _ AVMBuilderBackend = (*Backend)(nil) + +func NewBackend( + ctx *snow.Context, + state state.State, + sharedMemory atomic.SharedMemory, + codec codec.Manager, +) *Backend { + return &Backend{ + xchainID: ctx.XChainID, + state: state, + sharedMemory: sharedMemory, + codec: codec, + } +} + +type Backend struct { + xchainID ids.ID + state state.State + sharedMemory atomic.SharedMemory + codec codec.Manager +} + +func (b *Backend) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { + if sourceChainID == b.xchainID { + return avax.GetAllUTXOs(b.state, addrs) + } + + atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( + b.sharedMemory, + b.codec, + sourceChainID, + addrs, + ids.ShortEmpty, + ids.Empty, + int(maxPageSize), + ) + return atomicUTXOs, err +} + +func (b *Backend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { + if chainID == b.xchainID { + return b.state.GetUTXO(utxoID) + } + + atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( + b.sharedMemory, + b.codec, + chainID, + addrs, + ids.ShortEmpty, + ids.Empty, + int(maxPageSize), + ) + if err != nil { + return nil, fmt.Errorf("problem retrieving atomic UTXOs: %w", err) + } + for _, utxo := range atomicUTXOs { + if utxo.InputID() == utxoID { + return utxo, nil + } + } + return nil, database.ErrNotFound +} diff --git a/vms/avm/txs/builder/backends.go b/vms/avm/txs/builder/backends.go index 6e54491e767..9229020e126 100644 --- a/vms/avm/txs/builder/backends.go +++ b/vms/avm/txs/builder/backends.go @@ -10,9 +10,13 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/wallet/chain/x/builder" + "github.com/ava-labs/avalanchego/wallet/chain/x/signer" ) -var _ builder.Backend = (*walletBackendAdapter)(nil) +var ( + _ builder.Backend = (*walletBackendAdapter)(nil) + _ signer.Backend = (*walletBackendAdapter)(nil) +) type AVMBuilderBackend interface { UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 8f276749122..714442645be 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -55,7 +55,7 @@ func TestVerifyFxUsage(t *testing.T) { } // Create the asset - createAssetTx, err := env.service.builder.CreateAssetTx( + createAssetTx, err := env.txBuilder.CreateAssetTx( "Team Rocket", // name "TR", // symbol 0, // denomination @@ -67,7 +67,7 @@ func TestVerifyFxUsage(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - mintNFTTx, err := env.service.builder.MintNFT( + mintNFTTx, err := env.txBuilder.MintNFT( createAssetTx.ID(), []byte{'h', 'e', 'l', 'l', 'o'}, // payload []*secp256k1fx.OutputOwners{{ @@ -82,7 +82,7 @@ func TestVerifyFxUsage(t *testing.T) { // move the NFT to := keys[2].PublicKey().Address() - spendTx, err := env.service.builder.BaseTx( + spendTx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{{ Asset: avax.Asset{ID: createAssetTx.ID()}, Out: &secp256k1fx.TransferOutput{ diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 95f0bf094ec..4e81df10ad0 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -160,7 +160,7 @@ func TestIssueNFT(t *testing.T) { }, } - createAssetTx, err := env.service.builder.CreateAssetTx( + createAssetTx, err := env.txBuilder.CreateAssetTx( "Team Rocket", // name "TR", // symbol 0, // denomination @@ -172,7 +172,7 @@ func TestIssueNFT(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) // Mint the NFT - mintNFTTx, err := env.service.builder.MintNFT( + mintNFTTx, err := env.txBuilder.MintNFT( createAssetTx.ID(), []byte{'h', 'e', 'l', 'l', 'o'}, // payload []*secp256k1fx.OutputOwners{{ @@ -197,7 +197,7 @@ func TestIssueNFT(t *testing.T) { ) require.NoError(err) - transferNFTTx, err := env.service.builder.Operation( + transferNFTTx, err := env.txBuilder.Operation( transferOp, kc, key.Address(), @@ -242,7 +242,7 @@ func TestIssueProperty(t *testing.T) { }, } - createAssetTx, err := env.service.builder.CreateAssetTx( + createAssetTx, err := env.txBuilder.CreateAssetTx( "Team Rocket", // name "TR", // symbol 0, // denomination @@ -274,7 +274,7 @@ func TestIssueProperty(t *testing.T) { }, } - mintPropertyTx, err := env.service.builder.Operation( + mintPropertyTx, err := env.txBuilder.Operation( []*txs.Operation{mintPropertyOp}, kc, key.Address(), @@ -292,7 +292,7 @@ func TestIssueProperty(t *testing.T) { Op: &propertyfx.BurnOperation{Input: secp256k1fx.Input{}}, } - burnPropertyTx, err := env.service.builder.Operation( + burnPropertyTx, err := env.txBuilder.Operation( []*txs.Operation{burnPropertyOp}, kc, key.Address(), @@ -344,7 +344,7 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { ) kc.Add(key) - tx, err := env.service.builder.BaseTx( + tx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{ { // fee asset Asset: avax.Asset{ID: feeAssetCreateTx.ID()}, @@ -421,7 +421,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { ) kc.Add(key) - firstTx, err := env.service.builder.BaseTx( + firstTx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{{ Asset: avax.Asset{ID: env.genesisTx.ID()}, Out: &secp256k1fx.TransferOutput{ @@ -542,7 +542,7 @@ func TestIssueImportTx(t *testing.T) { }, })) - tx, err := env.service.builder.ImportTx( + tx, err := env.txBuilder.ImportTx( constants.PlatformChainID, // source chain key.Address(), kc, @@ -663,7 +663,7 @@ func TestIssueExportTx(t *testing.T) { kc.Add(key) - tx, err := env.service.builder.ExportTx( + tx, err := env.txBuilder.ExportTx( constants.PlatformChainID, to, // to avaxID, @@ -729,7 +729,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { kc.Add(key) - tx, err := env.service.builder.ExportTx( + tx, err := env.txBuilder.ExportTx( constants.PlatformChainID, to, // to avaxID, From f7af3c1e2bcd3d48377814762f5f392cae04610b Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 13:56:53 -0400 Subject: [PATCH 35/53] consolidated txBuilder to make them similar to P-chain --- vms/avm/environment_test.go | 8 ++--- vms/avm/txs/builder/backends.go | 37 --------------------- vms/avm/txs/{builder => txstest}/backend.go | 25 ++++++++++++-- vms/avm/txs/{builder => txstest}/builder.go | 6 ++-- vms/avm/txs/{builder => txstest}/context.go | 2 +- 5 files changed, 30 insertions(+), 48 deletions(-) delete mode 100644 vms/avm/txs/builder/backends.go rename vms/avm/txs/{builder => txstest}/backend.go (72%) rename vms/avm/txs/{builder => txstest}/builder.go (98%) rename vms/avm/txs/{builder => txstest}/context.go (97%) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 2b2dec7021d..844b2de25a6 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -32,7 +32,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/builder" + "github.com/ava-labs/avalanchego/vms/avm/txs/txstest" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/nftfx" "github.com/ava-labs/avalanchego/vms/secp256k1fx" @@ -110,7 +110,7 @@ type environment struct { sharedMemory *atomic.Memory issuer chan common.Message vm *VM - txBuilder *builder.Builder + txBuilder *txstest.Builder service *Service walletService *WalletService } @@ -200,14 +200,14 @@ func setup(tb testing.TB, c *envConfig) *environment { stopVertexID := ids.GenerateTestID() issuer := make(chan common.Message, 1) - backend := builder.NewBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) + backend := txstest.NewBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) env := &environment{ genesisBytes: genesisBytes, genesisTx: getCreateTxFromGenesisTest(tb, genesisBytes, assetName), sharedMemory: m, issuer: issuer, vm: vm, - txBuilder: builder.New(vm.ctx, &vm.Config, vm.feeAssetID, backend), + txBuilder: txstest.New(vm.ctx, &vm.Config, vm.feeAssetID, backend), service: &Service{ vm: vm, }, diff --git a/vms/avm/txs/builder/backends.go b/vms/avm/txs/builder/backends.go deleted file mode 100644 index 9229020e126..00000000000 --- a/vms/avm/txs/builder/backends.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package builder - -import ( - "context" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/chain/x/builder" - "github.com/ava-labs/avalanchego/wallet/chain/x/signer" -) - -var ( - _ builder.Backend = (*walletBackendAdapter)(nil) - _ signer.Backend = (*walletBackendAdapter)(nil) -) - -type AVMBuilderBackend interface { - UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) - GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type walletBackendAdapter struct { - b AVMBuilderBackend - addrs set.Set[ids.ShortID] -} - -func (wa *walletBackendAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { - return wa.b.UTXOs(wa.addrs, sourceChainID) -} - -func (wa *walletBackendAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { - return wa.b.GetUTXO(wa.addrs, chainID, utxoID) -} diff --git a/vms/avm/txs/builder/backend.go b/vms/avm/txs/txstest/backend.go similarity index 72% rename from vms/avm/txs/builder/backend.go rename to vms/avm/txs/txstest/backend.go index f4dc11578c9..66a0c99d1fb 100644 --- a/vms/avm/txs/builder/backend.go +++ b/vms/avm/txs/txstest/backend.go @@ -1,9 +1,10 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package builder +package txstest import ( + "context" "fmt" "github.com/ava-labs/avalanchego/chains/atomic" @@ -14,11 +15,16 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/chain/x/builder" + "github.com/ava-labs/avalanchego/wallet/chain/x/signer" ) -const maxPageSize uint64 = 1024 // TODO ABENEGIA: remove duplication +const maxPageSize uint64 = 1024 -var _ AVMBuilderBackend = (*Backend)(nil) +var ( + _ builder.Backend = (*walletBackendAdapter)(nil) + _ signer.Backend = (*walletBackendAdapter)(nil) +) func NewBackend( ctx *snow.Context, @@ -82,3 +88,16 @@ func (b *Backend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (* } return nil, database.ErrNotFound } + +type walletBackendAdapter struct { + b *Backend + addrs set.Set[ids.ShortID] +} + +func (wa *walletBackendAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { + return wa.b.UTXOs(wa.addrs, sourceChainID) +} + +func (wa *walletBackendAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { + return wa.b.GetUTXO(wa.addrs, chainID, utxoID) +} diff --git a/vms/avm/txs/builder/builder.go b/vms/avm/txs/txstest/builder.go similarity index 98% rename from vms/avm/txs/builder/builder.go rename to vms/avm/txs/txstest/builder.go index f936c855f7f..4d59b0626b7 100644 --- a/vms/avm/txs/builder/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package builder +package txstest import ( "context" @@ -20,7 +20,7 @@ import ( ) type Builder struct { - backend AVMBuilderBackend + backend *Backend ctx *builder.Context } @@ -28,7 +28,7 @@ func New( ctx *snow.Context, cfg *config.Config, feeAssetID ids.ID, - backend AVMBuilderBackend, + backend *Backend, ) *Builder { return &Builder{ backend: backend, diff --git a/vms/avm/txs/builder/context.go b/vms/avm/txs/txstest/context.go similarity index 97% rename from vms/avm/txs/builder/context.go rename to vms/avm/txs/txstest/context.go index 9408fd04efa..ea3b9f2410f 100644 --- a/vms/avm/txs/builder/context.go +++ b/vms/avm/txs/txstest/context.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package builder +package txstest import ( "github.com/ava-labs/avalanchego/ids" From 21550da7f87518397bd99967605eb9b4844355a6 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 15:18:33 -0400 Subject: [PATCH 36/53] simplified avm test environment --- vms/avm/environment_test.go | 22 ++---- vms/avm/service_test.go | 137 ++++++++++++++++++++------------- vms/avm/wallet_service_test.go | 11 ++- 3 files changed, 99 insertions(+), 71 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 844b2de25a6..09c42e5bd99 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -24,7 +24,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" "github.com/ava-labs/avalanchego/utils/formatting/address" - "github.com/ava-labs/avalanchego/utils/linked" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/sampler" "github.com/ava-labs/avalanchego/utils/timer/mockable" @@ -105,14 +104,12 @@ type envConfig struct { } type environment struct { - genesisBytes []byte - genesisTx *txs.Tx - sharedMemory *atomic.Memory - issuer chan common.Message - vm *VM - txBuilder *txstest.Builder - service *Service - walletService *WalletService + genesisBytes []byte + genesisTx *txs.Tx + sharedMemory *atomic.Memory + issuer chan common.Message + vm *VM + txBuilder *txstest.Builder } // setup the testing environment @@ -208,13 +205,6 @@ func setup(tb testing.TB, c *envConfig) *environment { issuer: issuer, vm: vm, txBuilder: txstest.New(vm.ctx, &vm.Config, vm.feeAssetID, backend), - service: &Service{ - vm: vm, - }, - walletService: &WalletService{ - vm: vm, - pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), - }, } require.NoError(vm.SetState(context.Background(), snow.Bootstrapping)) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index d004f0d8ae2..53cf88619ca 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -51,6 +51,7 @@ func TestServiceIssueTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -61,7 +62,7 @@ func TestServiceIssueTx(t *testing.T) { txArgs := &api.FormattedTx{} txReply := &api.JSONTxID{} - err := env.service.IssueTx(nil, txArgs, txReply) + err := service.IssueTx(nil, txArgs, txReply) require.ErrorIs(err, codec.ErrCantUnpackVersion) tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, "AVAX") @@ -69,7 +70,7 @@ func TestServiceIssueTx(t *testing.T) { require.NoError(err) txArgs.Encoding = formatting.Hex txReply = &api.JSONTxID{} - require.NoError(env.service.IssueTx(nil, txArgs, txReply)) + require.NoError(service.IssueTx(nil, txArgs, txReply)) require.Equal(tx.ID(), txReply.TxID) } @@ -79,6 +80,7 @@ func TestServiceGetTxStatus(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -89,7 +91,7 @@ func TestServiceGetTxStatus(t *testing.T) { statusArgs := &api.JSONTxID{} statusReply := &GetTxStatusReply{} - err := env.service.GetTxStatus(nil, statusArgs, statusReply) + err := service.GetTxStatus(nil, statusArgs, statusReply) require.ErrorIs(err, errNilTxID) newTx := newAvaxBaseTxWithOutputs(t, env) @@ -99,13 +101,13 @@ func TestServiceGetTxStatus(t *testing.T) { TxID: txID, } statusReply = &GetTxStatusReply{} - require.NoError(env.service.GetTxStatus(nil, statusArgs, statusReply)) + require.NoError(service.GetTxStatus(nil, statusArgs, statusReply)) require.Equal(choices.Unknown, statusReply.Status) issueAndAccept(require, env.vm, env.issuer, newTx) statusReply = &GetTxStatusReply{} - require.NoError(env.service.GetTxStatus(nil, statusArgs, statusReply)) + require.NoError(service.GetTxStatus(nil, statusArgs, statusReply)) require.Equal(choices.Accepted, statusReply.Status) } @@ -116,6 +118,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} defer func() { env.vm.ctx.Lock.Lock() require.NoError(env.vm.Shutdown(context.Background())) @@ -156,7 +159,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { IncludePartial: true, } balanceReply := &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should include the UTXO since it is partly owned by [addr] require.Equal(uint64(1337), uint64(balanceReply.Balance)) require.Len(balanceReply.UTXOIDs, 1) @@ -167,7 +170,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { AssetID: assetID.String(), } balanceReply = &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should not include the UTXO since it is only partly owned by [addr] require.Zero(balanceReply.Balance) require.Empty(balanceReply.UTXOIDs) @@ -203,7 +206,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { IncludePartial: true, } balanceReply = &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should include the UTXO since it is partly owned by [addr] require.Equal(uint64(1337+1337), uint64(balanceReply.Balance)) require.Len(balanceReply.UTXOIDs, 2) @@ -214,7 +217,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { AssetID: assetID.String(), } balanceReply = &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should not include the UTXO since it is only partly owned by [addr] require.Zero(balanceReply.Balance) require.Empty(balanceReply.UTXOIDs) @@ -252,7 +255,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { IncludePartial: true, } balanceReply = &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should include the UTXO since it is partly owned by [addr] require.Equal(uint64(1337*3), uint64(balanceReply.Balance)) require.Len(balanceReply.UTXOIDs, 3) @@ -263,7 +266,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { AssetID: assetID.String(), } balanceReply = &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, balanceArgs, balanceReply)) + require.NoError(service.GetBalance(nil, balanceArgs, balanceReply)) // The balance should not include the UTXO since it is only partly owned by [addr] require.Zero(balanceReply.Balance) require.Empty(balanceReply.UTXOIDs) @@ -274,6 +277,7 @@ func TestServiceGetTxs(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} var err error env.vm.addressTxsIndexer, err = index.NewIndexer(env.vm.db, env.vm.ctx.Log, "", prometheus.NewRegistry(), false) require.NoError(err) @@ -300,14 +304,14 @@ func TestServiceGetTxs(t *testing.T) { AssetID: assetID.String(), } getTxsReply := &GetAddressTxsReply{} - require.NoError(env.service.GetAddressTxs(nil, getTxsArgs, getTxsReply)) + require.NoError(service.GetAddressTxs(nil, getTxsArgs, getTxsReply)) require.Len(getTxsReply.TxIDs, 10) require.Equal(getTxsReply.TxIDs, testTxs[:10]) // get the second page getTxsArgs.Cursor = getTxsReply.Cursor getTxsReply = &GetAddressTxsReply{} - require.NoError(env.service.GetAddressTxs(nil, getTxsArgs, getTxsReply)) + require.NoError(service.GetAddressTxs(nil, getTxsArgs, getTxsReply)) require.Len(getTxsReply.TxIDs, 10) require.Equal(getTxsReply.TxIDs, testTxs[10:20]) } @@ -318,6 +322,7 @@ func TestServiceGetAllBalances(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} defer func() { env.vm.ctx.Lock.Lock() require.NoError(env.vm.Shutdown(context.Background())) @@ -356,7 +361,7 @@ func TestServiceGetAllBalances(t *testing.T) { IncludePartial: true, } reply := &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should include the UTXO since it is partly owned by [addr] require.Len(reply.Balances, 1) require.Equal(assetID.String(), reply.Balances[0].AssetID) @@ -367,7 +372,7 @@ func TestServiceGetAllBalances(t *testing.T) { JSONAddress: api.JSONAddress{Address: addrStr}, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) require.Empty(reply.Balances) env.vm.ctx.Lock.Lock() @@ -400,7 +405,7 @@ func TestServiceGetAllBalances(t *testing.T) { IncludePartial: true, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should include the UTXO since it is partly owned by [addr] require.Len(reply.Balances, 1) require.Equal(assetID.String(), reply.Balances[0].AssetID) @@ -411,7 +416,7 @@ func TestServiceGetAllBalances(t *testing.T) { JSONAddress: api.JSONAddress{Address: addrStr}, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should not include the UTXO since it is only partly owned by [addr] require.Empty(reply.Balances) @@ -447,7 +452,7 @@ func TestServiceGetAllBalances(t *testing.T) { IncludePartial: true, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should include the UTXO since it is partly owned by [addr] // The balance should include the UTXO since it is partly owned by [addr] require.Len(reply.Balances, 1) @@ -458,7 +463,7 @@ func TestServiceGetAllBalances(t *testing.T) { JSONAddress: api.JSONAddress{Address: addrStr}, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should not include the UTXO since it is only partly owned by [addr] require.Empty(reply.Balances) @@ -492,7 +497,7 @@ func TestServiceGetAllBalances(t *testing.T) { IncludePartial: true, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should include the UTXO since it is partly owned by [addr] require.Len(reply.Balances, 2) gotAssetIDs := []string{reply.Balances[0].AssetID, reply.Balances[1].AssetID} @@ -507,7 +512,7 @@ func TestServiceGetAllBalances(t *testing.T) { JSONAddress: api.JSONAddress{Address: addrStr}, } reply = &GetAllBalancesReply{} - require.NoError(env.service.GetAllBalances(nil, balanceArgs, reply)) + require.NoError(service.GetAllBalances(nil, balanceArgs, reply)) // The balance should include the UTXO since it is partly owned by [addr] require.Empty(reply.Balances) } @@ -518,6 +523,7 @@ func TestServiceGetTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -529,7 +535,7 @@ func TestServiceGetTx(t *testing.T) { txID := env.genesisTx.ID() reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: txID, Encoding: formatting.Hex, }, &reply)) @@ -548,6 +554,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -559,7 +566,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: newTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -645,6 +652,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -656,7 +664,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, newTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: newTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -748,6 +756,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -804,7 +813,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: createAssetTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -945,6 +954,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -979,7 +989,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintNFTTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -1096,6 +1106,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -1133,7 +1144,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintNFTTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -1286,6 +1297,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -1317,7 +1329,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintSecpOpTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -1438,6 +1450,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -1473,7 +1486,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintSecpOpTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -1634,6 +1647,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -1660,7 +1674,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintPropertyFxOpTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -1778,6 +1792,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) Fx: &propertyfx.Fx{}, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { env.vm.ctx.Lock.Lock() @@ -1811,7 +1826,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} - require.NoError(env.service.GetTx(nil, &api.GetTxArgs{ + require.NoError(service.GetTx(nil, &api.GetTxArgs{ TxID: mintPropertyFxOpTx.ID(), Encoding: formatting.JSON, }, &reply)) @@ -2118,6 +2133,7 @@ func TestServiceGetNilTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2127,7 +2143,7 @@ func TestServiceGetNilTx(t *testing.T) { }() reply := api.GetTxReply{} - err := env.service.GetTx(nil, &api.GetTxArgs{}, &reply) + err := service.GetTx(nil, &api.GetTxArgs{}, &reply) require.ErrorIs(err, errNilTxID) } @@ -2137,6 +2153,7 @@ func TestServiceGetUnknownTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2146,7 +2163,7 @@ func TestServiceGetUnknownTx(t *testing.T) { }() reply := api.GetTxReply{} - err := env.service.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) + err := service.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) require.ErrorIs(err, database.ErrNotFound) } @@ -2154,6 +2171,7 @@ func TestServiceGetUTXOs(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} defer func() { env.vm.ctx.Lock.Lock() require.NoError(t, env.vm.Shutdown(context.Background())) @@ -2395,7 +2413,7 @@ func TestServiceGetUTXOs(t *testing.T) { t.Run(test.label, func(t *testing.T) { require := require.New(t) reply := &api.GetUTXOsReply{} - err := env.service.GetUTXOs(nil, test.args, reply) + err := service.GetUTXOs(nil, test.args, reply) require.ErrorIs(err, test.expectedErr) if test.expectedErr != nil { return @@ -2411,6 +2429,7 @@ func TestGetAssetDescription(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2422,7 +2441,7 @@ func TestGetAssetDescription(t *testing.T) { avaxAssetID := env.genesisTx.ID() reply := GetAssetDescriptionReply{} - require.NoError(env.service.GetAssetDescription(nil, &GetAssetDescriptionArgs{ + require.NoError(service.GetAssetDescription(nil, &GetAssetDescriptionArgs{ AssetID: avaxAssetID.String(), }, &reply)) @@ -2436,6 +2455,7 @@ func TestGetBalance(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2449,7 +2469,7 @@ func TestGetBalance(t *testing.T) { reply := GetBalanceReply{} addrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) require.NoError(err) - require.NoError(env.service.GetBalance(nil, &GetBalanceArgs{ + require.NoError(service.GetBalance(nil, &GetBalanceArgs{ Address: addrStr, AssetID: avaxAssetID.String(), }, &reply)) @@ -2470,6 +2490,7 @@ func TestCreateFixedCapAsset(t *testing.T) { initialKeys: keys, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2486,7 +2507,7 @@ func TestCreateFixedCapAsset(t *testing.T) { require.NoError(err) _, fromAddrsStr := sampleAddrs(t, env.vm.AddressManager, addrs) - require.NoError(env.service.CreateFixedCapAsset(nil, &CreateAssetArgs{ + require.NoError(service.CreateFixedCapAsset(nil, &CreateAssetArgs{ JSONSpendHeader: api.JSONSpendHeader{ UserPass: api.UserPass{ Username: username, @@ -2521,6 +2542,7 @@ func TestCreateVariableCapAsset(t *testing.T) { initialKeys: keys, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2535,7 +2557,7 @@ func TestCreateVariableCapAsset(t *testing.T) { _, fromAddrsStr := sampleAddrs(t, env.vm.AddressManager, addrs) changeAddrStr := fromAddrsStr[0] - require.NoError(env.service.CreateVariableCapAsset(nil, &CreateAssetArgs{ + require.NoError(service.CreateVariableCapAsset(nil, &CreateAssetArgs{ JSONSpendHeader: api.JSONSpendHeader{ UserPass: api.UserPass{ Username: username, @@ -2574,7 +2596,7 @@ func TestCreateVariableCapAsset(t *testing.T) { To: minterAddrStr, // Send newly minted tokens to this address } mintReply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.Mint(nil, mintArgs, mintReply)) + require.NoError(service.Mint(nil, mintArgs, mintReply)) require.Equal(changeAddrStr, mintReply.ChangeAddr) buildAndAccept(require, env.vm, env.issuer, mintReply.TxID) @@ -2595,7 +2617,7 @@ func TestCreateVariableCapAsset(t *testing.T) { }, } sendReply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.Send(nil, sendArgs, sendReply)) + require.NoError(service.Send(nil, sendArgs, sendReply)) require.Equal(changeAddrStr, sendReply.ChangeAddr) }) } @@ -2614,6 +2636,7 @@ func TestNFTWorkflow(t *testing.T) { initialKeys: keys, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2649,7 +2672,7 @@ func TestNFTWorkflow(t *testing.T) { }, } createReply := &AssetIDChangeAddr{} - require.NoError(env.service.CreateNFTAsset(nil, createArgs, createReply)) + require.NoError(service.CreateNFTAsset(nil, createArgs, createReply)) require.Equal(fromAddrsStr[0], createReply.ChangeAddr) buildAndAccept(require, env.vm, env.issuer, createReply.AssetID) @@ -2662,7 +2685,7 @@ func TestNFTWorkflow(t *testing.T) { require.NoError(err) reply := &GetBalanceReply{} - require.NoError(env.service.GetBalance(nil, + require.NoError(service.GetBalance(nil, &GetBalanceArgs{ Address: addrStr, AssetID: env.vm.feeAssetID.String(), @@ -2700,7 +2723,7 @@ func TestNFTWorkflow(t *testing.T) { } mintReply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.MintNFT(nil, mintArgs, mintReply)) + require.NoError(service.MintNFT(nil, mintArgs, mintReply)) require.Equal(fromAddrsStr[0], createReply.ChangeAddr) // Accept the transaction so that we can send the newly minted NFT @@ -2720,7 +2743,7 @@ func TestNFTWorkflow(t *testing.T) { To: addrStr, } sendReply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.SendNFT(nil, sendArgs, sendReply)) + require.NoError(service.SendNFT(nil, sendArgs, sendReply)) require.Equal(fromAddrsStr[0], sendReply.ChangeAddr) }) } @@ -2735,6 +2758,7 @@ func TestImportExportKey(t *testing.T) { password: password, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2754,7 +2778,7 @@ func TestImportExportKey(t *testing.T) { PrivateKey: sk, } importReply := &api.JSONAddress{} - require.NoError(env.service.ImportKey(nil, importArgs, importReply)) + require.NoError(service.ImportKey(nil, importArgs, importReply)) addrStr, err := env.vm.FormatLocalAddress(sk.PublicKey().Address()) require.NoError(err) @@ -2766,7 +2790,7 @@ func TestImportExportKey(t *testing.T) { Address: addrStr, } exportReply := &ExportKeyReply{} - require.NoError(env.service.ExportKey(nil, exportArgs, exportReply)) + require.NoError(service.ExportKey(nil, exportArgs, exportReply)) require.Equal(sk.Bytes(), exportReply.PrivateKey.Bytes()) } @@ -2779,6 +2803,7 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { password: password, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2797,7 +2822,7 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { PrivateKey: sk, } reply := api.JSONAddress{} - require.NoError(env.service.ImportKey(nil, &args, &reply)) + require.NoError(service.ImportKey(nil, &args, &reply)) expectedAddress, err := env.vm.FormatLocalAddress(sk.PublicKey().Address()) require.NoError(err) @@ -2805,7 +2830,7 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { require.Equal(expectedAddress, reply.Address) reply2 := api.JSONAddress{} - require.NoError(env.service.ImportKey(nil, &args, &reply2)) + require.NoError(service.ImportKey(nil, &args, &reply2)) require.Equal(expectedAddress, reply2.Address) @@ -2814,7 +2839,7 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { Password: password, } addrsReply := api.JSONAddresses{} - require.NoError(env.service.ListAddresses(nil, &addrsArgs, &addrsReply)) + require.NoError(service.ListAddresses(nil, &addrsArgs, &addrsReply)) require.Len(addrsReply.Addresses, 1) require.Equal(expectedAddress, addrsReply.Addresses[0]) @@ -2830,6 +2855,7 @@ func TestSend(t *testing.T) { initialKeys: keys, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2863,7 +2889,7 @@ func TestSend(t *testing.T) { }, } reply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.Send(nil, args, reply)) + require.NoError(service.Send(nil, args, reply)) require.Equal(changeAddrStr, reply.ChangeAddr) buildAndAccept(require, env.vm, env.issuer, reply.TxID) @@ -2885,6 +2911,7 @@ func TestSendMultiple(t *testing.T) { EUpgradeTime: mockable.MaxTime, }, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2925,7 +2952,7 @@ func TestSendMultiple(t *testing.T) { }, } reply := &api.JSONTxIDChangeAddr{} - require.NoError(env.service.SendMultiple(nil, args, reply)) + require.NoError(service.SendMultiple(nil, args, reply)) require.Equal(changeAddrStr, reply.ChangeAddr) buildAndAccept(require, env.vm, env.issuer, reply.TxID) @@ -2942,6 +2969,7 @@ func TestCreateAndListAddresses(t *testing.T) { password: password, }}, }) + service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() defer func() { @@ -2956,7 +2984,7 @@ func TestCreateAndListAddresses(t *testing.T) { } createReply := &api.JSONAddress{} - require.NoError(env.service.CreateAddress(nil, createArgs, createReply)) + require.NoError(service.CreateAddress(nil, createArgs, createReply)) newAddr := createReply.Address @@ -2966,7 +2994,7 @@ func TestCreateAndListAddresses(t *testing.T) { } listReply := &api.JSONAddresses{} - require.NoError(env.service.ListAddresses(nil, listArgs, listReply)) + require.NoError(service.ListAddresses(nil, listArgs, listReply)) require.Contains(listReply.Addresses, newAddr) } @@ -2983,6 +3011,7 @@ func TestImport(t *testing.T) { initialKeys: keys, }}, }) + service := &Service{vm: env.vm} defer func() { env.vm.ctx.Lock.Lock() @@ -3033,7 +3062,7 @@ func TestImport(t *testing.T) { To: addrStr, } reply := &api.JSONTxID{} - require.NoError(env.service.Import(nil, args, reply)) + require.NoError(service.Import(nil, args, reply)) }) } } diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index eeb214fba9b..55061492442 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -10,6 +10,9 @@ import ( "github.com/stretchr/testify/require" "github.com/ava-labs/avalanchego/api" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/linked" + "github.com/ava-labs/avalanchego/vms/avm/txs" ) func TestWalletService_SendMultiple(t *testing.T) { @@ -26,6 +29,12 @@ func TestWalletService_SendMultiple(t *testing.T) { initialKeys: keys, }}, }) + + walletService := &WalletService{ + vm: env.vm, + pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), + } + env.vm.ctx.Lock.Unlock() defer func() { @@ -65,7 +74,7 @@ func TestWalletService_SendMultiple(t *testing.T) { }, } reply := &api.JSONTxIDChangeAddr{} - require.NoError(env.walletService.SendMultiple(nil, args, reply)) + require.NoError(walletService.SendMultiple(nil, args, reply)) require.Equal(changeAddrStr, reply.ChangeAddr) buildAndAccept(require, env.vm, env.issuer, reply.TxID) From 9d4e0d4cf77f67135249869807ba1226ddc88010 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 21:34:42 -0400 Subject: [PATCH 37/53] consolidated avm UTs cleanup --- vms/avm/environment_test.go | 8 ++ vms/avm/index_test.go | 36 +------ vms/avm/service_test.go | 167 +-------------------------------- vms/avm/state_test.go | 16 +--- vms/avm/vm_benchmark_test.go | 11 +-- vms/avm/vm_regression_test.go | 6 -- vms/avm/vm_test.go | 68 ++------------ vms/avm/wallet_service_test.go | 8 +- 8 files changed, 26 insertions(+), 294 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 09c42e5bd99..af295c02e71 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -218,6 +218,14 @@ func setup(tb testing.TB, c *envConfig) *environment { } require.NoError(vm.SetState(context.Background(), snow.NormalOp)) + + tb.Cleanup(func() { + env.vm.ctx.Lock.Lock() + defer env.vm.ctx.Lock.Unlock() + + require.NoError(env.vm.Shutdown(context.Background())) + }) + return env } diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index f2d78c5379a..8f66fe25852 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "testing" "github.com/prometheus/client_golang/prometheus" @@ -29,10 +28,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() key := keys[0] addr := key.PublicKey().Address() @@ -51,12 +47,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addr) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - env.vm.ctx.Lock.Unlock() - issueAndAccept(require, env.vm, env.issuer, tx) - - env.vm.ctx.Lock.Lock() - txs = append(txs, tx) } @@ -71,10 +62,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() addressTxMap := map[ids.ShortID]*txs.Tx{} txAssetID := avax.Asset{ID: env.genesisTx.ID()} @@ -93,13 +81,8 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addr) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - env.vm.ctx.Lock.Unlock() - // issue transaction issueAndAccept(require, env.vm, env.issuer, tx) - - env.vm.ctx.Lock.Lock() - addressTxMap[addr] = tx } @@ -117,10 +100,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() addrs := make([]ids.ShortID, len(keys)) for i, key := range keys { @@ -144,12 +124,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addrs...) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) - env.vm.ctx.Lock.Unlock() - issueAndAccept(require, env.vm, env.issuer, tx) - - env.vm.ctx.Lock.Lock() - assertIndexedTX(t, env.vm.db, 0, addr, txAssetID.ID, tx.ID()) assertLatestIdx(t, env.vm.db, addr, txAssetID.ID, 1) } @@ -158,10 +133,7 @@ func TestIndexer_Read(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() // generate test address and asset IDs assetID := ids.GenerateTestID() diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 53cf88619ca..c422113cc60 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "encoding/json" "strings" "testing" @@ -54,12 +53,6 @@ func TestServiceIssueTx(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - txArgs := &api.FormattedTx{} txReply := &api.JSONTxID{} err := service.IssueTx(nil, txArgs, txReply) @@ -83,12 +76,6 @@ func TestServiceGetTxStatus(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - statusArgs := &api.JSONTxID{} statusReply := &GetTxStatusReply{} err := service.GetTxStatus(nil, statusArgs, statusReply) @@ -119,11 +106,6 @@ func TestServiceGetBalanceStrict(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -281,11 +263,6 @@ func TestServiceGetTxs(t *testing.T) { var err error env.vm.addressTxsIndexer, err = index.NewIndexer(env.vm.db, env.vm.ctx.Log, "", prometheus.NewRegistry(), false) require.NoError(err) - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -323,11 +300,6 @@ func TestServiceGetAllBalances(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -526,12 +498,6 @@ func TestServiceGetTx(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - txID := env.genesisTx.ID() reply := api.GetTxReply{} @@ -556,11 +522,6 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() newTx := newAvaxBaseTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -654,11 +615,6 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -758,11 +714,6 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() initialStates := map[uint32][]verify.State{ uint32(0): { @@ -956,11 +907,6 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1108,11 +1054,6 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1299,11 +1240,6 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1452,11 +1388,6 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1649,11 +1580,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1794,11 +1720,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }) service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -2136,12 +2057,6 @@ func TestServiceGetNilTx(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{}, &reply) require.ErrorIs(err, errNilTxID) @@ -2156,12 +2071,6 @@ func TestServiceGetUnknownTx(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) require.ErrorIs(err, database.ErrNotFound) @@ -2172,11 +2081,7 @@ func TestServiceGetUTXOs(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(t, env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() rawAddr := ids.GenerateTestShortID() rawEmptyAddr := ids.GenerateTestShortID() @@ -2248,8 +2153,6 @@ func TestServiceGetUTXOs(t *testing.T) { xEmptyAddr, err := env.vm.FormatLocalAddress(rawEmptyAddr) require.NoError(t, err) - env.vm.ctx.Lock.Unlock() - tests := []struct { label string count int @@ -2432,12 +2335,6 @@ func TestGetAssetDescription(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - avaxAssetID := env.genesisTx.ID() reply := GetAssetDescriptionReply{} @@ -2458,12 +2355,6 @@ func TestGetBalance(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - avaxAssetID := env.genesisTx.ID() reply := GetBalanceReply{} @@ -2493,12 +2384,6 @@ func TestCreateFixedCapAsset(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - reply := AssetIDChangeAddr{} addrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) require.NoError(err) @@ -2545,12 +2430,6 @@ func TestCreateVariableCapAsset(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - reply := AssetIDChangeAddr{} minterAddrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) require.NoError(err) @@ -2639,12 +2518,6 @@ func TestNFTWorkflow(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - fromAddrs, fromAddrsStr := sampleAddrs(t, env.vm.AddressManager, addrs) // Test minting of the created variable cap asset @@ -2761,12 +2634,6 @@ func TestImportExportKey(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - sk, err := secp256k1.NewPrivateKey() require.NoError(err) @@ -2806,12 +2673,6 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - sk, err := secp256k1.NewPrivateKey() require.NoError(err) args := ImportKeyArgs{ @@ -2858,12 +2719,6 @@ func TestSend(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2914,12 +2769,6 @@ func TestSendMultiple(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2972,12 +2821,6 @@ func TestCreateAndListAddresses(t *testing.T) { service := &Service{vm: env.vm} env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - createArgs := &api.UserPass{ Username: username, Password: password, @@ -3012,12 +2855,8 @@ func TestImport(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() assetID := env.genesisTx.ID() addr0 := keys[0].PublicKey().Address() @@ -3049,8 +2888,6 @@ func TestImport(t *testing.T) { }, })) - env.vm.ctx.Lock.Unlock() - addrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) require.NoError(err) args := &ImportArgs{ diff --git a/vms/avm/state_test.go b/vms/avm/state_test.go index e71acf1251c..57d4944a587 100644 --- a/vms/avm/state_test.go +++ b/vms/avm/state_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "math" "testing" @@ -35,10 +34,7 @@ func TestSetsAndGets(t *testing.T) { }, }}, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -98,10 +94,7 @@ func TestFundingNoAddresses(t *testing.T) { }, }}, }) - defer func() { - require.NoError(t, env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -131,10 +124,7 @@ func TestFundingAddresses(t *testing.T) { }, }}, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ diff --git a/vms/avm/vm_benchmark_test.go b/vms/avm/vm_benchmark_test.go index e0bb3080c4e..9e35d0f0ae0 100644 --- a/vms/avm/vm_benchmark_test.go +++ b/vms/avm/vm_benchmark_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "fmt" "math/rand" "testing" @@ -29,10 +28,7 @@ func BenchmarkLoadUser(b *testing.B) { password: password, }}, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() user, err := keystore.NewUserFromKeystore(env.vm.ctx.Keystore, username, password) require.NoError(err) @@ -69,10 +65,7 @@ func getAllUTXOsBenchmark(b *testing.B, utxoCount int, randSrc rand.Source) { require := require.New(b) env := setup(b, &envConfig{fork: latest}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() addr := ids.GenerateTestShortID() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index 714442645be..de1933648ae 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -21,11 +20,6 @@ func TestVerifyFxUsage(t *testing.T) { env := setup(t, &envConfig{fork: latest}) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() var ( key = keys[0] diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 4e81df10ad0..7c8516195b0 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -117,11 +117,6 @@ func TestIssueTx(t *testing.T) { fork: latest, }) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, "AVAX") issueAndAccept(require, env.vm, env.issuer, tx) @@ -135,11 +130,6 @@ func TestIssueNFT(t *testing.T) { fork: latest, }) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() var ( key = keys[0] @@ -218,11 +208,6 @@ func TestIssueProperty(t *testing.T) { }}, }) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() var ( key = keys[0] @@ -309,11 +294,6 @@ func TestIssueTxWithFeeAsset(t *testing.T) { isCustomFeeAsset: true, }) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() // send first asset tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, feeAssetName) @@ -328,11 +308,6 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { isCustomFeeAsset: true, }) env.vm.ctx.Lock.Unlock() - defer func() { - env.vm.ctx.Lock.Lock() - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() // send second asset var ( @@ -379,10 +354,7 @@ func TestVMFormat(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - defer func() { - require.NoError(t, env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() tests := []struct { in ids.ShortID @@ -410,10 +382,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { fork: latest, notLinearized: true, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -488,10 +457,7 @@ func TestIssueImportTx(t *testing.T) { env := setup(t, &envConfig{ fork: durango, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) @@ -549,12 +515,7 @@ func TestIssueImportTx(t *testing.T) { ) require.NoError(err) - env.vm.ctx.Lock.Unlock() - issueAndAccept(require, env.vm, env.issuer, tx) - - env.vm.ctx.Lock.Lock() - assertIndexedTX(t, env.vm.db, 0, key.PublicKey().Address(), txAssetID.AssetID(), tx.ID()) assertLatestIdx(t, env.vm.db, key.PublicKey().Address(), avaxID, 1) @@ -571,10 +532,7 @@ func TestForceAcceptImportTx(t *testing.T) { fork: durango, notLinearized: true, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() @@ -646,10 +604,7 @@ func TestIssueExportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -686,12 +641,8 @@ func TestIssueExportTx(t *testing.T) { require.NoError(err) require.Empty(utxoBytes) - env.vm.ctx.Lock.Unlock() - issueAndAccept(require, env.vm, env.issuer, tx) - env.vm.ctx.Lock.Lock() - utxoBytes, _, _, err = peerSharedMemory.Indexed( env.vm.ctx.ChainID, [][]byte{ @@ -711,10 +662,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -755,12 +703,8 @@ func TestClearForceAcceptedExportTx(t *testing.T) { _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) - env.vm.ctx.Lock.Unlock() - issueAndAccept(require, env.vm, env.issuer, tx) - env.vm.ctx.Lock.Lock() - _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index 55061492442..2b33e2e9f6b 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -4,7 +4,6 @@ package avm import ( - "context" "testing" "github.com/stretchr/testify/require" @@ -37,11 +36,6 @@ func TestWalletService_SendMultiple(t *testing.T) { env.vm.ctx.Lock.Unlock() - defer func() { - require.NoError(env.vm.Shutdown(context.Background())) - env.vm.ctx.Lock.Unlock() - }() - assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -80,8 +74,8 @@ func TestWalletService_SendMultiple(t *testing.T) { buildAndAccept(require, env.vm, env.issuer, reply.TxID) env.vm.ctx.Lock.Lock() - _, err = env.vm.state.GetTx(reply.TxID) + env.vm.ctx.Lock.Unlock() require.NoError(err) }) } From 9b31b052c921c7fa423c287b563bd3933be2a0f0 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 May 2024 21:43:36 -0400 Subject: [PATCH 38/53] nits over avm tx builder --- vms/avm/txs/txstest/builder.go | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index 4d59b0626b7..ab01e63ba02 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -56,12 +56,7 @@ func (b *Builder) CreateAssetTx( return nil, fmt.Errorf("failed building base tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) - if err != nil { - return nil, err - } - - return tx, nil + return signer.SignUnsigned(context.Background(), xSigner, utx) } func (b *Builder) BaseTx( @@ -80,12 +75,7 @@ func (b *Builder) BaseTx( return nil, fmt.Errorf("failed building base tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) - if err != nil { - return nil, err - } - - return tx, nil + return signer.SignUnsigned(context.Background(), xSigner, utx) } func (b *Builder) MintNFT( @@ -201,11 +191,7 @@ func (b *Builder) ExportTx( return nil, fmt.Errorf("failed building export tx: %w", err) } - tx, err := signer.SignUnsigned(context.Background(), xSigner, utx) - if err != nil { - return nil, err - } - return tx, nil + return signer.SignUnsigned(context.Background(), xSigner, utx) } func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { From 3013fb11ba720ab972777056942c96b9c689f216 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 05:11:12 -0400 Subject: [PATCH 39/53] removed some code duplication across UTs --- vms/avm/environment_test.go | 1 + vms/avm/index_test.go | 4 ---- vms/avm/service_test.go | 32 -------------------------------- vms/avm/state_test.go | 3 --- vms/avm/vm_benchmark_test.go | 2 -- vms/avm/vm_regression_test.go | 1 - vms/avm/vm_test.go | 11 ----------- vms/avm/wallet_service_test.go | 2 -- 8 files changed, 1 insertion(+), 55 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index af295c02e71..7ee61daf81c 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -219,6 +219,7 @@ func setup(tb testing.TB, c *envConfig) *environment { require.NoError(vm.SetState(context.Background(), snow.NormalOp)) + vm.ctx.Lock.Unlock() tb.Cleanup(func() { env.vm.ctx.Lock.Lock() defer env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 8f66fe25852..9f5c0a830aa 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,7 +28,6 @@ func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() key := keys[0] addr := key.PublicKey().Address() @@ -62,7 +61,6 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() addressTxMap := map[ids.ShortID]*txs.Tx{} txAssetID := avax.Asset{ID: env.genesisTx.ID()} @@ -100,7 +98,6 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() addrs := make([]ids.ShortID, len(keys)) for i, key := range keys { @@ -133,7 +130,6 @@ func TestIndexer_Read(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() // generate test address and asset IDs assetID := ids.GenerateTestID() diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index c422113cc60..5fb5fe8d15d 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -51,7 +51,6 @@ func TestServiceIssueTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() txArgs := &api.FormattedTx{} txReply := &api.JSONTxID{} @@ -74,7 +73,6 @@ func TestServiceGetTxStatus(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() statusArgs := &api.JSONTxID{} statusReply := &GetTxStatusReply{} @@ -132,8 +130,6 @@ func TestServiceGetBalanceStrict(t *testing.T) { env.vm.state.AddUTXO(twoOfTwoUTXO) require.NoError(env.vm.state.Commit()) - env.vm.ctx.Lock.Unlock() - // Check the balance with IncludePartial set to true balanceArgs := &GetBalanceArgs{ Address: addrStr, @@ -272,8 +268,6 @@ func TestServiceGetTxs(t *testing.T) { testTxCount := 25 testTxs := initTestTxIndex(t, env.vm.db, addr, assetID, testTxCount) - env.vm.ctx.Lock.Unlock() - // get the first page getTxsArgs := &GetAddressTxsArgs{ PageSize: 10, @@ -325,8 +319,6 @@ func TestServiceGetAllBalances(t *testing.T) { env.vm.state.AddUTXO(twoOfTwoUTXO) require.NoError(env.vm.state.Commit()) - env.vm.ctx.Lock.Unlock() - // Check the balance with IncludePartial set to true balanceArgs := &GetAllBalancesArgs{ JSONAddress: api.JSONAddress{Address: addrStr}, @@ -496,7 +488,6 @@ func TestServiceGetTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() txID := env.genesisTx.ID() @@ -521,7 +512,6 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() newTx := newAvaxBaseTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -614,7 +604,6 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -713,7 +702,6 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() initialStates := map[uint32][]verify.State{ uint32(0): { @@ -906,7 +894,6 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1053,7 +1040,6 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1239,7 +1225,6 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1387,7 +1372,6 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1579,7 +1563,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1719,7 +1702,6 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -2055,7 +2037,6 @@ func TestServiceGetNilTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{}, &reply) @@ -2069,7 +2050,6 @@ func TestServiceGetUnknownTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) @@ -2081,7 +2061,6 @@ func TestServiceGetUTXOs(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() rawAddr := ids.GenerateTestShortID() rawEmptyAddr := ids.GenerateTestShortID() @@ -2333,7 +2312,6 @@ func TestGetAssetDescription(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() avaxAssetID := env.genesisTx.ID() @@ -2353,7 +2331,6 @@ func TestGetBalance(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() avaxAssetID := env.genesisTx.ID() @@ -2382,7 +2359,6 @@ func TestCreateFixedCapAsset(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() reply := AssetIDChangeAddr{} addrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) @@ -2428,7 +2404,6 @@ func TestCreateVariableCapAsset(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() reply := AssetIDChangeAddr{} minterAddrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) @@ -2516,7 +2491,6 @@ func TestNFTWorkflow(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() fromAddrs, fromAddrsStr := sampleAddrs(t, env.vm.AddressManager, addrs) @@ -2632,7 +2606,6 @@ func TestImportExportKey(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() sk, err := secp256k1.NewPrivateKey() require.NoError(err) @@ -2671,7 +2644,6 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() sk, err := secp256k1.NewPrivateKey() require.NoError(err) @@ -2717,7 +2689,6 @@ func TestSend(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2767,7 +2738,6 @@ func TestSendMultiple(t *testing.T) { }, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2819,7 +2789,6 @@ func TestCreateAndListAddresses(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() createArgs := &api.UserPass{ Username: username, @@ -2855,7 +2824,6 @@ func TestImport(t *testing.T) { }}, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr0 := keys[0].PublicKey().Address() diff --git a/vms/avm/state_test.go b/vms/avm/state_test.go index 57d4944a587..c9fdad13c99 100644 --- a/vms/avm/state_test.go +++ b/vms/avm/state_test.go @@ -34,7 +34,6 @@ func TestSetsAndGets(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -94,7 +93,6 @@ func TestFundingNoAddresses(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -124,7 +122,6 @@ func TestFundingAddresses(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ diff --git a/vms/avm/vm_benchmark_test.go b/vms/avm/vm_benchmark_test.go index 9e35d0f0ae0..e8f873eda2a 100644 --- a/vms/avm/vm_benchmark_test.go +++ b/vms/avm/vm_benchmark_test.go @@ -28,7 +28,6 @@ func BenchmarkLoadUser(b *testing.B) { password: password, }}, }) - env.vm.ctx.Lock.Unlock() user, err := keystore.NewUserFromKeystore(env.vm.ctx.Keystore, username, password) require.NoError(err) @@ -65,7 +64,6 @@ func getAllUTXOsBenchmark(b *testing.B, utxoCount int, randSrc rand.Source) { require := require.New(b) env := setup(b, &envConfig{fork: latest}) - env.vm.ctx.Lock.Unlock() addr := ids.GenerateTestShortID() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index de1933648ae..b87a9cdc4fe 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -19,7 +19,6 @@ func TestVerifyFxUsage(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: latest}) - env.vm.ctx.Lock.Unlock() var ( key = keys[0] diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 7c8516195b0..90162e37683 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -116,7 +116,6 @@ func TestIssueTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, "AVAX") issueAndAccept(require, env.vm, env.issuer, tx) @@ -129,7 +128,6 @@ func TestIssueNFT(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -207,7 +205,6 @@ func TestIssueProperty(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) - env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -293,7 +290,6 @@ func TestIssueTxWithFeeAsset(t *testing.T) { fork: latest, isCustomFeeAsset: true, }) - env.vm.ctx.Lock.Unlock() // send first asset tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, feeAssetName) @@ -307,7 +303,6 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { fork: latest, isCustomFeeAsset: true, }) - env.vm.ctx.Lock.Unlock() // send second asset var ( @@ -354,7 +349,6 @@ func TestVMFormat(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() tests := []struct { in ids.ShortID @@ -382,7 +376,6 @@ func TestTxAcceptAfterParseTx(t *testing.T) { fork: latest, notLinearized: true, }) - env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -457,7 +450,6 @@ func TestIssueImportTx(t *testing.T) { env := setup(t, &envConfig{ fork: durango, }) - env.vm.ctx.Lock.Unlock() peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) @@ -532,7 +524,6 @@ func TestForceAcceptImportTx(t *testing.T) { fork: durango, notLinearized: true, }) - env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() @@ -604,7 +595,6 @@ func TestIssueExportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -662,7 +652,6 @@ func TestClearForceAcceptedExportTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index 2b33e2e9f6b..ea906e631d4 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -34,8 +34,6 @@ func TestWalletService_SendMultiple(t *testing.T) { pendingTxs: linked.NewHashmap[ids.ID, *txs.Tx](), } - env.vm.ctx.Lock.Unlock() - assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() From 003fa79cc7a26a8674dc74bbdc9aeeba213fb424 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 11:42:35 -0400 Subject: [PATCH 40/53] cleanup --- vms/avm/environment_test.go | 3 +-- vms/avm/txs/txstest/backend.go | 24 ++++++++++++------------ vms/avm/txs/txstest/builder.go | 10 +++++++--- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 7ee61daf81c..42883094eaf 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -197,14 +197,13 @@ func setup(tb testing.TB, c *envConfig) *environment { stopVertexID := ids.GenerateTestID() issuer := make(chan common.Message, 1) - backend := txstest.NewBackend(vm.ctx, vm.state, vm.ctx.SharedMemory, vm.parser.Codec()) env := &environment{ genesisBytes: genesisBytes, genesisTx: getCreateTxFromGenesisTest(tb, genesisBytes, assetName), sharedMemory: m, issuer: issuer, vm: vm, - txBuilder: txstest.New(vm.ctx, &vm.Config, vm.feeAssetID, backend), + txBuilder: txstest.New(vm.parser.Codec(), vm.ctx, &vm.Config, vm.feeAssetID, vm.state), } require.NoError(vm.SetState(context.Background(), snow.Bootstrapping)) diff --git a/vms/avm/txs/txstest/backend.go b/vms/avm/txs/txstest/backend.go index 66a0c99d1fb..780f2a32f63 100644 --- a/vms/avm/txs/txstest/backend.go +++ b/vms/avm/txs/txstest/backend.go @@ -22,17 +22,17 @@ import ( const maxPageSize uint64 = 1024 var ( - _ builder.Backend = (*walletBackendAdapter)(nil) - _ signer.Backend = (*walletBackendAdapter)(nil) + _ builder.Backend = (*walletUTXOsAdapter)(nil) + _ signer.Backend = (*walletUTXOsAdapter)(nil) ) -func NewBackend( +func newBackend( ctx *snow.Context, state state.State, sharedMemory atomic.SharedMemory, codec codec.Manager, -) *Backend { - return &Backend{ +) *utxos { + return &utxos{ xchainID: ctx.XChainID, state: state, sharedMemory: sharedMemory, @@ -40,14 +40,14 @@ func NewBackend( } } -type Backend struct { +type utxos struct { xchainID ids.ID state state.State sharedMemory atomic.SharedMemory codec codec.Manager } -func (b *Backend) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { +func (b *utxos) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { if sourceChainID == b.xchainID { return avax.GetAllUTXOs(b.state, addrs) } @@ -64,7 +64,7 @@ func (b *Backend) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*av return atomicUTXOs, err } -func (b *Backend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { +func (b *utxos) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { if chainID == b.xchainID { return b.state.GetUTXO(utxoID) } @@ -89,15 +89,15 @@ func (b *Backend) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (* return nil, database.ErrNotFound } -type walletBackendAdapter struct { - b *Backend +type walletUTXOsAdapter struct { + b *utxos addrs set.Set[ids.ShortID] } -func (wa *walletBackendAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { +func (wa *walletUTXOsAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { return wa.b.UTXOs(wa.addrs, sourceChainID) } -func (wa *walletBackendAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { +func (wa *walletUTXOsAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { return wa.b.GetUTXO(wa.addrs, chainID, utxoID) } diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index ab01e63ba02..cc77bee5f09 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -7,9 +7,11 @@ import ( "context" "fmt" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/vms/avm/config" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -20,16 +22,18 @@ import ( ) type Builder struct { - backend *Backend + backend *utxos ctx *builder.Context } func New( + codec codec.Manager, ctx *snow.Context, cfg *config.Config, feeAssetID ids.ID, - backend *Backend, + state state.State, ) *Builder { + backend := newBackend(ctx, state, ctx.SharedMemory, codec) return &Builder{ backend: backend, ctx: newContext(ctx, cfg, feeAssetID), @@ -197,7 +201,7 @@ func (b *Builder) ExportTx( func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) { var ( addrs = kc.Addresses() - wa = &walletBackendAdapter{ + wa = &walletUTXOsAdapter{ b: b.backend, addrs: addrs, } From 8880e77bfc86825f963d7c2252f29efec1884649 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 11:44:46 -0400 Subject: [PATCH 41/53] nit --- vms/avm/txs/txstest/builder.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index cc77bee5f09..e7c382ab057 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -212,11 +212,11 @@ func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Si } func options(changeAddr ids.ShortID, memo []byte) []common.Option { - return common.UnionOptions( - []common.Option{common.WithChangeOwner(&secp256k1fx.OutputOwners{ + return []common.Option{ + common.WithChangeOwner(&secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{changeAddr}, - })}, - []common.Option{common.WithMemo(memo)}, - ) + }), + common.WithMemo(memo), + } } From 350725efadfa138e7637ec8eb5d1f3c7de011ef8 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 11:56:05 -0400 Subject: [PATCH 42/53] nit --- vms/avm/txs/txstest/builder.go | 43 +++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index e7c382ab057..c9ccbe43a66 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -54,7 +54,10 @@ func (b *Builder) CreateAssetTx( symbol, denomination, initialStates, - options(changeAddr, nil /*memo*/)..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), ) if err != nil { return nil, fmt.Errorf("failed building base tx: %w", err) @@ -73,7 +76,13 @@ func (b *Builder) BaseTx( utx, err := xBuilder.NewBaseTx( outs, - options(changeAddr, memo)..., + []common.Option{ + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), + common.WithMemo(memo), + }..., ) if err != nil { return nil, fmt.Errorf("failed building base tx: %w", err) @@ -95,7 +104,10 @@ func (b *Builder) MintNFT( assetID, payload, owners, - options(changeAddr, nil /*memo*/)..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), ) if err != nil { return nil, fmt.Errorf("failed minting NFTs: %w", err) @@ -113,7 +125,10 @@ func (b *Builder) MintFTs( utx, err := xBuilder.NewOperationTxMintFT( outputs, - options(changeAddr, nil /*memo*/)..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), ) if err != nil { return nil, fmt.Errorf("failed minting FTs: %w", err) @@ -131,7 +146,10 @@ func (b *Builder) Operation( utx, err := xBuilder.NewOperationTx( ops, - options(changeAddr, nil /*memo*/)..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), ) if err != nil { return nil, fmt.Errorf("failed building operation tx: %w", err) @@ -189,7 +207,10 @@ func (b *Builder) ExportTx( utx, err := xBuilder.NewExportTx( destinationChain, outputs, - options(changeAddr, nil /*memo*/)..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), ) if err != nil { return nil, fmt.Errorf("failed building export tx: %w", err) @@ -210,13 +231,3 @@ func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Si ) return builder, signer } - -func options(changeAddr ids.ShortID, memo []byte) []common.Option { - return []common.Option{ - common.WithChangeOwner(&secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }), - common.WithMemo(memo), - } -} From f73ea9d3b678223f95f117524e63657a9c248953 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 12:27:51 -0400 Subject: [PATCH 43/53] nits --- vms/avm/txs/txstest/backend.go | 8 ++++---- vms/avm/txs/txstest/builder.go | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/vms/avm/txs/txstest/backend.go b/vms/avm/txs/txstest/backend.go index 780f2a32f63..4c3cc8e1d18 100644 --- a/vms/avm/txs/txstest/backend.go +++ b/vms/avm/txs/txstest/backend.go @@ -94,10 +94,10 @@ type walletUTXOsAdapter struct { addrs set.Set[ids.ShortID] } -func (wa *walletUTXOsAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { - return wa.b.UTXOs(wa.addrs, sourceChainID) +func (w *walletUTXOsAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { + return w.b.UTXOs(w.addrs, sourceChainID) } -func (wa *walletUTXOsAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { - return wa.b.GetUTXO(wa.addrs, chainID, utxoID) +func (w *walletUTXOsAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { + return w.b.GetUTXO(w.addrs, chainID, utxoID) } diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index c9ccbe43a66..80330a43d92 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -22,8 +22,8 @@ import ( ) type Builder struct { - backend *utxos - ctx *builder.Context + utxos *utxos + ctx *builder.Context } func New( @@ -33,10 +33,10 @@ func New( feeAssetID ids.ID, state state.State, ) *Builder { - backend := newBackend(ctx, state, ctx.SharedMemory, codec) + utxos := newBackend(ctx, state, ctx.SharedMemory, codec) return &Builder{ - backend: backend, - ctx: newContext(ctx, cfg, feeAssetID), + utxos: utxos, + ctx: newContext(ctx, cfg, feeAssetID), } } @@ -204,15 +204,14 @@ func (b *Builder) ExportTx( }, }} - utx, err := xBuilder.NewExportTx( + if utx, err := xBuilder.NewExportTx( destinationChain, outputs, common.WithChangeOwner(&secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{changeAddr}, }), - ) - if err != nil { + ); err != nil { return nil, fmt.Errorf("failed building export tx: %w", err) } @@ -223,7 +222,7 @@ func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Si var ( addrs = kc.Addresses() wa = &walletUTXOsAdapter{ - b: b.backend, + b: b.utxos, addrs: addrs, } builder = builder.New(addrs, b.ctx, wa) From de87fd6c63727d3c7048d9f6b3da6751c08e6e86 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 12:30:35 -0400 Subject: [PATCH 44/53] some more nits --- vms/avm/txs/txstest/builder.go | 21 ++++++++++---------- vms/avm/txs/txstest/{backend.go => utxos.go} | 8 ++++---- 2 files changed, 14 insertions(+), 15 deletions(-) rename vms/avm/txs/txstest/{backend.go => utxos.go} (94%) diff --git a/vms/avm/txs/txstest/builder.go b/vms/avm/txs/txstest/builder.go index 80330a43d92..c52e56cdb5e 100644 --- a/vms/avm/txs/txstest/builder.go +++ b/vms/avm/txs/txstest/builder.go @@ -33,7 +33,7 @@ func New( feeAssetID ids.ID, state state.State, ) *Builder { - utxos := newBackend(ctx, state, ctx.SharedMemory, codec) + utxos := newUTXOs(ctx, state, ctx.SharedMemory, codec) return &Builder{ utxos: utxos, ctx: newContext(ctx, cfg, feeAssetID), @@ -76,13 +76,11 @@ func (b *Builder) BaseTx( utx, err := xBuilder.NewBaseTx( outs, - []common.Option{ - common.WithChangeOwner(&secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{changeAddr}, - }), - common.WithMemo(memo), - }..., + common.WithChangeOwner(&secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{changeAddr}, + }), + common.WithMemo(memo), ) if err != nil { return nil, fmt.Errorf("failed building base tx: %w", err) @@ -204,14 +202,15 @@ func (b *Builder) ExportTx( }, }} - if utx, err := xBuilder.NewExportTx( + utx, err := xBuilder.NewExportTx( destinationChain, outputs, common.WithChangeOwner(&secp256k1fx.OutputOwners{ Threshold: 1, Addrs: []ids.ShortID{changeAddr}, }), - ); err != nil { + ) + if err != nil { return nil, fmt.Errorf("failed building export tx: %w", err) } @@ -222,7 +221,7 @@ func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Si var ( addrs = kc.Addresses() wa = &walletUTXOsAdapter{ - b: b.utxos, + utxos: b.utxos, addrs: addrs, } builder = builder.New(addrs, b.ctx, wa) diff --git a/vms/avm/txs/txstest/backend.go b/vms/avm/txs/txstest/utxos.go similarity index 94% rename from vms/avm/txs/txstest/backend.go rename to vms/avm/txs/txstest/utxos.go index 4c3cc8e1d18..cc1a67e9ec6 100644 --- a/vms/avm/txs/txstest/backend.go +++ b/vms/avm/txs/txstest/utxos.go @@ -26,7 +26,7 @@ var ( _ signer.Backend = (*walletUTXOsAdapter)(nil) ) -func newBackend( +func newUTXOs( ctx *snow.Context, state state.State, sharedMemory atomic.SharedMemory, @@ -90,14 +90,14 @@ func (b *utxos) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*av } type walletUTXOsAdapter struct { - b *utxos + utxos *utxos addrs set.Set[ids.ShortID] } func (w *walletUTXOsAdapter) UTXOs(_ context.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) { - return w.b.UTXOs(w.addrs, sourceChainID) + return w.utxos.UTXOs(w.addrs, sourceChainID) } func (w *walletUTXOsAdapter) GetUTXO(_ context.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) { - return w.b.GetUTXO(w.addrs, chainID, utxoID) + return w.utxos.GetUTXO(w.addrs, chainID, utxoID) } From c0f0a3a1353571c17ad2f9a7f52bcaf3f00eebc6 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 12:39:00 -0400 Subject: [PATCH 45/53] reduced diff --- vms/avm/service_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 5fb5fe8d15d..bf4d690ac45 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -918,7 +918,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildNFTxMintOp(createAssetTx, key, 1, 1) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintNFTTx := buildOperationTxWithOps(t, env, op) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -1067,7 +1067,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { mintOp1 := buildNFTxMintOp(createAssetTx, key, 1, 0) mintOp2 := buildNFTxMintOp(createAssetTx, key, 2, 1) - mintNFTTx := buildOperationTxWithOp(t, env, []*txs.Operation{mintOp1, mintOp2}) + mintNFTTx := buildOperationTxWithOps(t, env, mintOp1, mintOp2) issueAndAccept(require, env.vm, env.issuer, mintNFTTx) reply := api.GetTxReply{} @@ -1246,7 +1246,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildSecpMintOp(createAssetTx, key, 1) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintSecpOpTx := buildOperationTxWithOps(t, env, op) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1397,7 +1397,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { op1 := buildSecpMintOp(createAssetTx, key, 1) op2 := buildSecpMintOp(createAssetTx, key, 2) - mintSecpOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) + mintSecpOpTx := buildOperationTxWithOps(t, env, op1, op2) issueAndAccept(require, env.vm, env.issuer, mintSecpOpTx) reply := api.GetTxReply{} @@ -1579,7 +1579,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { issueAndAccept(require, env.vm, env.issuer, createAssetTx) op := buildPropertyFxMintOp(createAssetTx, key, 1) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op}) + mintPropertyFxOpTx := buildOperationTxWithOps(t, env, op) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -1725,7 +1725,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) op1 := buildPropertyFxMintOp(createAssetTx, key, 1) op2 := buildPropertyFxMintOp(createAssetTx, key, 2) - mintPropertyFxOpTx := buildOperationTxWithOp(t, env, []*txs.Operation{op1, op2}) + mintPropertyFxOpTx := buildOperationTxWithOps(t, env, op1, op2) issueAndAccept(require, env.vm, env.issuer, mintPropertyFxOpTx) reply := api.GetTxReply{} @@ -2014,7 +2014,7 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd } } -func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation) *txs.Tx { +func buildOperationTxWithOps(t *testing.T, env *environment, op ...*txs.Operation) *txs.Tx { var ( key = keys[0] kc = secp256k1fx.NewKeychain() @@ -2022,7 +2022,7 @@ func buildOperationTxWithOp(t *testing.T, env *environment, ops []*txs.Operation kc.Add(key) tx, err := env.txBuilder.Operation( - ops, + op, kc, key.Address(), ) From 760fbf876dfc09d70567225eca155f0bbe3d7493 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 May 2024 12:45:39 -0400 Subject: [PATCH 46/53] nit --- vms/avm/txs/txstest/utxos.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vms/avm/txs/txstest/utxos.go b/vms/avm/txs/txstest/utxos.go index cc1a67e9ec6..4b27e2d59b6 100644 --- a/vms/avm/txs/txstest/utxos.go +++ b/vms/avm/txs/txstest/utxos.go @@ -47,14 +47,14 @@ type utxos struct { codec codec.Manager } -func (b *utxos) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { - if sourceChainID == b.xchainID { - return avax.GetAllUTXOs(b.state, addrs) +func (u *utxos) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax.UTXO, error) { + if sourceChainID == u.xchainID { + return avax.GetAllUTXOs(u.state, addrs) } atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( - b.sharedMemory, - b.codec, + u.sharedMemory, + u.codec, sourceChainID, addrs, ids.ShortEmpty, @@ -64,14 +64,14 @@ func (b *utxos) UTXOs(addrs set.Set[ids.ShortID], sourceChainID ids.ID) ([]*avax return atomicUTXOs, err } -func (b *utxos) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { - if chainID == b.xchainID { - return b.state.GetUTXO(utxoID) +func (u *utxos) GetUTXO(addrs set.Set[ids.ShortID], chainID, utxoID ids.ID) (*avax.UTXO, error) { + if chainID == u.xchainID { + return u.state.GetUTXO(utxoID) } atomicUTXOs, _, _, err := avax.GetAtomicUTXOs( - b.sharedMemory, - b.codec, + u.sharedMemory, + u.codec, chainID, addrs, ids.ShortEmpty, From 29f7af7560aa839bfdb22fd08d9d01d73fa64b1a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 27 May 2024 13:50:43 +0200 Subject: [PATCH 47/53] fixed UTs locking --- vms/avm/environment_test.go | 1 - vms/avm/index_test.go | 4 ++++ vms/avm/service_test.go | 30 ++++++++++++++++++++++++++++++ vms/avm/state_test.go | 3 +++ vms/avm/vm_benchmark_test.go | 2 ++ vms/avm/vm_regression_test.go | 1 + vms/avm/vm_test.go | 11 +++++++++++ vms/avm/wallet_service_test.go | 3 +-- 8 files changed, 52 insertions(+), 3 deletions(-) diff --git a/vms/avm/environment_test.go b/vms/avm/environment_test.go index 42883094eaf..d4375aa092d 100644 --- a/vms/avm/environment_test.go +++ b/vms/avm/environment_test.go @@ -218,7 +218,6 @@ func setup(tb testing.TB, c *envConfig) *environment { require.NoError(vm.SetState(context.Background(), snow.NormalOp)) - vm.ctx.Lock.Unlock() tb.Cleanup(func() { env.vm.ctx.Lock.Lock() defer env.vm.ctx.Lock.Unlock() diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 9f5c0a830aa..8f66fe25852 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,6 +28,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) + env.vm.ctx.Lock.Unlock() key := keys[0] addr := key.PublicKey().Address() @@ -61,6 +62,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) + env.vm.ctx.Lock.Unlock() addressTxMap := map[ids.ShortID]*txs.Tx{} txAssetID := avax.Asset{ID: env.genesisTx.ID()} @@ -98,6 +100,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) + env.vm.ctx.Lock.Unlock() addrs := make([]ids.ShortID, len(keys)) for i, key := range keys { @@ -130,6 +133,7 @@ func TestIndexer_Read(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) + env.vm.ctx.Lock.Unlock() // generate test address and asset IDs assetID := ids.GenerateTestID() diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index bf4d690ac45..371db64c4b0 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -51,6 +51,7 @@ func TestServiceIssueTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() txArgs := &api.FormattedTx{} txReply := &api.JSONTxID{} @@ -73,6 +74,7 @@ func TestServiceGetTxStatus(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() statusArgs := &api.JSONTxID{} statusReply := &GetTxStatusReply{} @@ -104,6 +106,7 @@ func TestServiceGetBalanceStrict(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -256,6 +259,8 @@ func TestServiceGetTxs(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() + var err error env.vm.addressTxsIndexer, err = index.NewIndexer(env.vm.db, env.vm.ctx.Log, "", prometheus.NewRegistry(), false) require.NoError(err) @@ -294,6 +299,7 @@ func TestServiceGetAllBalances(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -488,6 +494,7 @@ func TestServiceGetTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() txID := env.genesisTx.ID() @@ -512,6 +519,7 @@ func TestServiceGetTxJSON_BaseTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() newTx := newAvaxBaseTxWithOutputs(t, env) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -604,6 +612,7 @@ func TestServiceGetTxJSON_ExportTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() newTx := buildTestExportTx(t, env, env.vm.ctx.CChainID) issueAndAccept(require, env.vm, env.issuer, newTx) @@ -702,6 +711,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() initialStates := map[uint32][]verify.State{ uint32(0): { @@ -894,6 +904,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1040,6 +1051,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1225,6 +1237,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1372,6 +1385,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1563,6 +1577,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -1702,6 +1717,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() key := keys[0] initialStates := map[uint32][]verify.State{ @@ -2037,6 +2053,7 @@ func TestServiceGetNilTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{}, &reply) @@ -2050,6 +2067,7 @@ func TestServiceGetUnknownTx(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() reply := api.GetTxReply{} err := service.GetTx(nil, &api.GetTxArgs{TxID: ids.GenerateTestID()}, &reply) @@ -2061,6 +2079,7 @@ func TestServiceGetUTXOs(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() rawAddr := ids.GenerateTestShortID() rawEmptyAddr := ids.GenerateTestShortID() @@ -2312,6 +2331,7 @@ func TestGetAssetDescription(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() avaxAssetID := env.genesisTx.ID() @@ -2331,6 +2351,7 @@ func TestGetBalance(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() avaxAssetID := env.genesisTx.ID() @@ -2359,6 +2380,7 @@ func TestCreateFixedCapAsset(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() reply := AssetIDChangeAddr{} addrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) @@ -2404,6 +2426,7 @@ func TestCreateVariableCapAsset(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() reply := AssetIDChangeAddr{} minterAddrStr, err := env.vm.FormatLocalAddress(keys[0].PublicKey().Address()) @@ -2491,6 +2514,7 @@ func TestNFTWorkflow(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() fromAddrs, fromAddrsStr := sampleAddrs(t, env.vm.AddressManager, addrs) @@ -2606,6 +2630,7 @@ func TestImportExportKey(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() sk, err := secp256k1.NewPrivateKey() require.NoError(err) @@ -2644,6 +2669,7 @@ func TestImportAVMKeyNoDuplicates(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() sk, err := secp256k1.NewPrivateKey() require.NoError(err) @@ -2689,6 +2715,7 @@ func TestSend(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2738,6 +2765,7 @@ func TestSendMultiple(t *testing.T) { }, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr := keys[0].PublicKey().Address() @@ -2789,6 +2817,7 @@ func TestCreateAndListAddresses(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() createArgs := &api.UserPass{ Username: username, @@ -2824,6 +2853,7 @@ func TestImport(t *testing.T) { }}, }) service := &Service{vm: env.vm} + env.vm.ctx.Lock.Unlock() assetID := env.genesisTx.ID() addr0 := keys[0].PublicKey().Address() diff --git a/vms/avm/state_test.go b/vms/avm/state_test.go index c9fdad13c99..57d4944a587 100644 --- a/vms/avm/state_test.go +++ b/vms/avm/state_test.go @@ -34,6 +34,7 @@ func TestSetsAndGets(t *testing.T) { }, }}, }) + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -93,6 +94,7 @@ func TestFundingNoAddresses(t *testing.T) { }, }}, }) + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -122,6 +124,7 @@ func TestFundingAddresses(t *testing.T) { }, }}, }) + env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ diff --git a/vms/avm/vm_benchmark_test.go b/vms/avm/vm_benchmark_test.go index e8f873eda2a..9e35d0f0ae0 100644 --- a/vms/avm/vm_benchmark_test.go +++ b/vms/avm/vm_benchmark_test.go @@ -28,6 +28,7 @@ func BenchmarkLoadUser(b *testing.B) { password: password, }}, }) + env.vm.ctx.Lock.Unlock() user, err := keystore.NewUserFromKeystore(env.vm.ctx.Keystore, username, password) require.NoError(err) @@ -64,6 +65,7 @@ func getAllUTXOsBenchmark(b *testing.B, utxoCount int, randSrc rand.Source) { require := require.New(b) env := setup(b, &envConfig{fork: latest}) + env.vm.ctx.Lock.Unlock() addr := ids.GenerateTestShortID() diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index b87a9cdc4fe..de1933648ae 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -19,6 +19,7 @@ func TestVerifyFxUsage(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: latest}) + env.vm.ctx.Lock.Unlock() var ( key = keys[0] diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 90162e37683..7c8516195b0 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -116,6 +116,7 @@ func TestIssueTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + env.vm.ctx.Lock.Unlock() tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, "AVAX") issueAndAccept(require, env.vm, env.issuer, tx) @@ -128,6 +129,7 @@ func TestIssueNFT(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -205,6 +207,7 @@ func TestIssueProperty(t *testing.T) { Fx: &propertyfx.Fx{}, }}, }) + env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -290,6 +293,7 @@ func TestIssueTxWithFeeAsset(t *testing.T) { fork: latest, isCustomFeeAsset: true, }) + env.vm.ctx.Lock.Unlock() // send first asset tx := newTx(t, env.genesisBytes, env.vm.ctx.ChainID, env.vm.parser, feeAssetName) @@ -303,6 +307,7 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { fork: latest, isCustomFeeAsset: true, }) + env.vm.ctx.Lock.Unlock() // send second asset var ( @@ -349,6 +354,7 @@ func TestVMFormat(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + env.vm.ctx.Lock.Unlock() tests := []struct { in ids.ShortID @@ -376,6 +382,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { fork: latest, notLinearized: true, }) + env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -450,6 +457,7 @@ func TestIssueImportTx(t *testing.T) { env := setup(t, &envConfig{ fork: durango, }) + env.vm.ctx.Lock.Unlock() peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) @@ -524,6 +532,7 @@ func TestForceAcceptImportTx(t *testing.T) { fork: durango, notLinearized: true, }) + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() @@ -595,6 +604,7 @@ func TestIssueExportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -652,6 +662,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) + env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index ea906e631d4..16435d1c92d 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -28,6 +28,7 @@ func TestWalletService_SendMultiple(t *testing.T) { initialKeys: keys, }}, }) + env.vm.ctx.Lock.Unlock() walletService := &WalletService{ vm: env.vm, @@ -71,9 +72,7 @@ func TestWalletService_SendMultiple(t *testing.T) { buildAndAccept(require, env.vm, env.issuer, reply.TxID) - env.vm.ctx.Lock.Lock() _, err = env.vm.state.GetTx(reply.TxID) - env.vm.ctx.Lock.Unlock() require.NoError(err) }) } From fc07c85c282b2f248623b2d1a5b6017a906a0a0a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 27 May 2024 14:01:18 +0200 Subject: [PATCH 48/53] nit --- vms/avm/txs/txstest/utxos.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/avm/txs/txstest/utxos.go b/vms/avm/txs/txstest/utxos.go index 4b27e2d59b6..39b3b712905 100644 --- a/vms/avm/txs/txstest/utxos.go +++ b/vms/avm/txs/txstest/utxos.go @@ -33,7 +33,7 @@ func newUTXOs( codec codec.Manager, ) *utxos { return &utxos{ - xchainID: ctx.XChainID, + xchainID: ctx.ChainID, state: state, sharedMemory: sharedMemory, codec: codec, From 966e4729d08c0c83dceea1d0c5be8828c0c0299a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 27 May 2024 14:06:16 +0200 Subject: [PATCH 49/53] reduced diffs --- vms/avm/index_test.go | 23 +++++++++++++++++++---- vms/avm/service_test.go | 9 ++++++--- vms/avm/state_test.go | 6 +++--- vms/avm/vm_benchmark_test.go | 4 ++-- vms/avm/vm_test.go | 25 +++++++++++++++++++------ vms/avm/wallet_service_test.go | 2 ++ 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/vms/avm/index_test.go b/vms/avm/index_test.go index 8f66fe25852..3d8614d5ee6 100644 --- a/vms/avm/index_test.go +++ b/vms/avm/index_test.go @@ -28,7 +28,7 @@ func TestIndexTransaction_Ordered(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() key := keys[0] addr := key.PublicKey().Address() @@ -47,7 +47,12 @@ func TestIndexTransaction_Ordered(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addr) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + env.vm.ctx.Lock.Unlock() + issueAndAccept(require, env.vm, env.issuer, tx) + + env.vm.ctx.Lock.Lock() + txs = append(txs, tx) } @@ -62,7 +67,7 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() addressTxMap := map[ids.ShortID]*txs.Tx{} txAssetID := avax.Asset{ID: env.genesisTx.ID()} @@ -81,8 +86,13 @@ func TestIndexTransaction_MultipleTransactions(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addr) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + env.vm.ctx.Lock.Unlock() + // issue transaction issueAndAccept(require, env.vm, env.issuer, tx) + + env.vm.ctx.Lock.Lock() + addressTxMap[addr] = tx } @@ -100,7 +110,7 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() addrs := make([]ids.ShortID, len(keys)) for i, key := range keys { @@ -124,7 +134,12 @@ func TestIndexTransaction_MultipleAddresses(t *testing.T) { tx := buildTX(env.vm.ctx.XChainID, utxoID, txAssetID, addrs...) require.NoError(tx.SignSECP256K1Fx(env.vm.parser.Codec(), [][]*secp256k1.PrivateKey{{key}})) + env.vm.ctx.Lock.Unlock() + issueAndAccept(require, env.vm, env.issuer, tx) + + env.vm.ctx.Lock.Lock() + assertIndexedTX(t, env.vm.db, 0, addr, txAssetID.ID, tx.ID()) assertLatestIdx(t, env.vm.db, addr, txAssetID.ID, 1) } @@ -133,7 +148,7 @@ func TestIndexer_Read(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() // generate test address and asset IDs assetID := ids.GenerateTestID() diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 371db64c4b0..dc99dd383fc 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -106,7 +106,6 @@ func TestServiceGetBalanceStrict(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -133,6 +132,8 @@ func TestServiceGetBalanceStrict(t *testing.T) { env.vm.state.AddUTXO(twoOfTwoUTXO) require.NoError(env.vm.state.Commit()) + env.vm.ctx.Lock.Unlock() + // Check the balance with IncludePartial set to true balanceArgs := &GetBalanceArgs{ Address: addrStr, @@ -259,7 +260,6 @@ func TestServiceGetTxs(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() var err error env.vm.addressTxsIndexer, err = index.NewIndexer(env.vm.db, env.vm.ctx.Log, "", prometheus.NewRegistry(), false) @@ -273,6 +273,8 @@ func TestServiceGetTxs(t *testing.T) { testTxCount := 25 testTxs := initTestTxIndex(t, env.vm.db, addr, assetID, testTxCount) + env.vm.ctx.Lock.Unlock() + // get the first page getTxsArgs := &GetAddressTxsArgs{ PageSize: 10, @@ -299,7 +301,6 @@ func TestServiceGetAllBalances(t *testing.T) { fork: latest, }) service := &Service{vm: env.vm} - env.vm.ctx.Lock.Unlock() assetID := ids.GenerateTestID() addr := ids.GenerateTestShortID() @@ -325,6 +326,8 @@ func TestServiceGetAllBalances(t *testing.T) { env.vm.state.AddUTXO(twoOfTwoUTXO) require.NoError(env.vm.state.Commit()) + env.vm.ctx.Lock.Unlock() + // Check the balance with IncludePartial set to true balanceArgs := &GetAllBalancesArgs{ JSONAddress: api.JSONAddress{Address: addrStr}, diff --git a/vms/avm/state_test.go b/vms/avm/state_test.go index 57d4944a587..35744fdc63e 100644 --- a/vms/avm/state_test.go +++ b/vms/avm/state_test.go @@ -34,7 +34,7 @@ func TestSetsAndGets(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -94,7 +94,7 @@ func TestFundingNoAddresses(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ @@ -124,7 +124,7 @@ func TestFundingAddresses(t *testing.T) { }, }}, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() utxo := &avax.UTXO{ UTXOID: avax.UTXOID{ diff --git a/vms/avm/vm_benchmark_test.go b/vms/avm/vm_benchmark_test.go index 9e35d0f0ae0..096ed51e13b 100644 --- a/vms/avm/vm_benchmark_test.go +++ b/vms/avm/vm_benchmark_test.go @@ -28,7 +28,7 @@ func BenchmarkLoadUser(b *testing.B) { password: password, }}, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() user, err := keystore.NewUserFromKeystore(env.vm.ctx.Keystore, username, password) require.NoError(err) @@ -65,7 +65,7 @@ func getAllUTXOsBenchmark(b *testing.B, utxoCount int, randSrc rand.Source) { require := require.New(b) env := setup(b, &envConfig{fork: latest}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() addr := ids.GenerateTestShortID() diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 7c8516195b0..1c646d37166 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -354,7 +354,7 @@ func TestVMFormat(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() tests := []struct { in ids.ShortID @@ -382,7 +382,7 @@ func TestTxAcceptAfterParseTx(t *testing.T) { fork: latest, notLinearized: true, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() var ( key = keys[0] @@ -457,7 +457,7 @@ func TestIssueImportTx(t *testing.T) { env := setup(t, &envConfig{ fork: durango, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() peerSharedMemory := env.sharedMemory.NewSharedMemory(constants.PlatformChainID) @@ -515,7 +515,12 @@ func TestIssueImportTx(t *testing.T) { ) require.NoError(err) + env.vm.ctx.Lock.Unlock() + issueAndAccept(require, env.vm, env.issuer, tx) + + env.vm.ctx.Lock.Lock() + assertIndexedTX(t, env.vm.db, 0, key.PublicKey().Address(), txAssetID.AssetID(), tx.ID()) assertLatestIdx(t, env.vm.db, key.PublicKey().Address(), avaxID, 1) @@ -532,7 +537,7 @@ func TestForceAcceptImportTx(t *testing.T) { fork: durango, notLinearized: true, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") avaxID := genesisTx.ID() @@ -604,7 +609,7 @@ func TestIssueExportTx(t *testing.T) { require := require.New(t) env := setup(t, &envConfig{fork: durango}) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -641,8 +646,12 @@ func TestIssueExportTx(t *testing.T) { require.NoError(err) require.Empty(utxoBytes) + env.vm.ctx.Lock.Unlock() + issueAndAccept(require, env.vm, env.issuer, tx) + env.vm.ctx.Lock.Lock() + utxoBytes, _, _, err = peerSharedMemory.Indexed( env.vm.ctx.ChainID, [][]byte{ @@ -662,7 +671,7 @@ func TestClearForceAcceptedExportTx(t *testing.T) { env := setup(t, &envConfig{ fork: latest, }) - env.vm.ctx.Lock.Unlock() + defer env.vm.ctx.Lock.Unlock() genesisTx := getCreateTxFromGenesisTest(t, env.genesisBytes, "AVAX") @@ -703,8 +712,12 @@ func TestClearForceAcceptedExportTx(t *testing.T) { _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) + env.vm.ctx.Lock.Unlock() + issueAndAccept(require, env.vm, env.issuer, tx) + env.vm.ctx.Lock.Lock() + _, err = peerSharedMemory.Get(env.vm.ctx.ChainID, [][]byte{utxoID[:]}) require.ErrorIs(err, database.ErrNotFound) diff --git a/vms/avm/wallet_service_test.go b/vms/avm/wallet_service_test.go index 16435d1c92d..d4423bd31c7 100644 --- a/vms/avm/wallet_service_test.go +++ b/vms/avm/wallet_service_test.go @@ -72,7 +72,9 @@ func TestWalletService_SendMultiple(t *testing.T) { buildAndAccept(require, env.vm, env.issuer, reply.TxID) + env.vm.ctx.Lock.Lock() _, err = env.vm.state.GetTx(reply.TxID) + env.vm.ctx.Lock.Unlock() require.NoError(err) }) } From 1d1769000b609841e6b074a5299878bc5ef06dbf Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 29 May 2024 12:50:41 +0200 Subject: [PATCH 50/53] nit --- vms/avm/service_test.go | 12 ++++-------- vms/avm/vm_regression_test.go | 3 +-- vms/avm/vm_test.go | 23 +++++++---------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index dc99dd383fc..51b291520c8 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -1898,9 +1898,8 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { memo = []byte{1, 2, 3, 4, 5, 6, 7, 8} key = keys[0] changeKey = keys[1] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) tx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{{ @@ -1924,9 +1923,8 @@ func newAvaxBaseTxWithOutputs(t *testing.T, env *environment) *txs.Tx { func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStates map[uint32][]verify.State) *txs.Tx { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) tx, err := env.txBuilder.CreateAssetTx( "Team Rocket", // name @@ -1943,10 +1941,9 @@ func newAvaxCreateAssetTxWithOutputs(t *testing.T, env *environment, initialStat func buildTestExportTx(t *testing.T, env *environment, chainID ids.ID) *txs.Tx { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) to = key.PublicKey().Address() ) - kc.Add(key) tx, err := env.txBuilder.ExportTx( chainID, @@ -2036,9 +2033,8 @@ func buildSecpMintOp(createAssetTx *txs.Tx, key *secp256k1.PrivateKey, outputInd func buildOperationTxWithOps(t *testing.T, env *environment, op ...*txs.Operation) *txs.Tx { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) tx, err := env.txBuilder.Operation( op, diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index de1933648ae..fac1abdae42 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -23,9 +23,8 @@ func TestVerifyFxUsage(t *testing.T) { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) initialStates := map[uint32][]verify.State{ uint32(0): { diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index 1c646d37166..da8e93c54d0 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -133,9 +133,8 @@ func TestIssueNFT(t *testing.T) { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) // Create the asset initialStates := map[uint32][]verify.State{ @@ -211,9 +210,8 @@ func TestIssueProperty(t *testing.T) { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) // create the asset initialStates := map[uint32][]verify.State{ @@ -312,12 +310,11 @@ func TestIssueTxWithAnotherAsset(t *testing.T) { // send second asset var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) feeAssetCreateTx = getCreateTxFromGenesisTest(t, env.genesisBytes, feeAssetName) createTx = getCreateTxFromGenesisTest(t, env.genesisBytes, otherAssetName) ) - kc.Add(key) tx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{ @@ -386,9 +383,8 @@ func TestTxAcceptAfterParseTx(t *testing.T) { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) ) - kc.Add(key) firstTx, err := env.txBuilder.BaseTx( []*avax.TransferableOutput{{ @@ -466,7 +462,7 @@ func TestIssueImportTx(t *testing.T) { var ( key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) utxoID = avax.UTXOID{ TxID: ids.ID{ @@ -489,7 +485,6 @@ func TestIssueImportTx(t *testing.T) { }, } ) - kc.Add(key) // Provide the platform UTXO: utxoBytes, err := env.vm.parser.Codec().Marshal(txs.CodecVersion, importedUtxo) @@ -616,13 +611,11 @@ func TestIssueExportTx(t *testing.T) { var ( avaxID = genesisTx.ID() key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) to = key.PublicKey().Address() changeAddr = to ) - kc.Add(key) - tx, err := env.txBuilder.ExportTx( constants.PlatformChainID, to, // to @@ -679,13 +672,11 @@ func TestClearForceAcceptedExportTx(t *testing.T) { avaxID = genesisTx.ID() assetID = avax.Asset{ID: avaxID} key = keys[0] - kc = secp256k1fx.NewKeychain() + kc = secp256k1fx.NewKeychain(key) to = key.PublicKey().Address() changeAddr = to ) - kc.Add(key) - tx, err := env.txBuilder.ExportTx( constants.PlatformChainID, to, // to From aab2739854e5d8c5bca40620d644cb71fe89460d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 10 Jun 2024 10:02:45 +0200 Subject: [PATCH 51/53] refactored placeholder_signature --- vms/avm/service_test.go | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 51b291520c8..84d71a6423d 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -882,7 +882,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0xbbdff720789320b7f2b47e230ba8eb2e4b72c7eea52afe4ea1ae2e78ab1b611a318d21160a83bbd5a147848b909ad3859b0b1110e2401fa1c958d42dd6800ed501" + "PLACEHOLDER_SIGNATURE" ] } } @@ -893,6 +893,11 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_TX_ID", createAssetTx.ID().String(), 1) expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_BLOCKCHAIN_ID", createAssetTx.Unsigned.(*txs.CreateAssetTx).BlockchainID.String(), 1) + sigStr, err := formatting.Encode(formatting.HexNC, createAssetTx.Creds[0].Credential.(*secp256k1fx.Credential).Sigs[0][:]) + require.NoError(err) + + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) + require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1015,7 +1020,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" + "PLACEHOLDER_SIGNATURE" ] } }, @@ -1023,7 +1028,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "0x9e9b81e54fa10c25d772a5efaa2bda3173a2cf59b74ed4d022f08cf2bed1506c2384300827e3a0a3af39dc7b827157d55699a07d559f189890555b0272794afd00" + "PLACEHOLDER_SIGNATURE" ] } } @@ -1038,7 +1043,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1201,7 +1206,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { "fxID": "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT", "credential": { "signatures": [ - "0xc958811e7430677ed15c40ac1d7f6232e8f5060aecf4cd8c45ef1614d9c9a5be5b5d5e697da4e40c743c010bab7bca58d9970b1cc5f3dc15b2f6d9adc712289f00" + "PLACEHOLDER_SIGNATURE" ] } }, @@ -1224,7 +1229,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { sigStr, err := formatting.Encode(formatting.HexNC, mintNFTTx.Creds[1].Credential.(*nftfx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 3) require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1357,7 +1362,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0xad7f3f3cd2667eda64e6f9ca3ab0db21238c20a0174f590b5d9fdf69fa009d073b50d7e0db156cb3678c23509cb7adf767fc98119a683560950a1e8f3299d17800" + "PLACEHOLDER_SIGNATURE" ] } } @@ -1372,7 +1377,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { sigStr, err := formatting.Encode(formatting.HexNC, mintSecpOpTx.Creds[0].Credential.(*secp256k1fx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1549,7 +1554,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0xeada420035b6ad5e658e96abab39622c5aa730bda266374af4ddb264696fa998584823d34f7df3a5cb03c5cec3068365ece9a5b7242193a862e9e0459a8865b801" + "PLACEHOLDER_SIGNATURE" ] } } @@ -1564,7 +1569,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { sigStr, err := formatting.Encode(formatting.HexNC, mintSecpOpTx.Creds[0].Credential.(*secp256k1fx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 3) require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1681,7 +1686,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0xa5c7a3fac9f87479fafc347510e270e86da9e99ad606f31342baf1440674b1b53ea836b9a1cfee11eb85b96e1b8e547e2206758d3e902d9e14f6dd784172363401" + "PLACEHOLDER_SIGNATURE" ] } }, @@ -1704,7 +1709,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 1) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) require.Equal(expectedReplyTxString, string(replyTxBytes)) } @@ -1857,7 +1862,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ - "0xbf14b82775f2b260d77d4d790b0873e8cdb243e20bc95ca65bd08645f70845bd662ec4437b6599b0e4f86ad3d68ddfcd058bf0c729054aad609a26ba539b3b3300" + "PLACEHOLDER_SIGNATURE" ] } }, @@ -1888,7 +1893,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) sigStr, err := formatting.Encode(formatting.HexNC, mintPropertyFxOpTx.Creds[1].Credential.(*propertyfx.Credential).Sigs[0][:]) require.NoError(err) - expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 2) + expectedReplyTxString = strings.Replace(expectedReplyTxString, "PLACEHOLDER_SIGNATURE", sigStr, 3) require.Equal(expectedReplyTxString, string(replyTxBytes)) } From c5ea3e13fbffa148ef01ce56b688cd6ac924305b Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 10 Jun 2024 16:28:45 +0200 Subject: [PATCH 52/53] nit --- vms/avm/service_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 84d71a6423d..8ff92da64f5 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -717,7 +717,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { env.vm.ctx.Lock.Unlock() initialStates := map[uint32][]verify.State{ - uint32(0): { + 0: { &nftfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -730,7 +730,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { }, }, }, - uint32(1): { + 1: { &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ @@ -916,7 +916,7 @@ func TestServiceGetTxJSON_OperationTxWithNftxMintOp(t *testing.T) { key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(1): { + 1: { &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ @@ -1063,7 +1063,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(0): { + 0: { &nftfx.MintOutput{ GroupID: 0, OutputOwners: secp256k1fx.OutputOwners{ @@ -1072,7 +1072,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleNftxMintOp(t *testing.T) { }, }, }, - uint32(1): { + 1: { &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ @@ -1397,7 +1397,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(0): { + 0: { &secp256k1fx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -1405,7 +1405,7 @@ func TestServiceGetTxJSON_OperationTxWithMultipleSecpMintOp(t *testing.T) { }, }, }, - uint32(1): { + 1: { &secp256k1fx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, From cbe35fa057e3cc89997fae7cb1d2ce9602075a6c Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 10 Jun 2024 16:42:32 +0200 Subject: [PATCH 53/53] some more cleanup --- vms/avm/service_test.go | 8 ++++---- vms/avm/vm_regression_test.go | 4 ++-- vms/avm/vm_test.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 8ff92da64f5..d9dbb8db6f1 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -746,7 +746,7 @@ func TestServiceGetTxJSON_CreateAssetTx(t *testing.T) { }, }, }, - uint32(2): { + 2: { &propertyfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -1249,7 +1249,7 @@ func TestServiceGetTxJSON_OperationTxWithSecpMintOp(t *testing.T) { key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(0): { + 0: { &nftfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -1589,7 +1589,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOp(t *testing.T) { key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(2): { + 2: { &propertyfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, @@ -1729,7 +1729,7 @@ func TestServiceGetTxJSON_OperationTxWithPropertyFxMintOpMultiple(t *testing.T) key := keys[0] initialStates := map[uint32][]verify.State{ - uint32(2): { + 2: { &propertyfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1, diff --git a/vms/avm/vm_regression_test.go b/vms/avm/vm_regression_test.go index fac1abdae42..9e684e756d5 100644 --- a/vms/avm/vm_regression_test.go +++ b/vms/avm/vm_regression_test.go @@ -27,7 +27,7 @@ func TestVerifyFxUsage(t *testing.T) { ) initialStates := map[uint32][]verify.State{ - uint32(0): { + 0: { &secp256k1fx.TransferOutput{ Amt: 1, OutputOwners: secp256k1fx.OutputOwners{ @@ -36,7 +36,7 @@ func TestVerifyFxUsage(t *testing.T) { }, }, }, - uint32(1): { + 1: { &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ diff --git a/vms/avm/vm_test.go b/vms/avm/vm_test.go index da8e93c54d0..33af48c483f 100644 --- a/vms/avm/vm_test.go +++ b/vms/avm/vm_test.go @@ -138,7 +138,7 @@ func TestIssueNFT(t *testing.T) { // Create the asset initialStates := map[uint32][]verify.State{ - uint32(1): { + 1: { &nftfx.MintOutput{ GroupID: 1, OutputOwners: secp256k1fx.OutputOwners{ @@ -215,7 +215,7 @@ func TestIssueProperty(t *testing.T) { // create the asset initialStates := map[uint32][]verify.State{ - uint32(2): { + 2: { &propertyfx.MintOutput{ OutputOwners: secp256k1fx.OutputOwners{ Threshold: 1,