From 4cfa22567d0ebd7185ab11a1248e7c93092057c6 Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 10:16:06 +0100 Subject: [PATCH 1/8] Remove ugly workaround --- pkg/tests/accounts_test.go | 31 +++++++++++++++---------------- pkg/testsuite/testsuite.go | 5 +++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index ca33f6ab1..7f2537cf2 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -19,22 +19,7 @@ import ( func Test_TransitionAndDestroyAccount(t *testing.T) { oldGenesisOutputKey := utils.RandBlockIssuerKey() - // TODO: remove this ugly workaround - dummyParameters := iotago.NewV3ProtocolParameters(testsuite.DefaultProtocolParameterOptions("dummy")...) - - ts := testsuite.NewTestSuite(t, testsuite.WithAccounts(snapshotcreator.AccountDetails{ - // Nil address will be replaced with the address generated from genesis seed. - Address: nil, - // Set an amount enough to cover storage deposit and more issuer keys. - Amount: mock.MinIssuerAccountAmount(dummyParameters) * 10, - Mana: 0, - // AccountID is derived from this field, so this must be set uniquely for each account. - IssuerKey: oldGenesisOutputKey, - // Expiry Slot is the slot index at which the account expires. - ExpirySlot: iotago.MaxSlotIndex, - // BlockIssuanceCredits on this account is custom because it never needs to issue. - BlockIssuanceCredits: iotago.BlockIssuanceCredits(123), - }), + ts := testsuite.NewTestSuite(t, testsuite.WithProtocolParametersOptions( iotago.WithTimeProviderOptions( 0, @@ -53,6 +38,20 @@ func Test_TransitionAndDestroyAccount(t *testing.T) { ) defer ts.Shutdown() + ts.AddGenesisAccount(snapshotcreator.AccountDetails{ + // Nil address will be replaced with the address generated from genesis seed. + Address: nil, + // Set an amount enough to cover storage deposit and more issuer keys. + Amount: mock.MinIssuerAccountAmount(ts.API.ProtocolParameters()) * 10, + Mana: 0, + // AccountID is derived from this field, so this must be set uniquely for each account. + IssuerKey: oldGenesisOutputKey, + // Expiry Slot is the slot index at which the account expires. + ExpirySlot: iotago.MaxSlotIndex, + // BlockIssuanceCredits on this account is custom because it never needs to issue. + BlockIssuanceCredits: iotago.BlockIssuanceCredits(123), + }) + // Add a validator node to the network. This will add a validator account to the snapshot. node1 := ts.AddValidatorNode("node1") // Add a non-validator node to the network. This will not add any accounts to the snapshot. diff --git a/pkg/testsuite/testsuite.go b/pkg/testsuite/testsuite.go index fdb5b62a5..02b13d441 100644 --- a/pkg/testsuite/testsuite.go +++ b/pkg/testsuite/testsuite.go @@ -382,6 +382,11 @@ func (t *TestSuite) RemoveNode(name string) { t.nodes.Delete(name) } +// AddGenesisAccount adds an account the test suite in the genesis snapshot. +func (t *TestSuite) AddGenesisAccount(accountDetails snapshotcreator.AccountDetails) { + t.optsAccounts = append(t.optsAccounts, accountDetails) +} + // AddGenesisWallet adds a wallet to the test suite with a block issuer in the genesis snapshot and access to the genesis seed. // If no block issuance credits are provided, the wallet will be assigned half of the maximum block issuance credits. func (t *TestSuite) AddGenesisWallet(name string, node *mock.Node, blockIssuanceCredits ...iotago.BlockIssuanceCredits) *mock.Wallet { From a385690f0206f3f8b2801fc07ae84652ad3f4d0a Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 10:51:19 +0100 Subject: [PATCH 2/8] Simplify and fix test by removing magic number --- pkg/tests/accounts_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index 7f2537cf2..7bc683707 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -220,16 +220,16 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { // set the expiry slot of the transitioned genesis account to the latest committed + MaxCommittableAge newAccountExpirySlot := node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() + ts.API.ProtocolParameters().MaxCommittableAge() + validatorAccountAmount := mock.MinValidatorAccountAmount(ts.API.ProtocolParameters()) + var block1Slot iotago.SlotIndex = 1 tx1 := ts.DefaultWallet().CreateAccountFromInput( "TX1", "Genesis:0", ts.DefaultWallet(), mock.WithBlockIssuerFeature(iotago.BlockIssuerKeys{newAccountBlockIssuerKey}, newAccountExpirySlot), - mock.WithStakingFeature(10000, 421, 0, 10), - // TODO: Temporary "fix" for the tests, lets fix this in another PR, so we can at least use the docker network again - //mock.WithAccountAmount(mock.MinIssuerAccountAmount(ts.API.ProtocolParameters())), - mock.WithAccountAmount(mock.MinValidatorAccountAmount(ts.API.ProtocolParameters())), + mock.WithStakingFeature(validatorAccountAmount, 421, 0, 10), // match amount and staked amount to simplify the tests + mock.WithAccountAmount(validatorAccountAmount), ) genesisCommitment := iotago.NewEmptyCommitment(ts.API) @@ -250,7 +250,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { PreviousOutputID: iotago.EmptyOutputID, BlockIssuerKeysAdded: iotago.NewBlockIssuerKeys(newAccountBlockIssuerKey), BlockIssuerKeysRemoved: iotago.NewBlockIssuerKeys(), - ValidatorStakeChange: 10000, + ValidatorStakeChange: int64(validatorAccountAmount), StakeEndEpochChange: 10, FixedCostChange: 421, DelegationStakeChange: 0, @@ -265,7 +265,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: 0, - ValidatorStake: 10000, + ValidatorStake: validatorAccountAmount, }, ts.Nodes()...) // CREATE DELEGATION TO NEW ACCOUNT FROM BASIC UTXO @@ -304,7 +304,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: iotago.BaseToken(delegatedAmount), - ValidatorStake: 10000, + ValidatorStake: validatorAccountAmount, }, ts.Nodes()...) // transition a delegation output to a delayed claiming state @@ -337,7 +337,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: iotago.BaseToken(0), - ValidatorStake: 10000, + ValidatorStake: validatorAccountAmount, }, ts.Nodes()...) } From 58c27acab6bd4404ce0a195ad4b83bcb4973d142 Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 11:06:57 +0100 Subject: [PATCH 3/8] Add WalletOptions to the testsuite --- pkg/tests/accounts_test.go | 21 +++--- pkg/tests/committee_rotation_test.go | 12 ++-- pkg/tests/protocol_engine_switching_test.go | 2 +- pkg/tests/protocol_startup_test.go | 2 +- pkg/tests/upgrade_signaling_test.go | 2 +- pkg/testsuite/testsuite.go | 78 ++++++++++++--------- 6 files changed, 66 insertions(+), 51 deletions(-) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index 7bc683707..9bb8cf0fe 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -57,7 +57,7 @@ func Test_TransitionAndDestroyAccount(t *testing.T) { // Add a non-validator node to the network. This will not add any accounts to the snapshot. _ = ts.AddNode("node2") // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - wallet := ts.AddDefaultWallet(node1, iotago.MaxBlockIssuanceCredits/2) + wallet := ts.AddDefaultWallet(node1) ts.Run(true) @@ -188,7 +188,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { // Add a non-validator node to the network. This will not add any accounts to the snapshot. _ = ts.AddNode("node2") // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - wallet := ts.AddDefaultWallet(node1, iotago.MaxBlockIssuanceCredits/2) + wallet := ts.AddDefaultWallet(node1) ts.Run(true) @@ -366,7 +366,7 @@ func Test_ImplicitAccounts(t *testing.T) { // Add a non-validator node to the network. This will not add any accounts to the snapshot. _ = ts.AddNode("node2") // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - wallet := ts.AddDefaultWallet(node1, iotago.MaxBlockIssuanceCredits/2) + wallet := ts.AddDefaultWallet(node1) ts.Run(true) @@ -496,8 +496,8 @@ func Test_NegativeBIC_BlockIssuerLocked(t *testing.T) { wallet1BIC := iotago.BlockIssuanceCredits(100000) wallet2BIC := iotago.BlockIssuanceCredits(0) - wallet1 := ts.AddGenesisWallet("wallet 1", node2, wallet1BIC) - wallet2 := ts.AddGenesisWallet("wallet 2", node2, wallet2BIC) + wallet1 := ts.AddGenesisWallet("wallet 1", node2, testsuite.WithWalletBlockIssuanceCredits(wallet1BIC)) + wallet2 := ts.AddGenesisWallet("wallet 2", node2, testsuite.WithWalletBlockIssuanceCredits(wallet2BIC)) ts.Run(false) @@ -693,9 +693,11 @@ func Test_NegativeBIC_AccountOutput(t *testing.T) { wallet1BIC := iotago.BlockIssuanceCredits(-1) wallet2BIC := iotago.MaxBlockIssuanceCredits / 2 + // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - wallet1 := ts.AddGenesisWallet("wallet 1", node1, wallet1BIC) - wallet2 := ts.AddGenesisWallet("wallet 2", node1, wallet2BIC) + // TODO: calculate the correct amount + wallet1 := ts.AddGenesisWallet("wallet 1", node1, testsuite.WithWalletAmount(5000000), testsuite.WithWalletBlockIssuanceCredits(wallet1BIC)) + wallet2 := ts.AddGenesisWallet("wallet 2", node1, testsuite.WithWalletBlockIssuanceCredits(wallet2BIC)) ts.Run(true) @@ -741,7 +743,6 @@ func Test_NegativeBIC_AccountOutput(t *testing.T) { newExpirySlot := block1Slot + ts.API.ProtocolParameters().MaxCommittableAge() { // Prepare a transaction that will try to spend an AccountOutput of a locked account. - // BUG: How can we add a block issuer feature here with only minimum funds? tx1 := wallet1.TransitionAccount( "TX1", "Genesis:2", @@ -915,8 +916,8 @@ func Test_NegativeBIC_AccountOwnedBasicOutputLocked(t *testing.T) { wallet1BIC := iotago.BlockIssuanceCredits(-1) wallet2BIC := iotago.MaxBlockIssuanceCredits / 2 // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - wallet1 := ts.AddGenesisWallet("wallet 1", node1, wallet1BIC) - wallet2 := ts.AddGenesisWallet("wallet 2", node1, wallet2BIC) + wallet1 := ts.AddGenesisWallet("wallet 1", node1, testsuite.WithWalletBlockIssuanceCredits(wallet1BIC)) + wallet2 := ts.AddGenesisWallet("wallet 2", node1, testsuite.WithWalletBlockIssuanceCredits(wallet2BIC)) ts.Run(true) diff --git a/pkg/tests/committee_rotation_test.go b/pkg/tests/committee_rotation_test.go index 50f3cbc34..e8bd33b50 100644 --- a/pkg/tests/committee_rotation_test.go +++ b/pkg/tests/committee_rotation_test.go @@ -34,12 +34,12 @@ func Test_TopStakersRotation(t *testing.T) { ) defer ts.Shutdown() - node1 := ts.AddValidatorNode("node1", 1_000_006) - ts.AddValidatorNode("node2", 1_000_005) - ts.AddValidatorNode("node3", 1_000_004) - ts.AddValidatorNode("node4", 1_000_003) - ts.AddValidatorNode("node5", 1_000_002) - ts.AddValidatorNode("node6", 1_000_001) + node1 := ts.AddValidatorNode("node1", testsuite.WithWalletAmount(1_000_006)) + ts.AddValidatorNode("node2", testsuite.WithWalletAmount(1_000_005)) + ts.AddValidatorNode("node3", testsuite.WithWalletAmount(1_000_004)) + ts.AddValidatorNode("node4", testsuite.WithWalletAmount(1_000_003)) + ts.AddValidatorNode("node5", testsuite.WithWalletAmount(1_000_002)) + ts.AddValidatorNode("node6", testsuite.WithWalletAmount(1_000_001)) ts.AddDefaultWallet(node1) ts.AddNode("node7") diff --git a/pkg/tests/protocol_engine_switching_test.go b/pkg/tests/protocol_engine_switching_test.go index 506dbcd93..45cd86079 100644 --- a/pkg/tests/protocol_engine_switching_test.go +++ b/pkg/tests/protocol_engine_switching_test.go @@ -57,7 +57,7 @@ func TestProtocol_EngineSwitching(t *testing.T) { node6 := ts.AddValidatorNode("node6") node7 := ts.AddValidatorNode("node7") node8 := ts.AddNode("node8") - ts.AddDefaultWallet(node0, iotago.MaxBlockIssuanceCredits/2) + ts.AddDefaultWallet(node0) const expectedCommittedSlotAfterPartitionMerge = 19 nodesP1 := []*mock.Node{node0, node1, node2, node3, node4, node5} diff --git a/pkg/tests/protocol_startup_test.go b/pkg/tests/protocol_startup_test.go index cc4e23a33..b05178718 100644 --- a/pkg/tests/protocol_startup_test.go +++ b/pkg/tests/protocol_startup_test.go @@ -146,7 +146,7 @@ func Test_StartNodeFromSnapshotAndDisk(t *testing.T) { nodeA := ts.AddValidatorNode("nodeA") nodeB := ts.AddValidatorNode("nodeB") ts.AddNode("nodeC") - ts.AddDefaultWallet(nodeA, iotago.MaxBlockIssuanceCredits/2) + ts.AddDefaultWallet(nodeA) nodeOptions := []options.Option[protocol.Protocol]{ protocol.WithStorageOptions( diff --git a/pkg/tests/upgrade_signaling_test.go b/pkg/tests/upgrade_signaling_test.go index 9d009abef..8a94ef17a 100644 --- a/pkg/tests/upgrade_signaling_test.go +++ b/pkg/tests/upgrade_signaling_test.go @@ -126,7 +126,7 @@ func Test_Upgrade_Signaling(t *testing.T) { ts.AddValidatorNode("nodeD") ts.AddNode("nodeE") ts.AddNode("nodeF") - wallet := ts.AddDefaultWallet(nodeA, iotago.MaxBlockIssuanceCredits/2) + wallet := ts.AddDefaultWallet(nodeA) ts.Run(true, map[string][]options.Option[protocol.Protocol]{ "nodeA": nodeOptionsWithoutV5, diff --git a/pkg/testsuite/testsuite.go b/pkg/testsuite/testsuite.go index 02b13d441..7cf2c189a 100644 --- a/pkg/testsuite/testsuite.go +++ b/pkg/testsuite/testsuite.go @@ -71,6 +71,23 @@ func DefaultProtocolParameterOptions(networkName string) []options.Option[iotago } } +type WalletOptions struct { + Amount iotago.BaseToken + BlockIssuanceCredits iotago.BlockIssuanceCredits +} + +func WithWalletAmount(amount iotago.BaseToken) options.Option[WalletOptions] { + return func(opts *WalletOptions) { + opts.Amount = amount + } +} + +func WithWalletBlockIssuanceCredits(blockIssuanceCredits iotago.BlockIssuanceCredits) options.Option[WalletOptions] { + return func(opts *WalletOptions) { + opts.BlockIssuanceCredits = blockIssuanceCredits + } +} + type TestSuite struct { Testing *testing.T fakeTesting *testing.T @@ -322,7 +339,7 @@ func (t *TestSuite) Shutdown() { // }) } -func (t *TestSuite) addNodeToPartition(name string, partition string, validator bool, optAmount ...iotago.BaseToken) *mock.Node { +func (t *TestSuite) addNodeToPartition(name string, partition string, validator bool, walletOpts ...options.Option[WalletOptions]) *mock.Node { t.mutex.Lock() defer t.mutex.Unlock() @@ -334,19 +351,19 @@ func (t *TestSuite) addNodeToPartition(name string, partition string, validator t.nodes.Set(name, node) node.SetCurrentSlot(t.currentSlot) - amount := mock.MinValidatorAccountAmount(t.API.ProtocolParameters()) - if len(optAmount) > 0 { - amount = optAmount[0] - } - if amount > 0 && validator { + walletOptions := options.Apply(&WalletOptions{ + Amount: mock.MinValidatorAccountAmount(t.API.ProtocolParameters()), + }, walletOpts) + + if walletOptions.Amount > 0 && validator { accountDetails := snapshotcreator.AccountDetails{ Address: iotago.Ed25519AddressFromPubKey(node.Validator.PublicKey), - Amount: amount, - Mana: iotago.Mana(amount), + Amount: walletOptions.Amount, + Mana: iotago.Mana(walletOptions.Amount), IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(node.Validator.PublicKey)), ExpirySlot: iotago.MaxSlotIndex, BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits / 2, - StakedAmount: amount, + StakedAmount: walletOptions.Amount, StakingEpochEnd: iotago.MaxEpochIndex, FixedCost: iotago.Mana(0), AccountID: node.Validator.AccountID, @@ -358,24 +375,24 @@ func (t *TestSuite) addNodeToPartition(name string, partition string, validator return node } -func (t *TestSuite) AddValidatorNodeToPartition(name string, partition string, optAmount ...iotago.BaseToken) *mock.Node { - return t.addNodeToPartition(name, partition, true, optAmount...) +func (t *TestSuite) AddValidatorNodeToPartition(name string, partition string, walletOpts ...options.Option[WalletOptions]) *mock.Node { + return t.addNodeToPartition(name, partition, true, walletOpts...) } -func (t *TestSuite) AddValidatorNode(name string, optAmount ...iotago.BaseToken) *mock.Node { - node := t.addNodeToPartition(name, mock.NetworkMainPartition, true, optAmount...) +func (t *TestSuite) AddValidatorNode(name string, walletOpts ...options.Option[WalletOptions]) *mock.Node { + node := t.addNodeToPartition(name, mock.NetworkMainPartition, true, walletOpts...) // create a wallet for each validator node which uses the validator account as a block issuer t.AddWallet(name, node, node.Validator.AccountID, node.KeyManager) return node } -func (t *TestSuite) AddNodeToPartition(name string, partition string, optAmount ...iotago.BaseToken) *mock.Node { - return t.addNodeToPartition(name, partition, false, optAmount...) +func (t *TestSuite) AddNodeToPartition(name string, partition string, walletOpts ...options.Option[WalletOptions]) *mock.Node { + return t.addNodeToPartition(name, partition, false, walletOpts...) } -func (t *TestSuite) AddNode(name string, optAmount ...iotago.BaseToken) *mock.Node { - return t.addNodeToPartition(name, mock.NetworkMainPartition, false, optAmount...) +func (t *TestSuite) AddNode(name string, walletOpts ...options.Option[WalletOptions]) *mock.Node { + return t.addNodeToPartition(name, mock.NetworkMainPartition, false, walletOpts...) } func (t *TestSuite) RemoveNode(name string) { @@ -389,26 +406,23 @@ func (t *TestSuite) AddGenesisAccount(accountDetails snapshotcreator.AccountDeta // AddGenesisWallet adds a wallet to the test suite with a block issuer in the genesis snapshot and access to the genesis seed. // If no block issuance credits are provided, the wallet will be assigned half of the maximum block issuance credits. -func (t *TestSuite) AddGenesisWallet(name string, node *mock.Node, blockIssuanceCredits ...iotago.BlockIssuanceCredits) *mock.Wallet { +func (t *TestSuite) AddGenesisWallet(name string, node *mock.Node, walletOpts ...options.Option[WalletOptions]) *mock.Wallet { accountID := tpkg.RandAccountID() newWallet := t.AddWallet(name, node, accountID, t.genesisKeyManager) - var bic iotago.BlockIssuanceCredits - if len(blockIssuanceCredits) == 0 { - bic = iotago.MaxBlockIssuanceCredits / 2 - } else { - bic = blockIssuanceCredits[0] - } + + walletOptions := options.Apply(&WalletOptions{ + Amount: mock.MinIssuerAccountAmount(t.API.ProtocolParameters()), + BlockIssuanceCredits: iotago.MaxBlockIssuanceCredits / 2, + }, walletOpts) accountDetails := snapshotcreator.AccountDetails{ - AccountID: accountID, - Address: iotago.Ed25519AddressFromPubKey(newWallet.BlockIssuer.PublicKey), - // TODO: Temporary "fix" for the tests, lets fix this in another PR, so we can at least use the docker network again - //Amount: mock.MinIssuerAccountAmount(t.API.ProtocolParameters()), - Amount: mock.MinValidatorAccountAmount(t.API.ProtocolParameters()) + 800, + AccountID: accountID, + Address: iotago.Ed25519AddressFromPubKey(newWallet.BlockIssuer.PublicKey), + Amount: walletOptions.Amount, Mana: iotago.Mana(mock.MinIssuerAccountAmount(t.API.ProtocolParameters())), IssuerKey: iotago.Ed25519PublicKeyBlockIssuerKeyFromPublicKey(ed25519.PublicKey(newWallet.BlockIssuer.PublicKey)), ExpirySlot: iotago.MaxSlotIndex, - BlockIssuanceCredits: bic, + BlockIssuanceCredits: walletOptions.BlockIssuanceCredits, } t.optsAccounts = append(t.optsAccounts, accountDetails) @@ -420,8 +434,8 @@ const ( DefaultWallet = "defaultWallet" ) -func (t *TestSuite) AddDefaultWallet(node *mock.Node, blockIssuanceCredits ...iotago.BlockIssuanceCredits) *mock.Wallet { - return t.AddGenesisWallet(DefaultWallet, node, blockIssuanceCredits...) +func (t *TestSuite) AddDefaultWallet(node *mock.Node, walletOpts ...options.Option[WalletOptions]) *mock.Wallet { + return t.AddGenesisWallet(DefaultWallet, node, walletOpts...) } func (t *TestSuite) DefaultWallet() *mock.Wallet { From 1fd223b993df581c8ec0b8aad9897aee9cc5f331 Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 14:01:19 +0100 Subject: [PATCH 4/8] Add depositcalculator to calculate the correct min deposits in the tests --- go.mod | 2 +- go.sum | 4 +- pkg/tests/accounts_test.go | 29 +- .../depositcalculator/depositcalculator.go | 334 ++++++++++++++++++ pkg/testsuite/mock/utils.go | 57 +-- tools/gendoc/go.mod | 2 +- tools/gendoc/go.sum | 4 +- tools/genesis-snapshot/go.mod | 2 +- tools/genesis-snapshot/go.sum | 4 +- 9 files changed, 374 insertions(+), 64 deletions(-) create mode 100644 pkg/testsuite/depositcalculator/depositcalculator.go diff --git a/go.mod b/go.mod index 966dd83c3..b4df94167 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/iotaledger/hive.go/stringify v0.0.0-20231122112629-bdf1cc39fba7 github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98 - github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 + github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 github.com/labstack/echo/v4 v4.11.3 github.com/labstack/gommon v0.4.1 github.com/libp2p/go-libp2p v0.32.0 diff --git a/go.sum b/go.sum index 853d98815..c20bbda20 100644 --- a/go.sum +++ b/go.sum @@ -307,8 +307,8 @@ github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b h1:T/9f4 github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b/go.mod h1:c7ktZxoH5Wp2ixzJn/8RmM5v2QOCIu/79tDFvfLbyPs= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98 h1:PjGs+njONeFaxFgQ3lxxlRs3wTYw3233f/yDyTV8/F8= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98/go.mod h1:jFRt2SZO3KE74/mk+zeCjlhVROriEg86K8CJTxvfdP8= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 h1:xdsynMvuo1KcFCjvuUH8ekh6zigKnOj+/j/WrvHaDxU= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 h1:vIQemhyUKXzLtmuyadp2VAwg2lGGYciIjRIqWSMs/30= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= github.com/ipfs/boxo v0.13.1 h1:nQ5oQzcMZR3oL41REJDcTbrvDvuZh3J9ckc9+ILeRQI= github.com/ipfs/boxo v0.13.1/go.mod h1:btrtHy0lmO1ODMECbbEY1pxNtrLilvKSYLoGQt1yYCk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index 9bb8cf0fe..7df9eda11 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -10,6 +10,7 @@ import ( "github.com/iotaledger/iota-core/pkg/protocol/engine/accounts" "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" "github.com/iotaledger/iota-core/pkg/testsuite" + "github.com/iotaledger/iota-core/pkg/testsuite/depositcalculator" "github.com/iotaledger/iota-core/pkg/testsuite/mock" "github.com/iotaledger/iota-core/pkg/testsuite/snapshotcreator" "github.com/iotaledger/iota-core/pkg/utils" @@ -220,7 +221,14 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { // set the expiry slot of the transitioned genesis account to the latest committed + MaxCommittableAge newAccountExpirySlot := node1.Protocol.MainEngineInstance().Storage.Settings().LatestCommitment().Slot() + ts.API.ProtocolParameters().MaxCommittableAge() - validatorAccountAmount := mock.MinValidatorAccountAmount(ts.API.ProtocolParameters()) + stakedAmount := iotago.BaseToken(10000) + + validatorAccountAmount, err := depositcalculator.MinDeposit(ts.API.ProtocolParameters(), iotago.OutputAccount, + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + depositcalculator.WithBlockIssuerKeys(1), + depositcalculator.WithStakedAmount(stakedAmount), + ) + require.NoError(t, err) var block1Slot iotago.SlotIndex = 1 tx1 := ts.DefaultWallet().CreateAccountFromInput( @@ -228,7 +236,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { "Genesis:0", ts.DefaultWallet(), mock.WithBlockIssuerFeature(iotago.BlockIssuerKeys{newAccountBlockIssuerKey}, newAccountExpirySlot), - mock.WithStakingFeature(validatorAccountAmount, 421, 0, 10), // match amount and staked amount to simplify the tests + mock.WithStakingFeature(stakedAmount, 421, 0, 10), // match amount and staked amount to simplify the tests mock.WithAccountAmount(validatorAccountAmount), ) @@ -250,7 +258,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { PreviousOutputID: iotago.EmptyOutputID, BlockIssuerKeysAdded: iotago.NewBlockIssuerKeys(newAccountBlockIssuerKey), BlockIssuerKeysRemoved: iotago.NewBlockIssuerKeys(), - ValidatorStakeChange: int64(validatorAccountAmount), + ValidatorStakeChange: int64(stakedAmount), StakeEndEpochChange: 10, FixedCostChange: 421, DelegationStakeChange: 0, @@ -265,7 +273,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: 0, - ValidatorStake: validatorAccountAmount, + ValidatorStake: stakedAmount, }, ts.Nodes()...) // CREATE DELEGATION TO NEW ACCOUNT FROM BASIC UTXO @@ -304,7 +312,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: iotago.BaseToken(delegatedAmount), - ValidatorStake: validatorAccountAmount, + ValidatorStake: stakedAmount, }, ts.Nodes()...) // transition a delegation output to a delayed claiming state @@ -337,7 +345,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { StakeEndEpoch: 10, FixedCost: 421, DelegationStake: iotago.BaseToken(0), - ValidatorStake: validatorAccountAmount, + ValidatorStake: stakedAmount, }, ts.Nodes()...) } @@ -695,8 +703,13 @@ func Test_NegativeBIC_AccountOutput(t *testing.T) { wallet2BIC := iotago.MaxBlockIssuanceCredits / 2 // Add a default block issuer to the network. This will add another block issuer account to the snapshot. - // TODO: calculate the correct amount - wallet1 := ts.AddGenesisWallet("wallet 1", node1, testsuite.WithWalletAmount(5000000), testsuite.WithWalletBlockIssuanceCredits(wallet1BIC)) + minDeposit, err := depositcalculator.MinDeposit(ts.API.ProtocolParameters(), iotago.OutputAccount, + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + depositcalculator.WithBlockIssuerKeys(2), + ) + require.NoError(t, err) + + wallet1 := ts.AddGenesisWallet("wallet 1", node1, testsuite.WithWalletAmount(minDeposit), testsuite.WithWalletBlockIssuanceCredits(wallet1BIC)) wallet2 := ts.AddGenesisWallet("wallet 2", node1, testsuite.WithWalletBlockIssuanceCredits(wallet2BIC)) ts.Run(true) diff --git a/pkg/testsuite/depositcalculator/depositcalculator.go b/pkg/testsuite/depositcalculator/depositcalculator.go new file mode 100644 index 000000000..803785264 --- /dev/null +++ b/pkg/testsuite/depositcalculator/depositcalculator.go @@ -0,0 +1,334 @@ +package depositcalculator + +import ( + "math/big" + + "github.com/iotaledger/hive.go/runtime/options" + "github.com/iotaledger/hive.go/serializer/v2/serix" + iotago "github.com/iotaledger/iota.go/v4" +) + +type Options struct { + // UnlockConditions + Address iotago.Address + StorageDepositReturnAddress iotago.Address + HasTimelock bool + ExpirationAddress iotago.Address + StateControllerAddress iotago.Address + GovernorAddress iotago.Address + + // Features + SenderAddress iotago.Address + IssuerAddress iotago.Address + MetadataLength int + StateMetadataLength int + TagLength int + HasNativeToken bool + BlockIssuerKeys int + StakedAmount iotago.BaseToken + + // Immutable Features + ImmutableIssuerAddress iotago.Address + ImmutableMetadataLength int +} + +// WithAddress sets the address for the address unlock condition. +func WithAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.Address = address + } +} + +// WithStorageDepositReturnAddress adds a storage deposit return unlock condition and sets the address. +func WithStorageDepositReturnAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.StorageDepositReturnAddress = address + } +} + +// WithHasTimelock adds a timelock unlock condition. +func WithHasTimelock() options.Option[Options] { + return func(opts *Options) { + opts.HasTimelock = true + } +} + +// WithExpirationAddress adds a expiration unlock condition and sets the address. +func WithExpirationAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.ExpirationAddress = address + } +} + +// WithStateControllerAddress sets the address for the state controller address unlock condition. +func WithStateControllerAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.StateControllerAddress = address + } +} + +// WithGovernorAddress sets the address for the governor address unlock condition. +func WithGovernorAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.GovernorAddress = address + } +} + +// WithSenderAddress adds a sender feature and sets the address. +func WithSenderAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.SenderAddress = address + } +} + +// WithIssuerAddress adds a issuer feature and sets the address. +func WithIssuerAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.IssuerAddress = address + } +} + +// WithMetadataLength adds a metadata feature and adds an entry with an empty key and a dummy value +// of the given length minus the length of the map length prefix, key length prefix and value length prefix. +func WithMetadataLength(length int) options.Option[Options] { + return func(opts *Options) { + opts.MetadataLength = length + } +} + +// WithStateMetadataLength adds a state metadata feature and adds an entry with an empty key and a dummy value +// of the given length minus the length of the map length prefix, key length prefix and value length prefix. +func WithStateMetadataLength(length int) options.Option[Options] { + return func(opts *Options) { + opts.StateMetadataLength = length + } +} + +// WithTagLength adds a tag feature and sets a dummy tag with the given length. +func WithTagLength(length int) options.Option[Options] { + return func(opts *Options) { + opts.TagLength = length + } +} + +// WithHasNativeToken adds a native token feature. +func WithHasNativeToken() options.Option[Options] { + return func(opts *Options) { + opts.HasNativeToken = true + } +} + +// WithBlockIssuerKeys adds a block issuer feature and adds the given amount of dummy keys. +func WithBlockIssuerKeys(keys int) options.Option[Options] { + return func(opts *Options) { + opts.BlockIssuerKeys = keys + } +} + +// WithStakedAmount adds a staking feature and sets the staked amount. +func WithStakedAmount(amount iotago.BaseToken) options.Option[Options] { + return func(opts *Options) { + opts.StakedAmount = amount + } +} + +// WithImmutableIssuerAddress adds an immutable issuer feature and sets the address. +func WithImmutableIssuerAddress(address iotago.Address) options.Option[Options] { + return func(opts *Options) { + opts.ImmutableIssuerAddress = address + } +} + +// WithImmutableMetadataLength adds an immutable metadata feature and adds an entry with an empty key and a dummy value +// of the given length minus the length of the map length prefix, key length prefix and value length prefix. +func WithImmutableMetadataLength(length int) options.Option[Options] { + return func(opts *Options) { + opts.ImmutableMetadataLength = length + } +} + +func getUnlockConditions[T iotago.UnlockCondition](outputType iotago.OutputType, opts *Options) iotago.UnlockConditions[T] { + unlockConditions := make(iotago.UnlockConditions[T], 0) + + // Mandatory address unlocks + switch outputType { + case iotago.OutputBasic, iotago.OutputAccount, iotago.OutputNFT, iotago.OutputDelegation: + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.AddressUnlockCondition{Address: opts.Address}).(T)) + + case iotago.OutputAnchor: + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.StateControllerAddressUnlockCondition{Address: opts.StateControllerAddress}).(T)) + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.GovernorAddressUnlockCondition{Address: opts.GovernorAddress}).(T)) + + case iotago.OutputFoundry: + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.ImmutableAccountUnlockCondition{Address: &iotago.AccountAddress{}}).(T)) + } + + if opts.StorageDepositReturnAddress != nil { + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.StorageDepositReturnUnlockCondition{ReturnAddress: opts.StorageDepositReturnAddress}).(T)) + } + + if opts.HasTimelock { + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.TimelockUnlockCondition{}).(T)) + } + + if opts.ExpirationAddress != nil { + unlockConditions = append(unlockConditions, iotago.UnlockCondition(&iotago.ExpirationUnlockCondition{ReturnAddress: opts.ExpirationAddress}).(T)) + } + + return unlockConditions +} + +func getFeatures[T iotago.Feature](opts *Options) iotago.Features[T] { + features := iotago.Features[T]{} + + if opts.SenderAddress != nil { + features = append(features, &iotago.SenderFeature{Address: opts.SenderAddress}) + } + + if opts.IssuerAddress != nil { + features = append(features, &iotago.IssuerFeature{Address: opts.IssuerAddress}) + } + + if opts.MetadataLength > 0 { + features = append(features, &iotago.MetadataFeature{ + Entries: iotago.MetadataFeatureEntries{ + // configured length - map length prefix - key length prefix - value length prefix + "": make([]byte, opts.MetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + }, + }) + } + + if opts.StateMetadataLength > 0 { + features = append(features, &iotago.StateMetadataFeature{ + Entries: iotago.StateMetadataFeatureEntries{ + // configured length - map length prefix - key length prefix - value length prefix + "": make([]byte, opts.StateMetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + }, + }) + } + + if opts.TagLength > 0 { + features = append(features, &iotago.TagFeature{Tag: make([]byte, opts.TagLength)}) + } + + if opts.HasNativeToken { + features = append(features, &iotago.NativeTokenFeature{Amount: big.NewInt(0)}) + } + + if opts.BlockIssuerKeys > 0 { + blockIssuerKeys := make([]iotago.BlockIssuerKey, 0, opts.BlockIssuerKeys) + for i := 0; i < opts.BlockIssuerKeys; i++ { + blockIssuerKeys = append(blockIssuerKeys, &iotago.Ed25519PublicKeyBlockIssuerKey{}) + } + + features = append(features, &iotago.BlockIssuerFeature{BlockIssuerKeys: blockIssuerKeys}) + } + + if opts.StakedAmount > 0 { + features = append(features, &iotago.StakingFeature{StakedAmount: opts.StakedAmount}) + } + + return features +} + +func getImmutableFeatures[T iotago.Feature](opts *Options) iotago.Features[T] { + features := iotago.Features[T]{} + + if opts.ImmutableIssuerAddress != nil { + features = append(features, &iotago.IssuerFeature{Address: opts.ImmutableIssuerAddress}) + } + + if opts.ImmutableMetadataLength > 0 { + features = append(features, &iotago.MetadataFeature{ + Entries: iotago.MetadataFeatureEntries{ + // configured length - map length prefix - key length prefix - value length prefix + "": make([]byte, opts.ImmutableMetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + }, + }) + } + + return features +} + +func MinDeposit(protocolParams iotago.ProtocolParameters, outputType iotago.OutputType, opts ...options.Option[Options]) (iotago.BaseToken, error) { + depositCalculationOptions := options.Apply(&Options{}, opts) + + var dummyOutput iotago.Output + switch outputType { + case iotago.OutputBasic: + dummyOutput = &iotago.BasicOutput{ + Amount: 0, + Mana: 0, + UnlockConditions: getUnlockConditions[iotago.BasicOutputUnlockCondition](outputType, depositCalculationOptions), + Features: getFeatures[iotago.BasicOutputFeature](depositCalculationOptions), + } + + case iotago.OutputAccount: + dummyOutput = &iotago.AccountOutput{ + Amount: 0, + Mana: 0, + AccountID: iotago.AccountID{}, + FoundryCounter: 0, + UnlockConditions: getUnlockConditions[iotago.AccountOutputUnlockCondition](outputType, depositCalculationOptions), + Features: getFeatures[iotago.AccountOutputFeature](depositCalculationOptions), + ImmutableFeatures: getImmutableFeatures[iotago.AccountOutputImmFeature](depositCalculationOptions), + } + + case iotago.OutputAnchor: + dummyOutput = &iotago.AnchorOutput{ + Amount: 0, + Mana: 0, + AnchorID: iotago.AnchorID{}, + StateIndex: 0, + UnlockConditions: getUnlockConditions[iotago.AnchorOutputUnlockCondition](outputType, depositCalculationOptions), + Features: getFeatures[iotago.AnchorOutputFeature](depositCalculationOptions), + ImmutableFeatures: getImmutableFeatures[iotago.AnchorOutputImmFeature](depositCalculationOptions), + } + + case iotago.OutputFoundry: + dummyOutput = &iotago.FoundryOutput{ + Amount: 0, + SerialNumber: 0, + TokenScheme: &iotago.SimpleTokenScheme{}, + UnlockConditions: getUnlockConditions[iotago.FoundryOutputUnlockCondition](outputType, depositCalculationOptions), + Features: getFeatures[iotago.FoundryOutputFeature](depositCalculationOptions), + ImmutableFeatures: getImmutableFeatures[iotago.FoundryOutputImmFeature](depositCalculationOptions), + } + + case iotago.OutputNFT: + dummyOutput = &iotago.NFTOutput{ + Amount: 0, + Mana: 0, + NFTID: iotago.NFTID{}, + UnlockConditions: getUnlockConditions[iotago.NFTOutputUnlockCondition](outputType, depositCalculationOptions), + Features: getFeatures[iotago.NFTOutputFeature](depositCalculationOptions), + ImmutableFeatures: getImmutableFeatures[iotago.NFTOutputImmFeature](depositCalculationOptions), + } + + case iotago.OutputDelegation: + dummyOutput = &iotago.DelegationOutput{ + Amount: 0, + DelegatedAmount: 0, + DelegationID: iotago.DelegationID{}, + ValidatorAddress: &iotago.AccountAddress{}, + StartEpoch: 0, + EndEpoch: 0, + UnlockConditions: getUnlockConditions[iotago.DelegationOutputUnlockCondition](outputType, depositCalculationOptions), + } + } + + storageScoreStructure := iotago.NewStorageScoreStructure(protocolParams.StorageScoreParameters()) + + // calculate the minimum storage deposit + minDeposit, err := storageScoreStructure.MinDeposit(dummyOutput) + if err != nil { + return 0, err + } + + // we need to have at least the staked amount in the deposit + if depositCalculationOptions.StakedAmount > minDeposit { + minDeposit = depositCalculationOptions.StakedAmount + } + + return minDeposit, nil +} diff --git a/pkg/testsuite/mock/utils.go b/pkg/testsuite/mock/utils.go index 8b59b713f..92ec20594 100644 --- a/pkg/testsuite/mock/utils.go +++ b/pkg/testsuite/mock/utils.go @@ -4,61 +4,24 @@ import ( "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/runtime/options" "github.com/iotaledger/iota-core/pkg/protocol/engine/utxoledger" + "github.com/iotaledger/iota-core/pkg/testsuite/depositcalculator" iotago "github.com/iotaledger/iota.go/v4" "github.com/iotaledger/iota.go/v4/builder" ) func MinIssuerAccountAmount(protocolParameters iotago.ProtocolParameters) iotago.BaseToken { - // create a dummy account with a block issuer feature to calculate the storage score. - dummyAccountOutput := &iotago.AccountOutput{ - Amount: 0, - Mana: 0, - AccountID: iotago.EmptyAccountID, - FoundryCounter: 0, - UnlockConditions: iotago.AccountOutputUnlockConditions{ - &iotago.AddressUnlockCondition{ - Address: &iotago.Ed25519Address{}, - }, - }, - Features: iotago.AccountOutputFeatures{ - &iotago.BlockIssuerFeature{ - BlockIssuerKeys: iotago.BlockIssuerKeys{ - &iotago.Ed25519PublicKeyBlockIssuerKey{}, - }, - }, - }, - ImmutableFeatures: iotago.AccountOutputImmFeatures{}, - } - storageScoreStructure := iotago.NewStorageScoreStructure(protocolParameters.StorageScoreParameters()) - - return lo.PanicOnErr(storageScoreStructure.MinDeposit(dummyAccountOutput)) + return lo.PanicOnErr(depositcalculator.MinDeposit(protocolParameters, iotago.OutputAccount, + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + depositcalculator.WithBlockIssuerKeys(1), + )) } func MinValidatorAccountAmount(protocolParameters iotago.ProtocolParameters) iotago.BaseToken { - // create a dummy account with a staking and block issuer feature to calculate the storage score. - dummyAccountOutput := &iotago.AccountOutput{ - Amount: 0, - Mana: 0, - AccountID: iotago.EmptyAccountID, - FoundryCounter: 0, - UnlockConditions: iotago.AccountOutputUnlockConditions{ - &iotago.AddressUnlockCondition{ - Address: &iotago.Ed25519Address{}, - }, - }, - Features: iotago.AccountOutputFeatures{ - &iotago.BlockIssuerFeature{ - BlockIssuerKeys: iotago.BlockIssuerKeys{ - &iotago.Ed25519PublicKeyBlockIssuerKey{}, - }, - }, - &iotago.StakingFeature{}, - }, - ImmutableFeatures: iotago.AccountOutputImmFeatures{}, - } - storageScoreStructure := iotago.NewStorageScoreStructure(protocolParameters.StorageScoreParameters()) - - return lo.PanicOnErr(storageScoreStructure.MinDeposit(dummyAccountOutput)) + return lo.PanicOnErr(depositcalculator.MinDeposit(protocolParameters, iotago.OutputAccount, + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + depositcalculator.WithBlockIssuerKeys(1), + depositcalculator.WithStakedAmount(1), + )) } // TODO: add the correct formula later. diff --git a/tools/gendoc/go.mod b/tools/gendoc/go.mod index 33697e170..6f312ac5e 100644 --- a/tools/gendoc/go.mod +++ b/tools/gendoc/go.mod @@ -72,7 +72,7 @@ require ( github.com/iotaledger/hive.go/stringify v0.0.0-20231122112629-bdf1cc39fba7 // indirect github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b // indirect github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98 // indirect - github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 // indirect + github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 // indirect github.com/ipfs/boxo v0.13.1 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-datastore v0.6.0 // indirect diff --git a/tools/gendoc/go.sum b/tools/gendoc/go.sum index 8941f11a3..625e4af90 100644 --- a/tools/gendoc/go.sum +++ b/tools/gendoc/go.sum @@ -311,8 +311,8 @@ github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b h1:T/9f4 github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231123103852-bb039cbab83b/go.mod h1:c7ktZxoH5Wp2ixzJn/8RmM5v2QOCIu/79tDFvfLbyPs= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98 h1:PjGs+njONeFaxFgQ3lxxlRs3wTYw3233f/yDyTV8/F8= github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231123103318-f6ea945e2e98/go.mod h1:jFRt2SZO3KE74/mk+zeCjlhVROriEg86K8CJTxvfdP8= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 h1:xdsynMvuo1KcFCjvuUH8ekh6zigKnOj+/j/WrvHaDxU= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 h1:vIQemhyUKXzLtmuyadp2VAwg2lGGYciIjRIqWSMs/30= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= github.com/ipfs/boxo v0.13.1 h1:nQ5oQzcMZR3oL41REJDcTbrvDvuZh3J9ckc9+ILeRQI= github.com/ipfs/boxo v0.13.1/go.mod h1:btrtHy0lmO1ODMECbbEY1pxNtrLilvKSYLoGQt1yYCk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/tools/genesis-snapshot/go.mod b/tools/genesis-snapshot/go.mod index 89bbe8913..cf646a695 100644 --- a/tools/genesis-snapshot/go.mod +++ b/tools/genesis-snapshot/go.mod @@ -10,7 +10,7 @@ require ( github.com/iotaledger/hive.go/lo v0.0.0-20231122112629-bdf1cc39fba7 github.com/iotaledger/hive.go/runtime v0.0.0-20231122112629-bdf1cc39fba7 github.com/iotaledger/iota-core v0.0.0-00010101000000-000000000000 - github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 + github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 github.com/mr-tron/base58 v1.2.0 github.com/spf13/pflag v1.0.5 golang.org/x/crypto v0.15.0 diff --git a/tools/genesis-snapshot/go.sum b/tools/genesis-snapshot/go.sum index 23ddfa2f8..d3873d07e 100644 --- a/tools/genesis-snapshot/go.sum +++ b/tools/genesis-snapshot/go.sum @@ -52,8 +52,8 @@ github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231113110812-4ca2b6c github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231113110812-4ca2b6cc9a42/go.mod h1:FoH3T6yKlZJp8xm8K+zsQiibSynp32v21CpWx8xkek8= github.com/iotaledger/hive.go/stringify v0.0.0-20231122112629-bdf1cc39fba7 h1:h481Dn+giKO/1MamwuDZ8Mvzg4GbPx/asKD/X3Zs8wc= github.com/iotaledger/hive.go/stringify v0.0.0-20231122112629-bdf1cc39fba7/go.mod h1:FTo/UWzNYgnQ082GI9QVM9HFDERqf9rw9RivNpqrnTs= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49 h1:xdsynMvuo1KcFCjvuUH8ekh6zigKnOj+/j/WrvHaDxU= -github.com/iotaledger/iota.go/v4 v4.0.0-20231124100551-bb617f46bb49/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86 h1:vIQemhyUKXzLtmuyadp2VAwg2lGGYciIjRIqWSMs/30= +github.com/iotaledger/iota.go/v4 v4.0.0-20231124103306-ad44904e2b86/go.mod h1:aO+5iL0vTNwNfE4QMGHVIufGziSI1wTvwJY1ipSMgCk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= From 3f58de5324f7e152276628a164c5cc08c1ebfa78 Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 14:19:17 +0100 Subject: [PATCH 5/8] Fix linter --- pkg/testsuite/depositcalculator/depositcalculator.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/testsuite/depositcalculator/depositcalculator.go b/pkg/testsuite/depositcalculator/depositcalculator.go index 803785264..dbda2ad9f 100644 --- a/pkg/testsuite/depositcalculator/depositcalculator.go +++ b/pkg/testsuite/depositcalculator/depositcalculator.go @@ -1,3 +1,4 @@ +//nolint:forcetypeassert package depositcalculator import ( From 73610193c4125b4ca5205ae539b9b62b67c3b664 Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 15:44:25 +0100 Subject: [PATCH 6/8] Remove comment --- pkg/tests/accounts_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tests/accounts_test.go b/pkg/tests/accounts_test.go index 7df9eda11..dc5948973 100644 --- a/pkg/tests/accounts_test.go +++ b/pkg/tests/accounts_test.go @@ -236,7 +236,7 @@ func Test_StakeDelegateAndDelayedClaim(t *testing.T) { "Genesis:0", ts.DefaultWallet(), mock.WithBlockIssuerFeature(iotago.BlockIssuerKeys{newAccountBlockIssuerKey}, newAccountExpirySlot), - mock.WithStakingFeature(stakedAmount, 421, 0, 10), // match amount and staked amount to simplify the tests + mock.WithStakingFeature(stakedAmount, 421, 0, 10), mock.WithAccountAmount(validatorAccountAmount), ) From cfa2077968366689b7d2c92b8b4e4e331d411eae Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 15:53:01 +0100 Subject: [PATCH 7/8] Add tests for depositcalculator --- .../depositcalculator/depositcalculator.go | 10 +- .../depositcalculator_test.go | 151 ++++++++++++++++++ 2 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 pkg/testsuite/depositcalculator/depositcalculator_test.go diff --git a/pkg/testsuite/depositcalculator/depositcalculator.go b/pkg/testsuite/depositcalculator/depositcalculator.go index dbda2ad9f..ef379cb19 100644 --- a/pkg/testsuite/depositcalculator/depositcalculator.go +++ b/pkg/testsuite/depositcalculator/depositcalculator.go @@ -288,9 +288,13 @@ func MinDeposit(protocolParams iotago.ProtocolParameters, outputType iotago.Outp case iotago.OutputFoundry: dummyOutput = &iotago.FoundryOutput{ - Amount: 0, - SerialNumber: 0, - TokenScheme: &iotago.SimpleTokenScheme{}, + Amount: 0, + SerialNumber: 0, + TokenScheme: &iotago.SimpleTokenScheme{ + MintedTokens: big.NewInt(0), + MeltedTokens: big.NewInt(0), + MaximumSupply: big.NewInt(0), + }, UnlockConditions: getUnlockConditions[iotago.FoundryOutputUnlockCondition](outputType, depositCalculationOptions), Features: getFeatures[iotago.FoundryOutputFeature](depositCalculationOptions), ImmutableFeatures: getImmutableFeatures[iotago.FoundryOutputImmFeature](depositCalculationOptions), diff --git a/pkg/testsuite/depositcalculator/depositcalculator_test.go b/pkg/testsuite/depositcalculator/depositcalculator_test.go new file mode 100644 index 000000000..562e1831a --- /dev/null +++ b/pkg/testsuite/depositcalculator/depositcalculator_test.go @@ -0,0 +1,151 @@ +package depositcalculator_test + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/iotaledger/hive.go/runtime/options" + "github.com/iotaledger/iota-core/pkg/testsuite/depositcalculator" + iotago "github.com/iotaledger/iota.go/v4" +) + +func TestCalculate(t *testing.T) { + + protocolParams := iotago.NewV3ProtocolParameters(iotago.WithVersion(3)) + storageScoreStructure := iotago.NewStorageScoreStructure(protocolParams.StorageScoreParameters()) + + type test struct { + name string + outputType iotago.OutputType + options []options.Option[depositcalculator.Options] + targetOutput iotago.Output + targetErr error + } + + tests := []*test{ + { + name: "ok - basic output", + outputType: iotago.OutputBasic, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + }, + targetOutput: &iotago.BasicOutput{ + UnlockConditions: iotago.BasicOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + }, + targetErr: nil, + }, + { + name: "ok - account output", + outputType: iotago.OutputAccount, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + }, + targetOutput: &iotago.AccountOutput{ + UnlockConditions: iotago.AccountOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + }, + targetErr: nil, + }, + { + name: "ok - account output - 2 block issuer keys", + outputType: iotago.OutputAccount, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + depositcalculator.WithBlockIssuerKeys(2), + }, + targetOutput: &iotago.AccountOutput{ + UnlockConditions: iotago.AccountOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + Features: iotago.AccountOutputFeatures{ + &iotago.BlockIssuerFeature{ + BlockIssuerKeys: iotago.BlockIssuerKeys{ + &iotago.Ed25519PublicKeyBlockIssuerKey{}, + &iotago.Ed25519PublicKeyBlockIssuerKey{}, + }, + ExpirySlot: 0, + }, + }, + }, + targetErr: nil, + }, + { + name: "ok - anchor output", + outputType: iotago.OutputAnchor, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithStateControllerAddress(&iotago.Ed25519Address{}), + depositcalculator.WithGovernorAddress(&iotago.Ed25519Address{}), + }, + targetOutput: &iotago.AnchorOutput{ + UnlockConditions: iotago.AnchorOutputUnlockConditions{ + &iotago.StateControllerAddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + &iotago.GovernorAddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + }, + targetErr: nil, + }, + { + name: "ok - foundry output", + outputType: iotago.OutputFoundry, + options: []options.Option[depositcalculator.Options]{}, + targetOutput: &iotago.FoundryOutput{ + UnlockConditions: iotago.FoundryOutputUnlockConditions{ + &iotago.ImmutableAccountUnlockCondition{Address: &iotago.AccountAddress{}}, + }, + TokenScheme: &iotago.SimpleTokenScheme{ + MintedTokens: big.NewInt(0), + MeltedTokens: big.NewInt(0), + MaximumSupply: big.NewInt(0), + }, + }, + targetErr: nil, + }, + { + name: "ok - NFT output", + outputType: iotago.OutputNFT, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + }, + targetOutput: &iotago.NFTOutput{ + UnlockConditions: iotago.NFTOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + }, + targetErr: nil, + }, + { + name: "ok - Delegation output", + outputType: iotago.OutputDelegation, + options: []options.Option[depositcalculator.Options]{ + depositcalculator.WithAddress(&iotago.Ed25519Address{}), + }, + targetOutput: &iotago.DelegationOutput{ + UnlockConditions: iotago.DelegationOutputUnlockConditions{ + &iotago.AddressUnlockCondition{Address: &iotago.Ed25519Address{}}, + }, + }, + targetErr: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result, err := depositcalculator.MinDeposit(protocolParams, test.outputType, test.options...) + if test.targetErr != nil { + require.ErrorIs(t, err, test.targetErr) + return + } + require.NoError(t, err) + + targetDeposit, err := storageScoreStructure.MinDeposit(test.targetOutput) + require.NoError(t, err) + + require.Equal(t, targetDeposit, result) + }) + } +} From c4264f5a88cdf109d90dac054faef7de7f6cb98e Mon Sep 17 00:00:00 2001 From: muXxer Date: Fri, 24 Nov 2023 15:54:32 +0100 Subject: [PATCH 8/8] Rename metadata options --- .../depositcalculator/depositcalculator.go | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/pkg/testsuite/depositcalculator/depositcalculator.go b/pkg/testsuite/depositcalculator/depositcalculator.go index ef379cb19..fd0ad67a1 100644 --- a/pkg/testsuite/depositcalculator/depositcalculator.go +++ b/pkg/testsuite/depositcalculator/depositcalculator.go @@ -19,18 +19,18 @@ type Options struct { GovernorAddress iotago.Address // Features - SenderAddress iotago.Address - IssuerAddress iotago.Address - MetadataLength int - StateMetadataLength int - TagLength int - HasNativeToken bool - BlockIssuerKeys int - StakedAmount iotago.BaseToken + SenderAddress iotago.Address + IssuerAddress iotago.Address + MetadataSerializedSize int + StateMetadataSerializedSize int + TagLength int + HasNativeToken bool + BlockIssuerKeys int + StakedAmount iotago.BaseToken // Immutable Features - ImmutableIssuerAddress iotago.Address - ImmutableMetadataLength int + ImmutableIssuerAddress iotago.Address + ImmutableMetadataSerializedSize int } // WithAddress sets the address for the address unlock condition. @@ -89,19 +89,19 @@ func WithIssuerAddress(address iotago.Address) options.Option[Options] { } } -// WithMetadataLength adds a metadata feature and adds an entry with an empty key and a dummy value +// WithMetadataSerializedSize adds a metadata feature and adds an entry with an empty key and a dummy value // of the given length minus the length of the map length prefix, key length prefix and value length prefix. -func WithMetadataLength(length int) options.Option[Options] { +func WithMetadataSerializedSize(size int) options.Option[Options] { return func(opts *Options) { - opts.MetadataLength = length + opts.MetadataSerializedSize = size } } -// WithStateMetadataLength adds a state metadata feature and adds an entry with an empty key and a dummy value +// WithStateMetadataSerializedSize adds a state metadata feature and adds an entry with an empty key and a dummy value // of the given length minus the length of the map length prefix, key length prefix and value length prefix. -func WithStateMetadataLength(length int) options.Option[Options] { +func WithStateMetadataSerializedSize(size int) options.Option[Options] { return func(opts *Options) { - opts.StateMetadataLength = length + opts.StateMetadataSerializedSize = size } } @@ -140,11 +140,11 @@ func WithImmutableIssuerAddress(address iotago.Address) options.Option[Options] } } -// WithImmutableMetadataLength adds an immutable metadata feature and adds an entry with an empty key and a dummy value +// WithImmutableMetadataSerializedSize adds an immutable metadata feature and adds an entry with an empty key and a dummy value // of the given length minus the length of the map length prefix, key length prefix and value length prefix. -func WithImmutableMetadataLength(length int) options.Option[Options] { +func WithImmutableMetadataSerializedSize(size int) options.Option[Options] { return func(opts *Options) { - opts.ImmutableMetadataLength = length + opts.ImmutableMetadataSerializedSize = size } } @@ -190,20 +190,20 @@ func getFeatures[T iotago.Feature](opts *Options) iotago.Features[T] { features = append(features, &iotago.IssuerFeature{Address: opts.IssuerAddress}) } - if opts.MetadataLength > 0 { + if opts.MetadataSerializedSize > 0 { features = append(features, &iotago.MetadataFeature{ Entries: iotago.MetadataFeatureEntries{ // configured length - map length prefix - key length prefix - value length prefix - "": make([]byte, opts.MetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + "": make([]byte, opts.MetadataSerializedSize-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), }, }) } - if opts.StateMetadataLength > 0 { + if opts.StateMetadataSerializedSize > 0 { features = append(features, &iotago.StateMetadataFeature{ Entries: iotago.StateMetadataFeatureEntries{ // configured length - map length prefix - key length prefix - value length prefix - "": make([]byte, opts.StateMetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + "": make([]byte, opts.StateMetadataSerializedSize-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), }, }) } @@ -239,11 +239,11 @@ func getImmutableFeatures[T iotago.Feature](opts *Options) iotago.Features[T] { features = append(features, &iotago.IssuerFeature{Address: opts.ImmutableIssuerAddress}) } - if opts.ImmutableMetadataLength > 0 { + if opts.ImmutableMetadataSerializedSize > 0 { features = append(features, &iotago.MetadataFeature{ Entries: iotago.MetadataFeatureEntries{ // configured length - map length prefix - key length prefix - value length prefix - "": make([]byte, opts.ImmutableMetadataLength-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), + "": make([]byte, opts.ImmutableMetadataSerializedSize-int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsByte)+int(serix.LengthPrefixTypeAsUint16)), }, }) }