From c1f3e6dbd0d50fa3cfbf2437e4e55b82031893f9 Mon Sep 17 00:00:00 2001 From: najla Date: Sat, 6 Apr 2024 20:17:59 +0100 Subject: [PATCH 01/78] integration tests for staking --- tests/e2e/e2e_new_actions.go | 0 tests/integration/new_actions_test.go | 213 ++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 tests/e2e/e2e_new_actions.go create mode 100644 tests/integration/new_actions_test.go diff --git a/tests/e2e/e2e_new_actions.go b/tests/e2e/e2e_new_actions.go new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go new file mode 100644 index 0000000..85bdd9c --- /dev/null +++ b/tests/integration/new_actions_test.go @@ -0,0 +1,213 @@ +// Copyright (C) 2024, AllianceBlock. All rights reserved. +// See the file LICENSE for licensing terms. + +package integration_test + +import ( + "context" + "testing" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/logging" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/ed25519" + + "github.com/nuklai/nuklaivm/actions" + "github.com/nuklai/nuklaivm/auth" +) + +func init() { + logFactory = logging.NewFactory(logging.Config{ + DisplayLevel: logging.Debug, + }) + l, err := logFactory.Make("main") + if err != nil { + panic(err) + } + log = l +} + +func TestNewActions(t *testing.T) { + gomega.RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, "nuklaivm new actions integration tests") +} + +var _ = ginkgo.Describe("nuklai staking mecanism", func() { + ginkgo.It("Auto register validator stake", func() { + currentTime := time.Now().UTC() + stakeStartTime := currentTime.Add(2 * time.Minute) + stakeEndTime := currentTime.Add(15 * time.Minute) + delegationFeeRate := 50 + parser0, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + parser1, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + ginkgo.By("Register validator stake instances[0] with zero balance", func() { + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[0].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rsender, + } + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := factory.Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser0, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + factory, + ) + gomega.Ω(err).Should(gomega.HaveOccurred()) + gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) + }) + + ginkgo.By("Get staked validators", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) + + ginkgo.By("Register validator stake instances[1] with zero balance", func() { + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[1].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rsender2, + } + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := factory.Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser1, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + factory, + ) + gomega.Ω(err).Should(gomega.HaveOccurred()) + gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) + }) + + ginkgo.By("Get validator staked amount after staking", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + }) + + ginkgo.By("Get staked validators", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(2)) + }) + + ginkgo.By("Transfer NAI to user and delegate stake to instances[0]", func() { + priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + userFactory := auth.NewED25519Factory(priv) + userSender := auth.NewED25519Address(priv.PublicKey()) + // uSender := codec.MustAddressBech32(nconsts.HRP, userSender) + // fund new account + // write another test with funding < 200 + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: userSender, + Asset: ids.Empty, + Value: 100, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + userStakeStartTime := currentTime.Add(2 * time.Minute) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err = instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instances[0].nodeID.Bytes(), + StakeStartTime: uint64(userStakeStartTime.Unix()), + StakedAmount: 50, + RewardAddress: userSender, + }, + userFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + // add more ginko.By where error should be thrown with wrong data input + ginkgo.By("Claim validator instances[0] stake reward", func() { + // ClaimValidatorStakeRewards + // TO DO: test claim with a wrong key + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser0, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instances[0].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(instances[0].ncli.Balance(context.Background(), sender, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.By("Withdraw validator instances[0] stake", func() { + // WithdrawValidatorStake + // TO DO: test claim with a wrong key + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser0, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instances[0].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.By("Get validator stake after staking withdraw ", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) + }) +}) From 12a816f140e88fa089c55cdc32653acdddd25700 Mon Sep 17 00:00:00 2001 From: najla Date: Sun, 7 Apr 2024 18:53:15 +0100 Subject: [PATCH 02/78] tests for staking --- tests/integration/new_actions_test.go | 85 +++++++++++++++++++++------ 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 85bdd9c..dee7f3e 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -18,6 +18,7 @@ import ( "github.com/nuklai/nuklaivm/actions" "github.com/nuklai/nuklaivm/auth" + nconsts "github.com/nuklai/nuklaivm/consts" ) func init() { @@ -36,17 +37,34 @@ func TestNewActions(t *testing.T) { ginkgo.RunSpecs(t, "nuklaivm new actions integration tests") } -var _ = ginkgo.Describe("nuklai staking mecanism", func() { +var _ = ginkgo.Describe("nuklai staking mechanism", func() { ginkgo.It("Auto register validator stake", func() { currentTime := time.Now().UTC() stakeStartTime := currentTime.Add(2 * time.Minute) stakeEndTime := currentTime.Add(15 * time.Minute) delegationFeeRate := 50 + parser0, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) parser1, err := instances[1].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 := codec.MustAddressBech32(nconsts.HRP, rwithdraw0) + + withdraw1Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + // withdraw0Factory := auth.NewED25519Factory(priv1Withdraw) + withdraw1 := auth.NewED25519Address(withdraw1Priv.PublicKey()) + + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + delegateFactory := auth.NewED25519Factory(delegatePriv) + rdelegate := auth.NewED25519Address(delegatePriv.PublicKey()) + delegate := codec.MustAddressBech32(nconsts.HRP, rdelegate) + ginkgo.By("Register validator stake instances[0] with zero balance", func() { stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[0].nodeID.Bytes(), @@ -54,7 +72,7 @@ var _ = ginkgo.Describe("nuklai staking mecanism", func() { StakeEndTime: uint64(stakeEndTime.Unix()), StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rsender, + RewardAddress: rwithdraw0, } stakeInfoBytes, err := stakeInfo.Marshal() gomega.Ω(err).Should(gomega.BeNil()) @@ -90,7 +108,7 @@ var _ = ginkgo.Describe("nuklai staking mecanism", func() { StakeEndTime: uint64(stakeEndTime.Unix()), StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rsender2, + RewardAddress: withdraw1, } stakeInfoBytes, err := stakeInfo.Marshal() gomega.Ω(err).Should(gomega.BeNil()) @@ -129,21 +147,13 @@ var _ = ginkgo.Describe("nuklai staking mecanism", func() { }) ginkgo.By("Transfer NAI to user and delegate stake to instances[0]", func() { - priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - userFactory := auth.NewED25519Factory(priv) - userSender := auth.NewED25519Address(priv.PublicKey()) - // uSender := codec.MustAddressBech32(nconsts.HRP, userSender) - // fund new account - // write another test with funding < 200 - parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err := instances[0].hcli.GenerateTransaction( context.Background(), - parser, + parser0, nil, &actions.Transfer{ - To: userSender, + To: rdelegate, Asset: ids.Empty, Value: 100, }, @@ -156,15 +166,56 @@ var _ = ginkgo.Describe("nuklai staking mecanism", func() { gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err = instances[0].hcli.GenerateTransaction( context.Background(), - parser, + parser0, nil, &actions.DelegateUserStake{ NodeID: instances[0].nodeID.Bytes(), StakeStartTime: uint64(userStakeStartTime.Unix()), StakedAmount: 50, - RewardAddress: userSender, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.By("Get user stake before claim", func() { + _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) + }) + + ginkgo.By("Claim delegation stake rewards from instances[0]", func() { + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser0, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[0].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.By("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) + }) + + ginkgo.By("Undelegate user stake from instances[0]", func() { + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser0, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[0].nodeID.Bytes(), }, - userFactory, + delegateFactory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) @@ -184,7 +235,7 @@ var _ = ginkgo.Describe("nuklai staking mecanism", func() { factory, ) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(instances[0].ncli.Balance(context.Background(), sender, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) }) From 06046f57d5953f76901ad6433d1c30e1cd1a86c8 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 10 Apr 2024 17:35:18 +0100 Subject: [PATCH 03/78] delete 2d file and current test file keep only staking test (for debugging) --- tests/integration/integration_test.go | 2537 +++++++++++++------------ tests/integration/new_actions_test.go | 264 --- 2 files changed, 1314 insertions(+), 1487 deletions(-) delete mode 100644 tests/integration/new_actions_test.go diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 963bc8e..2952d66 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -35,11 +35,8 @@ import ( "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" - hconsts "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/crypto/ed25519" - "github.com/ava-labs/hypersdk/pubsub" hrpc "github.com/ava-labs/hypersdk/rpc" - hutils "github.com/ava-labs/hypersdk/utils" "github.com/ava-labs/hypersdk/vm" "github.com/nuklai/nuklaivm/actions" @@ -86,7 +83,7 @@ func init() { flag.IntVar( &vms, "vms", - 3, + 5, "number of VMs to create", ) } @@ -122,6 +119,19 @@ var ( networkID uint32 gen *genesis.Genesis + + //to be reordered staking vars + currentTime time.Time + stakeStartTime time.Time + stakeEndTime time.Time + delegationFeeRate int + withdraw0 string + withdraw1 string + rwithdraw0 codec.Address + rwithdraw1 codec.Address + rdelegate codec.Address + // parser0 chain.Parser + // err error ) type instance struct { @@ -301,1252 +311,1333 @@ var _ = ginkgo.AfterSuite(func() { } }) -var _ = ginkgo.Describe("[Ping]", func() { - ginkgo.It("can ping", func() { - for _, inst := range instances { - hcli := inst.hcli - ok, err := hcli.Ping(context.Background()) - gomega.Ω(ok).Should(gomega.BeTrue()) +// var _ = ginkgo.Describe("[Ping]", func() { +// ginkgo.It("can ping", func() { +// if skip { +// ginkgo.Skip("skip can ping") +// } +// for _, inst := range instances { +// hcli := inst.hcli +// ok, err := hcli.Ping(context.Background()) +// gomega.Ω(ok).Should(gomega.BeTrue()) +// gomega.Ω(err).Should(gomega.BeNil()) +// } +// }) +// }) + +// var _ = ginkgo.Describe("[Network]", func() { +// ginkgo.It("can get network", func() { +// for _, inst := range instances { +// hcli := inst.hcli +// networkID, subnetID, chainID, err := hcli.Network(context.Background()) +// gomega.Ω(networkID).Should(gomega.Equal(uint32(1))) +// gomega.Ω(subnetID).ShouldNot(gomega.Equal(ids.Empty)) +// gomega.Ω(chainID).ShouldNot(gomega.Equal(ids.Empty)) +// gomega.Ω(err).Should(gomega.BeNil()) +// } +// }) +// }) + +// var _ = ginkgo.Describe("[Tx Processing]", func() { +// ginkgo.It("get currently accepted block ID", func() { +// for _, inst := range instances { +// hcli := inst.hcli +// _, _, _, err := hcli.Accepted(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// } +// }) + +// var transferTxRoot *chain.Transaction +// ginkgo.It("Gossip TransferTx to a different node", func() { +// ginkgo.By("issue TransferTx", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 100_000, // must be more than StateLockup +// }, +// factory, +// ) +// transferTxRoot = transferTx +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) +// }) + +// ginkgo.By("skip duplicate", func() { +// _, err := instances[0].hcli.SubmitTx( +// context.Background(), +// transferTxRoot.Bytes(), +// ) +// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) +// }) + +// ginkgo.By("send gossip from node 0 to 1", func() { +// err := instances[0].vm.Gossiper().Force(context.TODO()) +// gomega.Ω(err).Should(gomega.BeNil()) +// }) + +// ginkgo.By("skip invalid time", func() { +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: 0, +// MaxFee: 1000, +// }, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 110, +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // 0 timestamp) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) +// }) + +// ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { +// _, err := instances[0].hcli.SubmitTx( +// context.Background(), +// transferTxRoot.Bytes(), +// ) +// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) +// }) + +// ginkgo.By("receive gossip in the node 1, and signal block build", func() { +// gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) +// <-instances[1].toEngine +// }) + +// ginkgo.By("build block in the node 1", func() { +// ctx := context.TODO() +// blk, err := instances[1].vm.BuildBlock(ctx) +// gomega.Ω(err).To(gomega.BeNil()) + +// gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) +// gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + +// err = instances[1].vm.SetPreference(ctx, blk.ID()) +// gomega.Ω(err).To(gomega.BeNil()) + +// gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) +// gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) +// blocks = append(blocks, blk) + +// lastAccepted, err := instances[1].vm.LastAccepted(ctx) +// gomega.Ω(err).To(gomega.BeNil()) +// gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + +// results := blk.(*chain.StatelessBlock).Results() +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) +// gomega.Ω(results[0].Output).Should(gomega.BeNil()) + +// // Unit explanation +// // +// // bandwidth: tx size +// // compute: 5 for signature, 1 for base, 1 for transfer +// // read: 2 keys reads, 1 had 0 chunks +// // allocate: 1 key created +// // write: 1 key modified, 1 key new +// transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} +// gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) + +// // Fee explanation +// // +// // Multiply all unit consumption by 1 and sum +// gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) +// }) + +// ginkgo.By("ensure balance is updated", func() { +// balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) +// gomega.Ω(err).To(gomega.BeNil()) +// gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) +// balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) +// gomega.Ω(err).To(gomega.BeNil()) +// gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) +// }) +// }) + +// ginkgo.It("ensure multiple txs work ", func() { +// ginkgo.By("transfer funds again", func() { +// parser, err := instances[1].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[1].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 101, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// time.Sleep(2 * time.Second) // for replay test +// accept := expectBlk(instances[1]) +// results := accept(true) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) +// gomega.Ω(err).To(gomega.BeNil()) +// gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) +// }) +// }) + +// ginkgo.It("Test processing block handling", func() { +// var accept, accept2 func(bool) []*chain.Result + +// ginkgo.By("create processing tip", func() { +// parser, err := instances[1].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[1].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 200, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// time.Sleep(2 * time.Second) // for replay test +// accept = expectBlk(instances[1]) + +// submit, _, _, err = instances[1].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 201, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// time.Sleep(2 * time.Second) // for replay test +// accept2 = expectBlk(instances[1]) +// }) + +// ginkgo.By("clear processing tip", func() { +// results := accept(true) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) +// results = accept2(true) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) +// }) +// }) + +// ginkgo.It("ensure mempool works", func() { +// ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { +// parser, err := instances[1].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[1].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: rsender2, +// Value: 203, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + +// err = instances[1].vm.Gossiper().Force(context.TODO()) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // mempool in 0 should be 1 (old amount), since gossip/submit failed +// gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) +// }) +// }) + +// ginkgo.It("ensure unprocessed tip and replay protection works", func() { +// ginkgo.By("import accepted blocks to instance 2", func() { +// ctx := context.TODO() + +// gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) + +// n := instances[2] +// blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk1.Verify(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Parse tip +// blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) +// gomega.Ω(err).Should(gomega.BeNil()) +// blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Verify tip +// err = blk2.Verify(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk3.Verify(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Check if tx from old block would be considered a repeat on processing tip +// tx := blk2.(*chain.StatelessBlock).Txs[0] +// sblk3 := blk3.(*chain.StatelessBlock) +// sblk3t := sblk3.Timestamp().UnixMilli() +// ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(ok.Len()).Should(gomega.Equal(1)) + +// // Accept tip +// err = blk1.Accept(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk2.Accept(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk3.Accept(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Parse another +// blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk4.Verify(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) +// err = blk4.Accept(ctx) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Check if tx from old block would be considered a repeat on accepted tip +// time.Sleep(2 * time.Second) +// gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) +// }) +// }) + +// ginkgo.It("processes valid index transactions (w/block listening)", func() { +// // Clear previous txs on instance 0 +// accept := expectBlk(instances[0]) +// accept(false) // don't care about results + +// // Subscribe to blocks +// hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) + +// // Wait for message to be sent +// time.Sleep(2 * pubsub.MaxMessageWait) + +// // Fetch balances +// balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Send tx +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// transfer := &actions.Transfer{ +// To: auth.NewED25519Address(other.PublicKey()), +// Value: 1, +// } + +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// transfer, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + +// gomega.Ω(err).Should(gomega.BeNil()) +// accept = expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// // Read item from connection +// blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) +// tx := blk.Txs[0].Action.(*actions.Transfer) +// gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) +// gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) +// gomega.Ω(lresults).Should(gomega.Equal(results)) +// gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) + +// // Check balance modifications are correct +// balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) + +// // Close connection when done +// gomega.Ω(hcli.Close()).Should(gomega.BeNil()) +// }) + +// ginkgo.It("processes valid index transactions (w/streaming verification)", func() { +// // Create streaming client +// hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Create tx +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// transfer := &actions.Transfer{ +// To: auth.NewED25519Address(other.PublicKey()), +// Value: 1, +// } +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// _, tx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// transfer, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) + +// // Submit tx and accept block +// gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) + +// // Wait for message to be sent +// time.Sleep(2 * pubsub.MaxMessageWait) + +// for instances[0].vm.Mempool().Len(context.TODO()) == 0 { +// // We need to wait for mempool to be populated because issuance will +// // return as soon as bytes are on the channel. +// hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") +// time.Sleep(500 * time.Millisecond) +// } +// gomega.Ω(err).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// // Read decision from connection +// txID, dErr, result, err := hcli.ListenTx(context.TODO()) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(txID).Should(gomega.Equal(tx.ID())) +// gomega.Ω(dErr).Should(gomega.BeNil()) +// gomega.Ω(result.Success).Should(gomega.BeTrue()) +// gomega.Ω(result).Should(gomega.Equal(results[0])) + +// // Close connection when done +// gomega.Ω(hcli.Close()).Should(gomega.BeNil()) +// }) + +// ginkgo.It("transfer an asset with a memo", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.Transfer{ +// To: auth.NewED25519Address(other.PublicKey()), +// Value: 10, +// Memo: []byte("hello"), +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeTrue()) +// }) + +// ginkgo.It("transfer an asset with large memo", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1001, +// }, +// nil, +// &actions.Transfer{ +// To: auth.NewED25519Address(other.PublicKey()), +// Value: 10, +// Memo: make([]byte, 1000), +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // too large) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) +// }) + +// ginkgo.It("mint an asset that doesn't exist", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// assetID := ids.GenerateTestID() +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: auth.NewED25519Address(other.PublicKey()), +// Asset: assetID, +// Value: 10, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)). +// Should(gomega.ContainSubstring("asset missing")) + +// exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("create a new asset (no metadata)", func() { +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1001, +// }, +// nil, +// &actions.CreateAsset{ +// Symbol: []byte("s0"), +// Decimals: 0, +// Metadata: nil, +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // too large) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) +// }) + +// ginkgo.It("create a new asset (no symbol)", func() { +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1001, +// }, +// nil, +// &actions.CreateAsset{ +// Symbol: nil, +// Decimals: 0, +// Metadata: []byte("m"), +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // too large) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) +// }) + +// ginkgo.It("create asset with too long of metadata", func() { +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// nil, +// &actions.CreateAsset{ +// Symbol: []byte("s0"), +// Decimals: 0, +// Metadata: make([]byte, actions.MaxMetadataSize*2), +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // too large) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) +// }) + +// ginkgo.It("create a new asset (simple metadata)", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, tx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.CreateAsset{ +// Symbol: asset1Symbol, +// Decimals: asset1Decimals, +// Metadata: asset1, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// asset1ID = tx.ID() +// balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(0))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("mint a new asset", func() { +// fmt.Println("MINT ASSET") +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: rsender2, +// Asset: asset1ID, +// Value: 15, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(15))) +// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(15))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("mint asset from wrong owner", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: auth.NewED25519Address(other.PublicKey()), +// Asset: asset1ID, +// Value: 10, +// }, +// factory2, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)). +// Should(gomega.ContainSubstring("wrong owner")) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(15))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("burn new asset", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.BurnAsset{ +// Asset: asset1ID, +// Value: 5, +// }, +// factory2, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) +// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("burn missing asset", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.BurnAsset{ +// Asset: asset1ID, +// Value: 10, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)). +// Should(gomega.ContainSubstring("invalid balance")) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("rejects empty mint", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// nil, +// &actions.MintAsset{ +// To: auth.NewED25519Address(other.PublicKey()), +// Asset: asset1ID, +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // bad codec) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) +// }) + +// ginkgo.It("reject max mint", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: rsender2, +// Asset: asset1ID, +// Value: hconsts.MaxUint64, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)). +// Should(gomega.ContainSubstring("overflow")) + +// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) +// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + +// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(exists).Should(gomega.BeTrue()) +// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) +// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) +// gomega.Ω(metadata).Should(gomega.Equal(asset1)) +// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) +// gomega.Ω(owner).Should(gomega.Equal(sender)) +// gomega.Ω(warp).Should(gomega.BeFalse()) +// }) + +// ginkgo.It("rejects mint of native token", func() { +// other, err := ed25519.GeneratePrivateKey() +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// nil, +// &actions.MintAsset{ +// To: auth.NewED25519Address(other.PublicKey()), +// Value: 10, +// }, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // bad codec) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) +// }) + +// ginkgo.It("mints another new asset (to self)", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, tx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.CreateAsset{ +// Symbol: asset2Symbol, +// Decimals: asset2Decimals, +// Metadata: asset2, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) +// asset2ID = tx.ID() + +// submit, _, _, err = instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: rsender, +// Asset: asset2ID, +// Value: 10, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept = expectBlk(instances[0]) +// results = accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) +// }) + +// ginkgo.It("mints another new asset (to self) on another account", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, tx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.CreateAsset{ +// Symbol: asset3Symbol, +// Decimals: asset3Decimals, +// Metadata: asset3, +// }, +// factory2, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) +// asset3ID = tx.ID() + +// submit, _, _, err = instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.MintAsset{ +// To: rsender2, +// Asset: asset3ID, +// Value: 10, +// }, +// factory2, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept = expectBlk(instances[0]) +// results = accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + +// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) +// }) + +// ginkgo.It("import warp message with nil when expected", func() { +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// nil, +// &actions.ImportAsset{}, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // empty warp) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) +// }) + +// ginkgo.It("import warp message empty", func() { +// wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// wm, +// &actions.ImportAsset{}, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // empty warp) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) +// }) + +// ginkgo.It("import with wrong payload", func() { +// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) +// gomega.Ω(err).Should(gomega.BeNil()) +// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// wm, +// &actions.ImportAsset{}, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // invalid object) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) +// }) + +// ginkgo.It("import with invalid payload", func() { +// wt := &actions.WarpTransfer{} +// wtb, err := wt.Marshal() +// gomega.Ω(err).Should(gomega.BeNil()) +// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) +// gomega.Ω(err).Should(gomega.BeNil()) +// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) +// gomega.Ω(err).Should(gomega.BeNil()) +// tx := chain.NewTx( +// &chain.Base{ +// ChainID: instances[0].chainID, +// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), +// MaxFee: 1000, +// }, +// wm, +// &actions.ImportAsset{}, +// ) +// // Must do manual construction to avoid `tx.Sign` error (would fail with +// // invalid object) +// msg, err := tx.Digest() +// gomega.Ω(err).To(gomega.BeNil()) +// auth, err := factory.Sign(msg) +// gomega.Ω(err).To(gomega.BeNil()) +// tx.Auth = auth +// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth +// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) +// gomega.Ω(p.Err()).To(gomega.BeNil()) +// _, err = instances[0].hcli.SubmitTx( +// context.Background(), +// p.Bytes(), +// ) +// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) +// }) + +// ginkgo.It("import with wrong destination", func() { +// wt := &actions.WarpTransfer{ +// To: rsender, +// Symbol: []byte("s"), +// Decimals: 2, +// Asset: ids.GenerateTestID(), +// Value: 100, +// Return: false, +// Reward: 100, +// TxID: ids.GenerateTestID(), +// DestinationChainID: ids.GenerateTestID(), +// } +// wtb, err := wt.Marshal() +// gomega.Ω(err).Should(gomega.BeNil()) +// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) +// gomega.Ω(err).Should(gomega.BeNil()) +// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) +// gomega.Ω(err).Should(gomega.BeNil()) +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// wm, +// &actions.ImportAsset{}, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + +// // Build block with no context (should fail) +// gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) +// <-instances[0].toEngine +// blk, err := instances[0].vm.BuildBlock(context.TODO()) +// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) +// gomega.Ω(blk).To(gomega.BeNil()) + +// // Wait for mempool to be size 1 (txs are restored async) +// for { +// if instances[0].vm.Mempool().Len(context.Background()) > 0 { +// break +// } +// log.Info("waiting for txs to be restored") +// time.Sleep(100 * time.Millisecond) +// } + +// // Build block with context +// accept := expectBlkWithContext(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) +// }) + +// ginkgo.It("export native asset", func() { +// dest := ids.GenerateTestID() +// loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(loan).Should(gomega.Equal(uint64(0))) + +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, tx, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.ExportAsset{ +// To: rsender, +// Asset: ids.Empty, +// Value: 100, +// Return: false, +// Reward: 10, +// Destination: dest, +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeTrue()) +// wt := &actions.WarpTransfer{ +// To: rsender, +// Symbol: []byte(nconsts.Symbol), +// Decimals: nconsts.Decimals, +// Asset: ids.Empty, +// Value: 100, +// Return: false, +// Reward: 10, +// TxID: tx.ID(), +// DestinationChainID: dest, +// } +// wtb, err := wt.Marshal() +// gomega.Ω(err).Should(gomega.BeNil()) +// wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) + +// loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(loan).Should(gomega.Equal(uint64(110))) +// }) + +// ginkgo.It("export native asset (invalid return)", func() { +// parser, err := instances[0].ncli.Parser(context.Background()) +// gomega.Ω(err).Should(gomega.BeNil()) +// submit, _, _, err := instances[0].hcli.GenerateTransaction( +// context.Background(), +// parser, +// nil, +// &actions.ExportAsset{ +// To: rsender, +// Asset: ids.Empty, +// Value: 100, +// Return: true, +// Reward: 10, +// Destination: ids.GenerateTestID(), +// }, +// factory, +// ) +// gomega.Ω(err).Should(gomega.BeNil()) +// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) +// accept := expectBlk(instances[0]) +// results := accept(false) +// gomega.Ω(results).Should(gomega.HaveLen(1)) +// result := results[0] +// gomega.Ω(result.Success).Should(gomega.BeFalse()) +// gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) +// }) +// }) + +var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { + // var err error + ginkgo.It("Setup and get initial staked validators", func() { + ginkgo.By("Set up", func() { + currentTime = time.Now().UTC() + stakeStartTime = currentTime.Add(2 * time.Minute) + stakeEndTime = currentTime.Add(15 * time.Minute) + delegationFeeRate = 50 + + withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - } - }) -}) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) -var _ = ginkgo.Describe("[Network]", func() { - ginkgo.It("can get network", func() { - for _, inst := range instances { - hcli := inst.hcli - networkID, subnetID, chainID, err := hcli.Network(context.Background()) - gomega.Ω(networkID).Should(gomega.Equal(uint32(1))) - gomega.Ω(subnetID).ShouldNot(gomega.Equal(ids.Empty)) - gomega.Ω(chainID).ShouldNot(gomega.Equal(ids.Empty)) + withdraw1Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - } - }) -}) + rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) + withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) -var _ = ginkgo.Describe("[Tx Processing]", func() { - ginkgo.It("get currently accepted block ID", func() { - for _, inst := range instances { - hcli := inst.hcli - _, _, _, err := hcli.Accepted(context.Background()) + delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - } - }) - - var transferTxRoot *chain.Transaction - ginkgo.It("Gossip TransferTx to a different node", func() { - ginkgo.By("issue TransferTx", func() { - parser, err := instances[0].ncli.Parser(context.Background()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + validators, err := instances[3].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 100_000, // must be more than StateLockup - }, - factory, - ) - transferTxRoot = transferTx - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) }) - ginkgo.By("skip duplicate", func() { - _, err := instances[0].hcli.SubmitTx( - context.Background(), - transferTxRoot.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("send gossip from node 0 to 1", func() { - err := instances[0].vm.Gossiper().Force(context.TODO()) + ginkgo.By("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - }) - - ginkgo.By("skip invalid time", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: 0, - MaxFee: 1000, - }, - nil, - &actions.Transfer{ - To: rsender2, - Value: 110, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // 0 timestamp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { - _, err := instances[0].hcli.SubmitTx( - context.Background(), - transferTxRoot.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("receive gossip in the node 1, and signal block build", func() { - gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - <-instances[1].toEngine - }) - - ginkgo.By("build block in the node 1", func() { - ctx := context.TODO() - blk, err := instances[1].vm.BuildBlock(ctx) - gomega.Ω(err).To(gomega.BeNil()) - - gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = instances[1].vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - blocks = append(blocks, blk) - - lastAccepted, err := instances[1].vm.LastAccepted(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - results := blk.(*chain.StatelessBlock).Results() - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(results[0].Output).Should(gomega.BeNil()) - - // Unit explanation - // - // bandwidth: tx size - // compute: 5 for signature, 1 for base, 1 for transfer - // read: 2 keys reads, 1 had 0 chunks - // allocate: 1 key created - // write: 1 key modified, 1 key new - transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} - gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) - - // Fee explanation - // - // Multiply all unit consumption by 1 and sum - gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) - }) - - ginkgo.By("ensure balance is updated", func() { - balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) - balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) - }) - }) - - ginkgo.It("ensure multiple txs work ", func() { - ginkgo.By("transfer funds again", func() { - parser, err := instances[1].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 101, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept := expectBlk(instances[1]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) - }) - }) - - ginkgo.It("Test processing block handling", func() { - var accept, accept2 func(bool) []*chain.Result + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 1000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } - ginkgo.By("create processing tip", func() { - parser, err := instances[1].ncli.Parser(context.Background()) + stakeInfoBytes, err := stakeInfo.Marshal() gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 200, - }, - factory, - ) + signature, err := factory.Sign(stakeInfoBytes) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept = expectBlk(instances[1]) - - submit, _, _, err = instances[1].hcli.GenerateTransaction( + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.Transfer{ - To: rsender2, - Value: 201, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, }, factory, ) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept2 = expectBlk(instances[1]) - }) - - ginkgo.By("clear processing tip", func() { - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - results = accept2(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - }) - }) - - ginkgo.It("ensure mempool works", func() { - ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { - parser, err := instances[1].ncli.Parser(context.Background()) + genesis, err := instances[3].ncli.Genesis(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 203, - }, - factory, - ) + alloc := genesis.CustomAllocation + fmt.Printf("ALLOC LEN %d", len(alloc)) + balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("BALANCE INSTANCES[3] %d", balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - err = instances[1].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - - // mempool in 0 should be 1 (old amount), since gossip/submit failed - gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + time.Sleep(10000 * time.Millisecond) }) - }) - - ginkgo.It("ensure unprocessed tip and replay protection works", func() { - ginkgo.By("import accepted blocks to instance 2", func() { - ctx := context.TODO() - - gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) - - n := instances[2] - blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Parse tip - blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - - // Verify tip - err = blk2.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk3.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Check if tx from old block would be considered a repeat on processing tip - tx := blk2.(*chain.StatelessBlock).Txs[0] - sblk3 := blk3.(*chain.StatelessBlock) - sblk3t := sblk3.Timestamp().UnixMilli() - ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - // Accept tip - err = blk1.Accept(ctx) + ginkgo.By("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk3.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Parse another - blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk4.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk4.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Check if tx from old block would be considered a repeat on accepted tip - time.Sleep(2 * time.Second) - gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) + gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals }) }) - - ginkgo.It("processes valid index transactions (w/block listening)", func() { - // Clear previous txs on instance 0 - accept := expectBlk(instances[0]) - accept(false) // don't care about results - - // Subscribe to blocks - hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) - - // Wait for message to be sent - time.Sleep(2 * pubsub.MaxMessageWait) - - // Fetch balances - balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - // Send tx - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - transfer := &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 1, - } - - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - transfer, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - gomega.Ω(err).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // Read item from connection - blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) - tx := blk.Txs[0].Action.(*actions.Transfer) - gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) - gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) - gomega.Ω(lresults).Should(gomega.Equal(results)) - gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) - - // Check balance modifications are correct - balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) - - // Close connection when done - gomega.Ω(hcli.Close()).Should(gomega.BeNil()) - }) - - ginkgo.It("processes valid index transactions (w/streaming verification)", func() { - // Create streaming client - hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) - gomega.Ω(err).Should(gomega.BeNil()) - - // Create tx - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - transfer := &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 1, - } - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - _, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - transfer, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - - // Submit tx and accept block - gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) - - // Wait for message to be sent - time.Sleep(2 * pubsub.MaxMessageWait) - - for instances[0].vm.Mempool().Len(context.TODO()) == 0 { - // We need to wait for mempool to be populated because issuance will - // return as soon as bytes are on the channel. - hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") - time.Sleep(500 * time.Millisecond) - } - gomega.Ω(err).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // Read decision from connection - txID, dErr, result, err := hcli.ListenTx(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(txID).Should(gomega.Equal(tx.ID())) - gomega.Ω(dErr).Should(gomega.BeNil()) - gomega.Ω(result.Success).Should(gomega.BeTrue()) - gomega.Ω(result).Should(gomega.Equal(results[0])) - - // Close connection when done - gomega.Ω(hcli.Close()).Should(gomega.BeNil()) - }) - - ginkgo.It("transfer an asset with a memo", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - Memo: []byte("hello"), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeTrue()) - }) - - ginkgo.It("transfer an asset with large memo", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - Memo: make([]byte, 1000), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) - }) - - ginkgo.It("mint an asset that doesn't exist", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - assetID := ids.GenerateTestID() - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: assetID, - Value: 10, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("asset missing")) - - exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeFalse()) - }) - - ginkgo.It("create a new asset (no metadata)", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.CreateAsset{ - Symbol: []byte("s0"), - Decimals: 0, - Metadata: nil, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - }) - - ginkgo.It("create a new asset (no symbol)", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.CreateAsset{ - Symbol: nil, - Decimals: 0, - Metadata: []byte("m"), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - }) - - ginkgo.It("create asset with too long of metadata", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.CreateAsset{ - Symbol: []byte("s0"), - Decimals: 0, - Metadata: make([]byte, actions.MaxMetadataSize*2), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) - }) - - ginkgo.It("create a new asset (simple metadata)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset1Symbol, - Decimals: asset1Decimals, - Metadata: asset1, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - asset1ID = tx.ID() - balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(0))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("mint a new asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset1ID, - Value: 15, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(15))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(15))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("mint asset from wrong owner", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: asset1ID, - Value: 10, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("wrong owner")) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(15))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("burn new asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.BurnAsset{ - Asset: asset1ID, - Value: 5, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("burn missing asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.BurnAsset{ - Asset: asset1ID, - Value: 10, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("invalid balance")) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("rejects empty mint", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: asset1ID, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // bad codec) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) - }) - - ginkgo.It("reject max mint", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset1ID, - Value: hconsts.MaxUint64, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("overflow")) - - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("rejects mint of native token", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // bad codec) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) - }) - - ginkgo.It("mints another new asset (to self)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset2Symbol, - Decimals: asset2Decimals, - Metadata: asset2, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - asset2ID = tx.ID() - - submit, _, _, err = instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender, - Asset: asset2ID, - Value: 10, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results = accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - }) - - ginkgo.It("mints another new asset (to self) on another account", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset3Symbol, - Decimals: asset3Decimals, - Metadata: asset3, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - asset3ID = tx.ID() - - submit, _, _, err = instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset3ID, - Value: 10, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results = accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - }) - - ginkgo.It("import warp message with nil when expected", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // empty warp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) - }) - - ginkgo.It("import warp message empty", func() { - wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // empty warp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) - }) - - ginkgo.It("import with wrong payload", func() { - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // invalid object) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) - }) - - ginkgo.It("import with invalid payload", func() { - wt := &actions.WarpTransfer{} - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // invalid object) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) - }) - - ginkgo.It("import with wrong destination", func() { - wt := &actions.WarpTransfer{ - To: rsender, - Symbol: []byte("s"), - Decimals: 2, - Asset: ids.GenerateTestID(), - Value: 100, - Return: false, - Reward: 100, - TxID: ids.GenerateTestID(), - DestinationChainID: ids.GenerateTestID(), - } - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - wm, - &actions.ImportAsset{}, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - // Build block with no context (should fail) - gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - <-instances[0].toEngine - blk, err := instances[0].vm.BuildBlock(context.TODO()) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - gomega.Ω(blk).To(gomega.BeNil()) - - // Wait for mempool to be size 1 (txs are restored async) - for { - if instances[0].vm.Mempool().Len(context.Background()) > 0 { - break - } - log.Info("waiting for txs to be restored") - time.Sleep(100 * time.Millisecond) - } - - // Build block with context - accept := expectBlkWithContext(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) - }) - - ginkgo.It("export native asset", func() { - dest := ids.GenerateTestID() - loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(loan).Should(gomega.Equal(uint64(0))) - - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ExportAsset{ - To: rsender, - Asset: ids.Empty, - Value: 100, - Return: false, - Reward: 10, - Destination: dest, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeTrue()) - wt := &actions.WarpTransfer{ - To: rsender, - Symbol: []byte(nconsts.Symbol), - Decimals: nconsts.Decimals, - Asset: ids.Empty, - Value: 100, - Return: false, - Reward: 10, - TxID: tx.ID(), - DestinationChainID: dest, - } - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) - - loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(loan).Should(gomega.Equal(uint64(110))) - }) - - ginkgo.It("export native asset (invalid return)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ExportAsset{ - To: rsender, - Asset: ids.Empty, - Value: 100, - Return: true, - Reward: 10, - Destination: ids.GenerateTestID(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) - }) }) func expectBlk(i instance) func(bool) []*chain.Result { diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go deleted file mode 100644 index dee7f3e..0000000 --- a/tests/integration/new_actions_test.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (C) 2024, AllianceBlock. All rights reserved. -// See the file LICENSE for licensing terms. - -package integration_test - -import ( - "context" - "testing" - "time" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/logging" - ginkgo "github.com/onsi/ginkgo/v2" - "github.com/onsi/gomega" - - "github.com/ava-labs/hypersdk/codec" - "github.com/ava-labs/hypersdk/crypto/ed25519" - - "github.com/nuklai/nuklaivm/actions" - "github.com/nuklai/nuklaivm/auth" - nconsts "github.com/nuklai/nuklaivm/consts" -) - -func init() { - logFactory = logging.NewFactory(logging.Config{ - DisplayLevel: logging.Debug, - }) - l, err := logFactory.Make("main") - if err != nil { - panic(err) - } - log = l -} - -func TestNewActions(t *testing.T) { - gomega.RegisterFailHandler(ginkgo.Fail) - ginkgo.RunSpecs(t, "nuklaivm new actions integration tests") -} - -var _ = ginkgo.Describe("nuklai staking mechanism", func() { - ginkgo.It("Auto register validator stake", func() { - currentTime := time.Now().UTC() - stakeStartTime := currentTime.Add(2 * time.Minute) - stakeEndTime := currentTime.Add(15 * time.Minute) - delegationFeeRate := 50 - - parser0, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - parser1, err := instances[1].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) - withdraw0 := codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - - withdraw1Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - // withdraw0Factory := auth.NewED25519Factory(priv1Withdraw) - withdraw1 := auth.NewED25519Address(withdraw1Priv.PublicKey()) - - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - delegateFactory := auth.NewED25519Factory(delegatePriv) - rdelegate := auth.NewED25519Address(delegatePriv.PublicKey()) - delegate := codec.MustAddressBech32(nconsts.HRP, rdelegate) - - ginkgo.By("Register validator stake instances[0] with zero balance", func() { - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[0].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := factory.Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - factory, - ) - gomega.Ω(err).Should(gomega.HaveOccurred()) - gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) - }) - - ginkgo.By("Get staked validators", func() { - validators, err := instances[0].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) - - ginkgo.By("Register validator stake instances[1] with zero balance", func() { - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[1].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: withdraw1, - } - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := factory.Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser1, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - factory, - ) - gomega.Ω(err).Should(gomega.HaveOccurred()) - gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) - }) - - ginkgo.By("Get validator staked amount after staking", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - }) - - ginkgo.By("Get staked validators", func() { - validators, err := instances[0].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(2)) - }) - - ginkgo.By("Transfer NAI to user and delegate stake to instances[0]", func() { - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.Transfer{ - To: rdelegate, - Asset: ids.Empty, - Value: 100, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(2 * time.Minute) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err = instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.DelegateUserStake{ - NodeID: instances[0].nodeID.Bytes(), - StakeStartTime: uint64(userStakeStartTime.Unix()), - StakedAmount: 50, - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - }) - - ginkgo.By("Get user stake before claim", func() { - _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) - }) - - ginkgo.By("Claim delegation stake rewards from instances[0]", func() { - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.ClaimDelegationStakeRewards{ - NodeID: instances[0].nodeID.Bytes(), - UserStakeAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - }) - - ginkgo.By("Get user stake after claim", func() { - _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) - }) - - ginkgo.By("Undelegate user stake from instances[0]", func() { - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.UndelegateUserStake{ - NodeID: instances[0].nodeID.Bytes(), - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - }) - - // add more ginko.By where error should be thrown with wrong data input - ginkgo.By("Claim validator instances[0] stake reward", func() { - // ClaimValidatorStakeRewards - // TO DO: test claim with a wrong key - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.ClaimValidatorStakeRewards{ - NodeID: instances[0].nodeID.Bytes(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - }) - - ginkgo.By("Withdraw validator instances[0] stake", func() { - // WithdrawValidatorStake - // TO DO: test claim with a wrong key - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser0, - nil, - &actions.WithdrawValidatorStake{ - NodeID: instances[0].nodeID.Bytes(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - }) - - ginkgo.By("Get validator stake after staking withdraw ", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - }) - }) -}) From bb5963d9202961d7b158f3417dfa9ecb8bc45976 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 10 Apr 2024 17:36:54 +0100 Subject: [PATCH 04/78] delete unit tests second file --- tests/e2e/e2e_new_actions.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/e2e/e2e_new_actions.go diff --git a/tests/e2e/e2e_new_actions.go b/tests/e2e/e2e_new_actions.go deleted file mode 100644 index e69de29..0000000 From df29b2375e8c28fab1f6ee9f10c8227145b6b04c Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 10 Apr 2024 18:44:42 +0100 Subject: [PATCH 05/78] use It --- tests/integration/integration_test.go | 132 +++++++++++++------------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 2952d66..83fdc5f 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -1566,77 +1566,75 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // var err error ginkgo.It("Setup and get initial staked validators", func() { - ginkgo.By("Set up", func() { - currentTime = time.Now().UTC() - stakeStartTime = currentTime.Add(2 * time.Minute) - stakeEndTime = currentTime.Add(15 * time.Minute) - delegationFeeRate = 50 + currentTime = time.Now().UTC() + stakeStartTime = currentTime.Add(2 * time.Minute) + stakeEndTime = currentTime.Add(15 * time.Minute) + delegationFeeRate = 50 - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) - withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - withdraw1Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) - withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) + withdraw1Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) + withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + validators, err := instances[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) - ginkgo.By("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 1000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := factory.Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - genesis, err := instances[3].ncli.Genesis(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - alloc := genesis.CustomAllocation - fmt.Printf("ALLOC LEN %d", len(alloc)) - balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("BALANCE INSTANCES[3] %d", balance) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(10000 * time.Millisecond) - }) - - ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals - }) + ginkgo.It("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 1000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := factory.Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // genesis, err := instances[3].ncli.Genesis(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // alloc := genesis.CustomAllocation + // fmt.Printf("ALLOC LEN %d", len(alloc)) + // balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + // fmt.Printf("BALANCE INSTANCES[3] %d", balance) + time.Sleep(5000 * time.Millisecond) + }) + + ginkgo.It("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals }) }) From dfdcd117789135e833ca58e6d45d9f47c8600c1b Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 11 Apr 2024 11:08:56 +0100 Subject: [PATCH 06/78] set parallelism to 5 --- tests/integration/integration_test.go | 2532 +++++++++++++------------ 1 file changed, 1267 insertions(+), 1265 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 83fdc5f..52d27a8 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -240,7 +240,7 @@ var _ = ginkgo.BeforeSuite(func() { genesisBytes, nil, []byte( - `{"parallelism":3, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, + `{"parallelism":5, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, ), toEngine, nil, @@ -338,1230 +338,1230 @@ var _ = ginkgo.AfterSuite(func() { // }) // }) -// var _ = ginkgo.Describe("[Tx Processing]", func() { -// ginkgo.It("get currently accepted block ID", func() { -// for _, inst := range instances { -// hcli := inst.hcli -// _, _, _, err := hcli.Accepted(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// } -// }) - -// var transferTxRoot *chain.Transaction -// ginkgo.It("Gossip TransferTx to a different node", func() { -// ginkgo.By("issue TransferTx", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 100_000, // must be more than StateLockup -// }, -// factory, -// ) -// transferTxRoot = transferTx -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) -// }) - -// ginkgo.By("skip duplicate", func() { -// _, err := instances[0].hcli.SubmitTx( -// context.Background(), -// transferTxRoot.Bytes(), -// ) -// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) -// }) - -// ginkgo.By("send gossip from node 0 to 1", func() { -// err := instances[0].vm.Gossiper().Force(context.TODO()) -// gomega.Ω(err).Should(gomega.BeNil()) -// }) - -// ginkgo.By("skip invalid time", func() { -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: 0, -// MaxFee: 1000, -// }, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 110, -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // 0 timestamp) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) -// }) - -// ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { -// _, err := instances[0].hcli.SubmitTx( -// context.Background(), -// transferTxRoot.Bytes(), -// ) -// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) -// }) - -// ginkgo.By("receive gossip in the node 1, and signal block build", func() { -// gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) -// <-instances[1].toEngine -// }) - -// ginkgo.By("build block in the node 1", func() { -// ctx := context.TODO() -// blk, err := instances[1].vm.BuildBlock(ctx) -// gomega.Ω(err).To(gomega.BeNil()) - -// gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) -// gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - -// err = instances[1].vm.SetPreference(ctx, blk.ID()) -// gomega.Ω(err).To(gomega.BeNil()) - -// gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) -// gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) -// blocks = append(blocks, blk) - -// lastAccepted, err := instances[1].vm.LastAccepted(ctx) -// gomega.Ω(err).To(gomega.BeNil()) -// gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - -// results := blk.(*chain.StatelessBlock).Results() -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// gomega.Ω(results[0].Output).Should(gomega.BeNil()) - -// // Unit explanation -// // -// // bandwidth: tx size -// // compute: 5 for signature, 1 for base, 1 for transfer -// // read: 2 keys reads, 1 had 0 chunks -// // allocate: 1 key created -// // write: 1 key modified, 1 key new -// transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} -// gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) - -// // Fee explanation -// // -// // Multiply all unit consumption by 1 and sum -// gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) -// }) - -// ginkgo.By("ensure balance is updated", func() { -// balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) -// gomega.Ω(err).To(gomega.BeNil()) -// gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) -// balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) -// gomega.Ω(err).To(gomega.BeNil()) -// gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) -// }) -// }) - -// ginkgo.It("ensure multiple txs work ", func() { -// ginkgo.By("transfer funds again", func() { -// parser, err := instances[1].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[1].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 101, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// time.Sleep(2 * time.Second) // for replay test -// accept := expectBlk(instances[1]) -// results := accept(true) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) -// gomega.Ω(err).To(gomega.BeNil()) -// gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) -// }) -// }) - -// ginkgo.It("Test processing block handling", func() { -// var accept, accept2 func(bool) []*chain.Result - -// ginkgo.By("create processing tip", func() { -// parser, err := instances[1].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[1].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 200, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// time.Sleep(2 * time.Second) // for replay test -// accept = expectBlk(instances[1]) - -// submit, _, _, err = instances[1].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 201, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// time.Sleep(2 * time.Second) // for replay test -// accept2 = expectBlk(instances[1]) -// }) - -// ginkgo.By("clear processing tip", func() { -// results := accept(true) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// results = accept2(true) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// }) -// }) - -// ginkgo.It("ensure mempool works", func() { -// ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { -// parser, err := instances[1].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[1].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: rsender2, -// Value: 203, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - -// err = instances[1].vm.Gossiper().Force(context.TODO()) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // mempool in 0 should be 1 (old amount), since gossip/submit failed -// gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) -// }) -// }) - -// ginkgo.It("ensure unprocessed tip and replay protection works", func() { -// ginkgo.By("import accepted blocks to instance 2", func() { -// ctx := context.TODO() - -// gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) - -// n := instances[2] -// blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk1.Verify(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Parse tip -// blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) -// gomega.Ω(err).Should(gomega.BeNil()) -// blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Verify tip -// err = blk2.Verify(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk3.Verify(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Check if tx from old block would be considered a repeat on processing tip -// tx := blk2.(*chain.StatelessBlock).Txs[0] -// sblk3 := blk3.(*chain.StatelessBlock) -// sblk3t := sblk3.Timestamp().UnixMilli() -// ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - -// // Accept tip -// err = blk1.Accept(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk2.Accept(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk3.Accept(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Parse another -// blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk4.Verify(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) -// err = blk4.Accept(ctx) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Check if tx from old block would be considered a repeat on accepted tip -// time.Sleep(2 * time.Second) -// gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) -// }) -// }) - -// ginkgo.It("processes valid index transactions (w/block listening)", func() { -// // Clear previous txs on instance 0 -// accept := expectBlk(instances[0]) -// accept(false) // don't care about results - -// // Subscribe to blocks -// hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) - -// // Wait for message to be sent -// time.Sleep(2 * pubsub.MaxMessageWait) - -// // Fetch balances -// balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Send tx -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// transfer := &actions.Transfer{ -// To: auth.NewED25519Address(other.PublicKey()), -// Value: 1, -// } - -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// transfer, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - -// gomega.Ω(err).Should(gomega.BeNil()) -// accept = expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// // Read item from connection -// blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) -// tx := blk.Txs[0].Action.(*actions.Transfer) -// gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) -// gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) -// gomega.Ω(lresults).Should(gomega.Equal(results)) -// gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) - -// // Check balance modifications are correct -// balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) - -// // Close connection when done -// gomega.Ω(hcli.Close()).Should(gomega.BeNil()) -// }) - -// ginkgo.It("processes valid index transactions (w/streaming verification)", func() { -// // Create streaming client -// hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Create tx -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// transfer := &actions.Transfer{ -// To: auth.NewED25519Address(other.PublicKey()), -// Value: 1, -// } -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// _, tx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// transfer, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) - -// // Submit tx and accept block -// gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) - -// // Wait for message to be sent -// time.Sleep(2 * pubsub.MaxMessageWait) - -// for instances[0].vm.Mempool().Len(context.TODO()) == 0 { -// // We need to wait for mempool to be populated because issuance will -// // return as soon as bytes are on the channel. -// hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") -// time.Sleep(500 * time.Millisecond) -// } -// gomega.Ω(err).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// // Read decision from connection -// txID, dErr, result, err := hcli.ListenTx(context.TODO()) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(txID).Should(gomega.Equal(tx.ID())) -// gomega.Ω(dErr).Should(gomega.BeNil()) -// gomega.Ω(result.Success).Should(gomega.BeTrue()) -// gomega.Ω(result).Should(gomega.Equal(results[0])) - -// // Close connection when done -// gomega.Ω(hcli.Close()).Should(gomega.BeNil()) -// }) - -// ginkgo.It("transfer an asset with a memo", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.Transfer{ -// To: auth.NewED25519Address(other.PublicKey()), -// Value: 10, -// Memo: []byte("hello"), -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeTrue()) -// }) - -// ginkgo.It("transfer an asset with large memo", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1001, -// }, -// nil, -// &actions.Transfer{ -// To: auth.NewED25519Address(other.PublicKey()), -// Value: 10, -// Memo: make([]byte, 1000), -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // too large) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) -// }) - -// ginkgo.It("mint an asset that doesn't exist", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// assetID := ids.GenerateTestID() -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: auth.NewED25519Address(other.PublicKey()), -// Asset: assetID, -// Value: 10, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)). -// Should(gomega.ContainSubstring("asset missing")) - -// exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("create a new asset (no metadata)", func() { -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1001, -// }, -// nil, -// &actions.CreateAsset{ -// Symbol: []byte("s0"), -// Decimals: 0, -// Metadata: nil, -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // too large) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) -// }) - -// ginkgo.It("create a new asset (no symbol)", func() { -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1001, -// }, -// nil, -// &actions.CreateAsset{ -// Symbol: nil, -// Decimals: 0, -// Metadata: []byte("m"), -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // too large) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) -// }) - -// ginkgo.It("create asset with too long of metadata", func() { -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// nil, -// &actions.CreateAsset{ -// Symbol: []byte("s0"), -// Decimals: 0, -// Metadata: make([]byte, actions.MaxMetadataSize*2), -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // too large) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) -// }) - -// ginkgo.It("create a new asset (simple metadata)", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, tx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.CreateAsset{ -// Symbol: asset1Symbol, -// Decimals: asset1Decimals, -// Metadata: asset1, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// asset1ID = tx.ID() -// balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(0))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("mint a new asset", func() { -// fmt.Println("MINT ASSET") -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: rsender2, -// Asset: asset1ID, -// Value: 15, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(15))) -// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(15))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("mint asset from wrong owner", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: auth.NewED25519Address(other.PublicKey()), -// Asset: asset1ID, -// Value: 10, -// }, -// factory2, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)). -// Should(gomega.ContainSubstring("wrong owner")) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(15))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("burn new asset", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.BurnAsset{ -// Asset: asset1ID, -// Value: 5, -// }, -// factory2, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) -// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("burn missing asset", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.BurnAsset{ -// Asset: asset1ID, -// Value: 10, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)). -// Should(gomega.ContainSubstring("invalid balance")) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("rejects empty mint", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// nil, -// &actions.MintAsset{ -// To: auth.NewED25519Address(other.PublicKey()), -// Asset: asset1ID, -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // bad codec) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) -// }) - -// ginkgo.It("reject max mint", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: rsender2, -// Asset: asset1ID, -// Value: hconsts.MaxUint64, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)). -// Should(gomega.ContainSubstring("overflow")) - -// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) -// balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - -// exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(exists).Should(gomega.BeTrue()) -// gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) -// gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) -// gomega.Ω(metadata).Should(gomega.Equal(asset1)) -// gomega.Ω(supply).Should(gomega.Equal(uint64(10))) -// gomega.Ω(owner).Should(gomega.Equal(sender)) -// gomega.Ω(warp).Should(gomega.BeFalse()) -// }) - -// ginkgo.It("rejects mint of native token", func() { -// other, err := ed25519.GeneratePrivateKey() -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// nil, -// &actions.MintAsset{ -// To: auth.NewED25519Address(other.PublicKey()), -// Value: 10, -// }, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // bad codec) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) -// }) - -// ginkgo.It("mints another new asset (to self)", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, tx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.CreateAsset{ -// Symbol: asset2Symbol, -// Decimals: asset2Decimals, -// Metadata: asset2, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// asset2ID = tx.ID() - -// submit, _, _, err = instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: rsender, -// Asset: asset2ID, -// Value: 10, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept = expectBlk(instances[0]) -// results = accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) -// }) - -// ginkgo.It("mints another new asset (to self) on another account", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, tx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.CreateAsset{ -// Symbol: asset3Symbol, -// Decimals: asset3Decimals, -// Metadata: asset3, -// }, -// factory2, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// asset3ID = tx.ID() - -// submit, _, _, err = instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.MintAsset{ -// To: rsender2, -// Asset: asset3ID, -// Value: 10, -// }, -// factory2, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept = expectBlk(instances[0]) -// results = accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - -// balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(balance).Should(gomega.Equal(uint64(10))) -// }) - -// ginkgo.It("import warp message with nil when expected", func() { -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// nil, -// &actions.ImportAsset{}, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // empty warp) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) -// }) - -// ginkgo.It("import warp message empty", func() { -// wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// wm, -// &actions.ImportAsset{}, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // empty warp) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) -// }) +var _ = ginkgo.Describe("[Tx Processing]", func() { + // ginkgo.It("get currently accepted block ID", func() { + // for _, inst := range instances { + // hcli := inst.hcli + // _, _, _, err := hcli.Accepted(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // } + // }) + + // var transferTxRoot *chain.Transaction + // ginkgo.It("Gossip TransferTx to a different node", func() { + // ginkgo.By("issue TransferTx", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 100_000, // must be more than StateLockup + // }, + // factory, + // ) + // transferTxRoot = transferTx + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + // }) + + // ginkgo.By("skip duplicate", func() { + // _, err := instances[0].hcli.SubmitTx( + // context.Background(), + // transferTxRoot.Bytes(), + // ) + // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + // }) + + // ginkgo.By("send gossip from node 0 to 1", func() { + // err := instances[0].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) + // }) + + // ginkgo.By("skip invalid time", func() { + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: 0, + // MaxFee: 1000, + // }, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 110, + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // 0 timestamp) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + // }) + + // ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { + // _, err := instances[0].hcli.SubmitTx( + // context.Background(), + // transferTxRoot.Bytes(), + // ) + // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + // }) + + // ginkgo.By("receive gossip in the node 1, and signal block build", func() { + // gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + // <-instances[1].toEngine + // }) + + // ginkgo.By("build block in the node 1", func() { + // ctx := context.TODO() + // blk, err := instances[1].vm.BuildBlock(ctx) + // gomega.Ω(err).To(gomega.BeNil()) + + // gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) + // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + // err = instances[1].vm.SetPreference(ctx, blk.ID()) + // gomega.Ω(err).To(gomega.BeNil()) + + // gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + // blocks = append(blocks, blk) + + // lastAccepted, err := instances[1].vm.LastAccepted(ctx) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + // results := blk.(*chain.StatelessBlock).Results() + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // gomega.Ω(results[0].Output).Should(gomega.BeNil()) + + // // Unit explanation + // // + // // bandwidth: tx size + // // compute: 5 for signature, 1 for base, 1 for transfer + // // read: 2 keys reads, 1 had 0 chunks + // // allocate: 1 key created + // // write: 1 key modified, 1 key new + // transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} + // gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) + + // // Fee explanation + // // + // // Multiply all unit consumption by 1 and sum + // gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) + // }) + + // ginkgo.By("ensure balance is updated", func() { + // balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) + // balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) + // }) + // }) + + // ginkgo.It("ensure multiple txs work ", func() { + // ginkgo.By("transfer funds again", func() { + // parser, err := instances[1].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 101, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // time.Sleep(2 * time.Second) // for replay test + // accept := expectBlk(instances[1]) + // results := accept(true) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) + // }) + // }) + + // ginkgo.It("Test processing block handling", func() { + // var accept, accept2 func(bool) []*chain.Result + + // ginkgo.By("create processing tip", func() { + // parser, err := instances[1].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 200, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // time.Sleep(2 * time.Second) // for replay test + // accept = expectBlk(instances[1]) + + // submit, _, _, err = instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 201, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // time.Sleep(2 * time.Second) // for replay test + // accept2 = expectBlk(instances[1]) + // }) + + // ginkgo.By("clear processing tip", func() { + // results := accept(true) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // results = accept2(true) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // }) + // }) + + // ginkgo.It("ensure mempool works", func() { + // ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { + // parser, err := instances[1].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: rsender2, + // Value: 203, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + // err = instances[1].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // mempool in 0 should be 1 (old amount), since gossip/submit failed + // gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + // }) + // }) + + // ginkgo.It("ensure unprocessed tip and replay protection works", func() { + // ginkgo.By("import accepted blocks to instance 2", func() { + // ctx := context.TODO() + + // gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) + + // n := instances[2] + // blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Verify(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Parse tip + // blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Verify tip + // err = blk2.Verify(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk3.Verify(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Check if tx from old block would be considered a repeat on processing tip + // tx := blk2.(*chain.StatelessBlock).Txs[0] + // sblk3 := blk3.(*chain.StatelessBlock) + // sblk3t := sblk3.Timestamp().UnixMilli() + // ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(ok.Len()).Should(gomega.Equal(1)) + + // // Accept tip + // err = blk1.Accept(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Accept(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk3.Accept(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Parse another + // blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk4.Verify(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk4.Accept(ctx) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Check if tx from old block would be considered a repeat on accepted tip + // time.Sleep(2 * time.Second) + // gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) + // }) + // }) + + // ginkgo.It("processes valid index transactions (w/block listening)", func() { + // // Clear previous txs on instance 0 + // accept := expectBlk(instances[0]) + // accept(false) // don't care about results + + // // Subscribe to blocks + // hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) + + // // Wait for message to be sent + // time.Sleep(2 * pubsub.MaxMessageWait) + + // // Fetch balances + // balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Send tx + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // transfer := &actions.Transfer{ + // To: auth.NewED25519Address(other.PublicKey()), + // Value: 1, + // } + + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // transfer, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + // gomega.Ω(err).Should(gomega.BeNil()) + // accept = expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // // Read item from connection + // blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) + // tx := blk.Txs[0].Action.(*actions.Transfer) + // gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) + // gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) + // gomega.Ω(lresults).Should(gomega.Equal(results)) + // gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) + + // // Check balance modifications are correct + // balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) + + // // Close connection when done + // gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + // }) + + // ginkgo.It("processes valid index transactions (w/streaming verification)", func() { + // // Create streaming client + // hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Create tx + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // transfer := &actions.Transfer{ + // To: auth.NewED25519Address(other.PublicKey()), + // Value: 1, + // } + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // _, tx, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // transfer, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + + // // Submit tx and accept block + // gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) + + // // Wait for message to be sent + // time.Sleep(2 * pubsub.MaxMessageWait) + + // for instances[0].vm.Mempool().Len(context.TODO()) == 0 { + // // We need to wait for mempool to be populated because issuance will + // // return as soon as bytes are on the channel. + // hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") + // time.Sleep(500 * time.Millisecond) + // } + // gomega.Ω(err).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // // Read decision from connection + // txID, dErr, result, err := hcli.ListenTx(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(txID).Should(gomega.Equal(tx.ID())) + // gomega.Ω(dErr).Should(gomega.BeNil()) + // gomega.Ω(result.Success).Should(gomega.BeTrue()) + // gomega.Ω(result).Should(gomega.Equal(results[0])) + + // // Close connection when done + // gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + // }) + + // ginkgo.It("transfer an asset with a memo", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.Transfer{ + // To: auth.NewED25519Address(other.PublicKey()), + // Value: 10, + // Memo: []byte("hello"), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeTrue()) + // }) + + // ginkgo.It("transfer an asset with large memo", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1001, + // }, + // nil, + // &actions.Transfer{ + // To: auth.NewED25519Address(other.PublicKey()), + // Value: 10, + // Memo: make([]byte, 1000), + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // too large) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + // }) + + // ginkgo.It("mint an asset that doesn't exist", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // assetID := ids.GenerateTestID() + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.MintAsset{ + // To: auth.NewED25519Address(other.PublicKey()), + // Asset: assetID, + // Value: 10, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)). + // Should(gomega.ContainSubstring("asset missing")) + + // exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(exists).Should(gomega.BeFalse()) + // }) + + // ginkgo.It("create a new asset (no metadata)", func() { + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1001, + // }, + // nil, + // &actions.CreateAsset{ + // Symbol: []byte("s0"), + // Decimals: 0, + // Metadata: nil, + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // too large) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + // }) + + // ginkgo.It("create a new asset (no symbol)", func() { + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1001, + // }, + // nil, + // &actions.CreateAsset{ + // Symbol: nil, + // Decimals: 0, + // Metadata: []byte("m"), + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // too large) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + // }) + + // ginkgo.It("create asset with too long of metadata", func() { + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // nil, + // &actions.CreateAsset{ + // Symbol: []byte("s0"), + // Decimals: 0, + // Metadata: make([]byte, actions.MaxMetadataSize*2), + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // too large) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + // }) + + ginkgo.It("create a new asset (simple metadata)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset1Symbol, + Decimals: asset1Decimals, + Metadata: asset1, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// ginkgo.It("import with wrong payload", func() { -// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) -// gomega.Ω(err).Should(gomega.BeNil()) -// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// wm, -// &actions.ImportAsset{}, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // invalid object) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) -// }) + asset1ID = tx.ID() + balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) -// ginkgo.It("import with invalid payload", func() { -// wt := &actions.WarpTransfer{} -// wtb, err := wt.Marshal() -// gomega.Ω(err).Should(gomega.BeNil()) -// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) -// gomega.Ω(err).Should(gomega.BeNil()) -// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) -// gomega.Ω(err).Should(gomega.BeNil()) -// tx := chain.NewTx( -// &chain.Base{ -// ChainID: instances[0].chainID, -// Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), -// MaxFee: 1000, -// }, -// wm, -// &actions.ImportAsset{}, -// ) -// // Must do manual construction to avoid `tx.Sign` error (would fail with -// // invalid object) -// msg, err := tx.Digest() -// gomega.Ω(err).To(gomega.BeNil()) -// auth, err := factory.Sign(msg) -// gomega.Ω(err).To(gomega.BeNil()) -// tx.Auth = auth -// p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth -// gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) -// gomega.Ω(p.Err()).To(gomega.BeNil()) -// _, err = instances[0].hcli.SubmitTx( -// context.Background(), -// p.Bytes(), -// ) -// gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) -// }) + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(0))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) -// ginkgo.It("import with wrong destination", func() { -// wt := &actions.WarpTransfer{ -// To: rsender, -// Symbol: []byte("s"), -// Decimals: 2, -// Asset: ids.GenerateTestID(), -// Value: 100, -// Return: false, -// Reward: 100, -// TxID: ids.GenerateTestID(), -// DestinationChainID: ids.GenerateTestID(), -// } -// wtb, err := wt.Marshal() -// gomega.Ω(err).Should(gomega.BeNil()) -// uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) -// gomega.Ω(err).Should(gomega.BeNil()) -// wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) -// gomega.Ω(err).Should(gomega.BeNil()) -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// wm, -// &actions.ImportAsset{}, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - -// // Build block with no context (should fail) -// gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) -// <-instances[0].toEngine -// blk, err := instances[0].vm.BuildBlock(context.TODO()) -// gomega.Ω(err).To(gomega.Not(gomega.BeNil())) -// gomega.Ω(blk).To(gomega.BeNil()) - -// // Wait for mempool to be size 1 (txs are restored async) -// for { -// if instances[0].vm.Mempool().Len(context.Background()) > 0 { -// break -// } -// log.Info("waiting for txs to be restored") -// time.Sleep(100 * time.Millisecond) -// } + ginkgo.It("mint a new asset", func() { + fmt.Println("MINT ASSET") + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender2, + Asset: asset1ID, + Value: 15, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) -// // Build block with context -// accept := expectBlkWithContext(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) -// }) + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(15))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) -// ginkgo.It("export native asset", func() { -// dest := ids.GenerateTestID() -// loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(loan).Should(gomega.Equal(uint64(0))) - -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, tx, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.ExportAsset{ -// To: rsender, -// Asset: ids.Empty, -// Value: 100, -// Return: false, -// Reward: 10, -// Destination: dest, -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeTrue()) -// wt := &actions.WarpTransfer{ -// To: rsender, -// Symbol: []byte(nconsts.Symbol), -// Decimals: nconsts.Decimals, -// Asset: ids.Empty, -// Value: 100, -// Return: false, -// Reward: 10, -// TxID: tx.ID(), -// DestinationChainID: dest, -// } -// wtb, err := wt.Marshal() -// gomega.Ω(err).Should(gomega.BeNil()) -// wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) - -// loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(loan).Should(gomega.Equal(uint64(110))) -// }) + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) -// ginkgo.It("export native asset (invalid return)", func() { -// parser, err := instances[0].ncli.Parser(context.Background()) -// gomega.Ω(err).Should(gomega.BeNil()) -// submit, _, _, err := instances[0].hcli.GenerateTransaction( -// context.Background(), -// parser, -// nil, -// &actions.ExportAsset{ -// To: rsender, -// Asset: ids.Empty, -// Value: 100, -// Return: true, -// Reward: 10, -// Destination: ids.GenerateTestID(), -// }, -// factory, -// ) -// gomega.Ω(err).Should(gomega.BeNil()) -// gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -// accept := expectBlk(instances[0]) -// results := accept(false) -// gomega.Ω(results).Should(gomega.HaveLen(1)) -// result := results[0] -// gomega.Ω(result.Success).Should(gomega.BeFalse()) -// gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) -// }) -// }) + // ginkgo.It("mint asset from wrong owner", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.MintAsset{ + // To: auth.NewED25519Address(other.PublicKey()), + // Asset: asset1ID, + // Value: 10, + // }, + // factory2, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)). + // Should(gomega.ContainSubstring("wrong owner")) + + // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(exists).Should(gomega.BeTrue()) + // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + // gomega.Ω(metadata).Should(gomega.Equal(asset1)) + // gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + // gomega.Ω(owner).Should(gomega.Equal(sender)) + // gomega.Ω(warp).Should(gomega.BeFalse()) + // }) + + // ginkgo.It("burn new asset", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.BurnAsset{ + // Asset: asset1ID, + // Value: 5, + // }, + // factory2, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + // balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(exists).Should(gomega.BeTrue()) + // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + // gomega.Ω(metadata).Should(gomega.Equal(asset1)) + // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + // gomega.Ω(owner).Should(gomega.Equal(sender)) + // gomega.Ω(warp).Should(gomega.BeFalse()) + // }) + + // ginkgo.It("burn missing asset", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.BurnAsset{ + // Asset: asset1ID, + // Value: 10, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)). + // Should(gomega.ContainSubstring("invalid balance")) + + // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(exists).Should(gomega.BeTrue()) + // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + // gomega.Ω(metadata).Should(gomega.Equal(asset1)) + // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + // gomega.Ω(owner).Should(gomega.Equal(sender)) + // gomega.Ω(warp).Should(gomega.BeFalse()) + // }) + + // ginkgo.It("rejects empty mint", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // nil, + // &actions.MintAsset{ + // To: auth.NewED25519Address(other.PublicKey()), + // Asset: asset1ID, + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // bad codec) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) + // }) + + // ginkgo.It("reject max mint", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.MintAsset{ + // To: rsender2, + // Asset: asset1ID, + // Value: hconsts.MaxUint64, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)). + // Should(gomega.ContainSubstring("overflow")) + + // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + // balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(exists).Should(gomega.BeTrue()) + // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + // gomega.Ω(metadata).Should(gomega.Equal(asset1)) + // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + // gomega.Ω(owner).Should(gomega.Equal(sender)) + // gomega.Ω(warp).Should(gomega.BeFalse()) + // }) + + // ginkgo.It("rejects mint of native token", func() { + // other, err := ed25519.GeneratePrivateKey() + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // nil, + // &actions.MintAsset{ + // To: auth.NewED25519Address(other.PublicKey()), + // Value: 10, + // }, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // bad codec) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) + // }) + + // ginkgo.It("mints another new asset (to self)", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, tx, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.CreateAsset{ + // Symbol: asset2Symbol, + // Decimals: asset2Decimals, + // Metadata: asset2, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // asset2ID = tx.ID() + + // submit, _, _, err = instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.MintAsset{ + // To: rsender, + // Asset: asset2ID, + // Value: 10, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept = expectBlk(instances[0]) + // results = accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + // }) + + // ginkgo.It("mints another new asset (to self) on another account", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, tx, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.CreateAsset{ + // Symbol: asset3Symbol, + // Decimals: asset3Decimals, + // Metadata: asset3, + // }, + // factory2, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // asset3ID = tx.ID() + + // submit, _, _, err = instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.MintAsset{ + // To: rsender2, + // Asset: asset3ID, + // Value: 10, + // }, + // factory2, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept = expectBlk(instances[0]) + // results = accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + // }) + + // ginkgo.It("import warp message with nil when expected", func() { + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // nil, + // &actions.ImportAsset{}, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // empty warp) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) + // }) + + // ginkgo.It("import warp message empty", func() { + // wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // wm, + // &actions.ImportAsset{}, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // empty warp) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) + // }) + + // ginkgo.It("import with wrong payload", func() { + // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) + // gomega.Ω(err).Should(gomega.BeNil()) + // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // wm, + // &actions.ImportAsset{}, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // invalid object) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) + // }) + + // ginkgo.It("import with invalid payload", func() { + // wt := &actions.WarpTransfer{} + // wtb, err := wt.Marshal() + // gomega.Ω(err).Should(gomega.BeNil()) + // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + // gomega.Ω(err).Should(gomega.BeNil()) + // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + // gomega.Ω(err).Should(gomega.BeNil()) + // tx := chain.NewTx( + // &chain.Base{ + // ChainID: instances[0].chainID, + // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + // MaxFee: 1000, + // }, + // wm, + // &actions.ImportAsset{}, + // ) + // // Must do manual construction to avoid `tx.Sign` error (would fail with + // // invalid object) + // msg, err := tx.Digest() + // gomega.Ω(err).To(gomega.BeNil()) + // auth, err := factory.Sign(msg) + // gomega.Ω(err).To(gomega.BeNil()) + // tx.Auth = auth + // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + // gomega.Ω(p.Err()).To(gomega.BeNil()) + // _, err = instances[0].hcli.SubmitTx( + // context.Background(), + // p.Bytes(), + // ) + // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) + // }) + + // ginkgo.It("import with wrong destination", func() { + // wt := &actions.WarpTransfer{ + // To: rsender, + // Symbol: []byte("s"), + // Decimals: 2, + // Asset: ids.GenerateTestID(), + // Value: 100, + // Return: false, + // Reward: 100, + // TxID: ids.GenerateTestID(), + // DestinationChainID: ids.GenerateTestID(), + // } + // wtb, err := wt.Marshal() + // gomega.Ω(err).Should(gomega.BeNil()) + // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + // gomega.Ω(err).Should(gomega.BeNil()) + // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + // gomega.Ω(err).Should(gomega.BeNil()) + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // wm, + // &actions.ImportAsset{}, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + // // Build block with no context (should fail) + // gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + // <-instances[0].toEngine + // blk, err := instances[0].vm.BuildBlock(context.TODO()) + // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + // gomega.Ω(blk).To(gomega.BeNil()) + + // // Wait for mempool to be size 1 (txs are restored async) + // for { + // if instances[0].vm.Mempool().Len(context.Background()) > 0 { + // break + // } + // log.Info("waiting for txs to be restored") + // time.Sleep(100 * time.Millisecond) + // } + + // // Build block with context + // accept := expectBlkWithContext(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) + // }) + + // ginkgo.It("export native asset", func() { + // dest := ids.GenerateTestID() + // loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(loan).Should(gomega.Equal(uint64(0))) + + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, tx, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.ExportAsset{ + // To: rsender, + // Asset: ids.Empty, + // Value: 100, + // Return: false, + // Reward: 10, + // Destination: dest, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeTrue()) + // wt := &actions.WarpTransfer{ + // To: rsender, + // Symbol: []byte(nconsts.Symbol), + // Decimals: nconsts.Decimals, + // Asset: ids.Empty, + // Value: 100, + // Return: false, + // Reward: 10, + // TxID: tx.ID(), + // DestinationChainID: dest, + // } + // wtb, err := wt.Marshal() + // gomega.Ω(err).Should(gomega.BeNil()) + // wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) + + // loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(loan).Should(gomega.Equal(uint64(110))) + // }) + + // ginkgo.It("export native asset (invalid return)", func() { + // parser, err := instances[0].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser, + // nil, + // &actions.ExportAsset{ + // To: rsender, + // Asset: ids.Empty, + // Value: 100, + // Return: true, + // Reward: 10, + // Destination: ids.GenerateTestID(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // accept := expectBlk(instances[0]) + // results := accept(false) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // result := results[0] + // gomega.Ω(result.Success).Should(gomega.BeFalse()) + // gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) + // }) +}) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // var err error @@ -1587,55 +1587,57 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { validators, err := instances[3].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) - - ginkgo.It("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 1000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := factory.Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // genesis, err := instances[3].ncli.Genesis(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // alloc := genesis.CustomAllocation - // fmt.Printf("ALLOC LEN %d", len(alloc)) - // balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // fmt.Printf("BALANCE INSTANCES[3] %d", balance) - time.Sleep(5000 * time.Millisecond) + ginkgo.By("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 1000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := factory.Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + factory, + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // genesis, err := instances[3].ncli.Genesis(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // alloc := genesis.CustomAllocation + // fmt.Printf("ALLOC LEN %d", len(alloc)) + // balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + // fmt.Printf("BALANCE INSTANCES[3] %d", balance) + time.Sleep(5000 * time.Millisecond) + }) + + ginkgo.By("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals + }) }) - ginkgo.It("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals - }) }) func expectBlk(i instance) func(bool) []*chain.Result { From 33790e712d29b8429a31aa1aa9aa00b3b74749ec Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 11 Apr 2024 13:56:53 +0100 Subject: [PATCH 07/78] remove sleep time --- tests/integration/integration_test.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 52d27a8..faae1b2 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -313,9 +313,6 @@ var _ = ginkgo.AfterSuite(func() { // var _ = ginkgo.Describe("[Ping]", func() { // ginkgo.It("can ping", func() { -// if skip { -// ginkgo.Skip("skip can ping") -// } // for _, inst := range instances { // hcli := inst.hcli // ok, err := hcli.Ping(context.Background()) @@ -339,13 +336,13 @@ var _ = ginkgo.AfterSuite(func() { // }) var _ = ginkgo.Describe("[Tx Processing]", func() { - // ginkgo.It("get currently accepted block ID", func() { - // for _, inst := range instances { - // hcli := inst.hcli - // _, _, _, err := hcli.Accepted(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // } - // }) + ginkgo.It("get currently accepted block ID", func() { + for _, inst := range instances { + hcli := inst.hcli + _, _, _, err := hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + } + }) // var transferTxRoot *chain.Transaction // ginkgo.It("Gossip TransferTx to a different node", func() { @@ -1627,7 +1624,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) // gomega.Ω(err).Should(gomega.BeNil()) // fmt.Printf("BALANCE INSTANCES[3] %d", balance) - time.Sleep(5000 * time.Millisecond) + // time.Sleep(5000 * time.Millisecond) }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { From 63c40a8dc0343e7b8c0bae05dd867befd8dc6480 Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 11 Apr 2024 16:28:14 +0100 Subject: [PATCH 08/78] change factories for nodes --- tests/integration/integration_test.go | 37 +++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index faae1b2..131cbcf 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -132,6 +132,8 @@ var ( rdelegate codec.Address // parser0 chain.Parser // err error + nodesFactories []*auth.BLSFactory + nodesAddresses []codec.Address ) type instance struct { @@ -185,6 +187,8 @@ var _ = ginkgo.BeforeSuite(func() { // create embedded VMs instances = make([]instance, vms) + nodesFactories = make([]*auth.BLSFactory, vms) + nodesAddresses = make([]codec.Address, vms) gen = genesis.Default() gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} @@ -228,6 +232,8 @@ var _ = ginkgo.BeforeSuite(func() { WarpSigner: warp.NewSigner(sk, networkID, chainID), ValidatorState: &validators.TestState{}, } + nodesFactories[i] = auth.NewBLSFactory(sk) + nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) toEngine := make(chan common.Message, 1) db := memdb.New() @@ -1585,6 +1591,25 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) + ginkgo.By("Fund node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[3], + Asset: ids.Empty, + Value: 100, + }, + factory, + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + ginkgo.By("Register validator stake node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1592,7 +1617,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { NodeID: instances[3].nodeID.Bytes(), StakeStartTime: uint64(stakeStartTime.Unix()), StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 1000, + StakedAmount: 100, DelegationFeeRate: uint64(delegationFeeRate), RewardAddress: rwithdraw0, } @@ -1612,19 +1637,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { StakeInfo: stakeInfoBytes, AuthSignature: authSignature, }, - factory, + nodesFactories[3], ) fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // genesis, err := instances[3].ncli.Genesis(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // alloc := genesis.CustomAllocation - // fmt.Printf("ALLOC LEN %d", len(alloc)) - // balance, err := instances[3].ncli.Balance(context.Background(), alloc[0].Address, ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // fmt.Printf("BALANCE INSTANCES[3] %d", balance) - // time.Sleep(5000 * time.Millisecond) }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { From 9e88267e2eb4156ac63ca2b4ebf832414220dffd Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 11 Apr 2024 18:02:34 +0100 Subject: [PATCH 09/78] transfer to node address --- tests/integration/integration_test.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 131cbcf..da79c7d 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -1592,22 +1592,32 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(validators)).Should(gomega.Equal(0)) ginkgo.By("Fund node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + parser, err := instances[4].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( + submit, _, _, err := instances[4].hcli.GenerateTransaction( context.Background(), parser, nil, &actions.Transfer{ To: nodesAddresses[3], Asset: ids.Empty, - Value: 100, + // Value: uint64(200 * math.Pow10(nconsts.Decimals)), + Value: 100_000, }, factory, ) fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) + // accept := expectBlk(instances[1]) + // results := accept(true) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + fmt.Printf("node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + fmt.Printf("balance factory %s %d", sender, balance) + gomega.Ω(err).Should(gomega.BeNil()) }) ginkgo.By("Register validator stake node 3", func() { From 99de97acc13f7b8ca78f4c60644001a8761f621b Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 11 Apr 2024 18:25:26 +0100 Subject: [PATCH 10/78] test balance --- tests/integration/integration_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index da79c7d..3f10c3d 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -246,7 +246,7 @@ var _ = ginkgo.BeforeSuite(func() { genesisBytes, nil, []byte( - `{"parallelism":5, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, + `{"parallelism":3, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, ), toEngine, nil, @@ -1615,7 +1615,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // gomega.Ω(results).Should(gomega.HaveLen(1)) // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + balance, err = instances[4].ncli.Balance(context.TODO(), sender, ids.Empty) fmt.Printf("balance factory %s %d", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) }) From b6acd995ca29647da1babc09ea0a8ba6a2bc39f8 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 10:22:39 +0100 Subject: [PATCH 11/78] transfer and register --- tests/integration/integration_test.go | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 3f10c3d..96291ed 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -196,7 +196,7 @@ var _ = ginkgo.BeforeSuite(func() { gen.CustomAllocation = []*genesis.CustomAllocation{ { Address: sender, - Balance: 10_000_000, + Balance: 10_000_000_000_000_000, }, } gen.EmissionBalancer = genesis.EmissionBalancer{ @@ -1591,7 +1591,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) - ginkgo.By("Fund node 3", func() { + ginkgo.By("Funding node 3", func() { parser, err := instances[4].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err := instances[4].hcli.GenerateTransaction( @@ -1602,18 +1602,18 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { To: nodesAddresses[3], Asset: ids.Empty, // Value: uint64(200 * math.Pow10(nconsts.Decimals)), - Value: 100_000, + Value: 100_000_000_000, }, factory, ) fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) - // accept := expectBlk(instances[1]) - // results := accept(true) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + time.Sleep(5 * time.Second) + accept := expectBlk(instances[4]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) @@ -1623,25 +1623,25 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) ginkgo.By("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + parser, err := instances[4].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[3].nodeID.Bytes(), StakeStartTime: uint64(stakeStartTime.Unix()), StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100, + StakedAmount: 100_000_000_000, DelegationFeeRate: uint64(delegationFeeRate), RewardAddress: rwithdraw0, } stakeInfoBytes, err := stakeInfo.Marshal() gomega.Ω(err).Should(gomega.BeNil()) - signature, err := factory.Sign(stakeInfoBytes) + signature, err := nodesFactories[3].Sign(stakeInfoBytes) gomega.Ω(err).Should(gomega.BeNil()) signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) signature.Marshal(signaturePacker) authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( + submit, _, _, err := instances[4].hcli.GenerateTransaction( context.Background(), parser, nil, @@ -1653,11 +1653,16 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) + + balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("bis node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + _, _, stakedAmount, _, _, _, err := instances[4].ncli.ValidatorStake(context.Background(), instances[3].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals From 45a47cc67679479c3564e81157a5c5fb2ac3916a Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 11:59:36 +0100 Subject: [PATCH 12/78] transfer and register --- tests/integration/integration_test.go | 86 +++++++++++++++------------ 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 96291ed..1e28d2c 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -317,29 +317,29 @@ var _ = ginkgo.AfterSuite(func() { } }) -// var _ = ginkgo.Describe("[Ping]", func() { -// ginkgo.It("can ping", func() { -// for _, inst := range instances { -// hcli := inst.hcli -// ok, err := hcli.Ping(context.Background()) -// gomega.Ω(ok).Should(gomega.BeTrue()) -// gomega.Ω(err).Should(gomega.BeNil()) -// } -// }) -// }) - -// var _ = ginkgo.Describe("[Network]", func() { -// ginkgo.It("can get network", func() { -// for _, inst := range instances { -// hcli := inst.hcli -// networkID, subnetID, chainID, err := hcli.Network(context.Background()) -// gomega.Ω(networkID).Should(gomega.Equal(uint32(1))) -// gomega.Ω(subnetID).ShouldNot(gomega.Equal(ids.Empty)) -// gomega.Ω(chainID).ShouldNot(gomega.Equal(ids.Empty)) -// gomega.Ω(err).Should(gomega.BeNil()) -// } -// }) -// }) +var _ = ginkgo.Describe("[Ping]", func() { + ginkgo.It("can ping", func() { + for _, inst := range instances { + hcli := inst.hcli + ok, err := hcli.Ping(context.Background()) + gomega.Ω(ok).Should(gomega.BeTrue()) + gomega.Ω(err).Should(gomega.BeNil()) + } + }) +}) + +var _ = ginkgo.Describe("[Network]", func() { + ginkgo.It("can get network", func() { + for _, inst := range instances { + hcli := inst.hcli + networkID, subnetID, chainID, err := hcli.Network(context.Background()) + gomega.Ω(networkID).Should(gomega.Equal(uint32(1))) + gomega.Ω(subnetID).ShouldNot(gomega.Equal(ids.Empty)) + gomega.Ω(chainID).ShouldNot(gomega.Equal(ids.Empty)) + gomega.Ω(err).Should(gomega.BeNil()) + } + }) +}) var _ = ginkgo.Describe("[Tx Processing]", func() { ginkgo.It("get currently accepted block ID", func() { @@ -1567,7 +1567,6 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - // var err error ginkgo.It("Setup and get initial staked validators", func() { currentTime = time.Now().UTC() stakeStartTime = currentTime.Add(2 * time.Minute) @@ -1592,38 +1591,44 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(validators)).Should(gomega.Equal(0)) ginkgo.By("Funding node 3", func() { - parser, err := instances[4].ncli.Parser(context.Background()) + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[4].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, &actions.Transfer{ To: nodesAddresses[3], Asset: ids.Empty, - // Value: uint64(200 * math.Pow10(nconsts.Decimals)), - Value: 100_000_000_000, + Value: 200_000_000_000, }, factory, ) fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + gomega.Ω(instances[3].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + time.Sleep(5 * time.Second) - accept := expectBlk(instances[4]) + accept := expectBlk(instances[3]) results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - balance, err = instances[4].ncli.Balance(context.TODO(), sender, ids.Empty) - fmt.Printf("balance factory %s %d", sender, balance) + fmt.Printf("node 3 %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) + fmt.Printf("balance factory %s %d\n", sender, balance) + gomega.Ω(err).Should(gomega.BeNil()) + + err = instances[3].vm.Gossiper().Force(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) }) ginkgo.By("Register validator stake node 3", func() { - parser, err := instances[4].ncli.Parser(context.Background()) + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[3].nodeID.Bytes(), @@ -1641,7 +1646,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) signature.Marshal(signaturePacker) authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[4].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, @@ -1654,15 +1659,20 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) - balance, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("bis node 3 %s balance %d", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(5 * time.Second) + + balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[4].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals From 70cd8ceaa651973f084fbeabdf409122310182d0 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 12:00:08 +0100 Subject: [PATCH 13/78] transfer and register --- tests/integration/integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 1e28d2c..5d59f16 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -1675,7 +1675,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(1000)) // multiply by the decimals + gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) // multiply by the decimals }) }) From 49364d3d8802bb5adf96dd329898a7bef9aae861 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 12:26:39 +0100 Subject: [PATCH 14/78] add print --- tests/integration/integration_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 5d59f16..c19a08f 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -43,6 +43,7 @@ import ( "github.com/nuklai/nuklaivm/auth" nconsts "github.com/nuklai/nuklaivm/consts" "github.com/nuklai/nuklaivm/controller" + "github.com/nuklai/nuklaivm/emission" "github.com/nuklai/nuklaivm/genesis" nrpc "github.com/nuklai/nuklaivm/rpc" ) @@ -1669,6 +1670,13 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + emissionInstance := emission.GetEmission() + currentValidators := emissionInstance.GetAllValidators(context.TODO()) + fmt.Println(currentValidators) + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + fmt.Println(stakedValidator) + }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { From fad8a0ae64ef20b51dc79fc9d28717e15dff6d26 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 14:20:30 +0100 Subject: [PATCH 15/78] add print --- tests/integration/integration_test.go | 238 +++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 3 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index c19a08f..a2ee464 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -1624,8 +1624,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("balance factory %s %d\n", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) }) ginkgo.By("Register validator stake node 3", func() { @@ -1683,8 +1683,240 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) // multiply by the decimals + gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) }) + + // ginkgo.By("Register validator stake node 1", func() { + // stakeInfo := &actions.ValidatorStakeInfo{ + // NodeID: instances[1].nodeID.Bytes(), + // StakeStartTime: uint64(stakeStartTime.Unix()), + // StakeEndTime: uint64(stakeEndTime.Unix()), + // StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR + // DelegationFeeRate: uint64(delegationFeeRate), + // RewardAddress: rwithdraw1, + // } + // stakeInfoBytes, err := stakeInfo.Marshal() + // gomega.Ω(err).Should(gomega.BeNil()) + // signature, err := factory.Sign(stakeInfoBytes) + // gomega.Ω(err).Should(gomega.BeNil()) + // signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + // signature.Marshal(signaturePacker) + // authSignature := signaturePacker.Bytes() + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser1, + // nil, + // &actions.RegisterValidatorStake{ + // StakeInfo: stakeInfoBytes, + // AuthSignature: authSignature, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.HaveOccurred()) + // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) + // }) + + // ginkgo.By("Get staked validators", func() { + // validators, err := instances[0].ncli.StakedValidators(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(len(validators)).Should(gomega.Equal(3)) + // }) + + // ginkgo.By("Get validator staked amount after staking", func() { + // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + // _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + // }) + + // ginkgo.By("Get staked validators", func() { + // validators, err := instances[0].ncli.StakedValidators(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(len(validators)).Should(gomega.Equal(2)) + // }) + + // ginkgo.By("Transfer NAI to user and delegate stake to node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.Transfer{ + // To: rdelegate, + // Asset: ids.Empty, + // Value: 100, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // currentTime := time.Now().UTC() + // userStakeStartTime := currentTime.Add(2 * time.Minute) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err = instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.DelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // StakeStartTime: uint64(userStakeStartTime.Unix()), + // StakedAmount: 50, + // RewardAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Delegate stake to node 1", func() { + // currentTime = time.Now().UTC() + // userStakeStartTime := currentTime.Add(2 * time.Minute) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.DelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // StakeStartTime: uint64(userStakeStartTime.Unix()), + // StakedAmount: 50, + // RewardAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get user stake before claim", func() { + // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) + // }) + + // ginkgo.By("Claim delegation stake rewards from node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.ClaimDelegationStakeRewards{ + // NodeID: instances[0].nodeID.Bytes(), + // UserStakeAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get user stake after claim", func() { + // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) + // }) + + // ginkgo.By("Undelegate user stake from node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.UndelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // add more ginko.By where error should be thrown with wrong data input + // ginkgo.By("Claim validator node 0 stake reward", func() { + // // ClaimValidatorStakeRewards + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.ClaimValidatorStakeRewards{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Withdraw validator node 0 stake", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get validator stake after staking withdraw ", func() { + // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + // }) + + // ginkgo.By("Withdraw validator node 1 stake with wrong key", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[1].nodeID.Bytes(), + // }, + // factory2, + // ) + // gomega.Ω(err).ShouldNot(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) + // }) + + // staking withdraw then user delegate withdraw on node 1 + // ginkgo.By("Withdraw validator node 1 stake", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[1].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Undelegate user stake from node 1", func() { + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.UndelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) }) }) From 5e9b959d936d187afe6f96f600ce39836fa65bd2 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 12 Apr 2024 18:16:01 +0100 Subject: [PATCH 16/78] uncomment tokenvm tests --- tests/integration/integration_test.go | 2307 +++++++++++++------------ 1 file changed, 1155 insertions(+), 1152 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index a2ee464..70ceffc 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -35,8 +35,11 @@ import ( "github.com/ava-labs/hypersdk/chain" "github.com/ava-labs/hypersdk/codec" + hconsts "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/crypto/ed25519" + "github.com/ava-labs/hypersdk/pubsub" hrpc "github.com/ava-labs/hypersdk/rpc" + hutils "github.com/ava-labs/hypersdk/utils" "github.com/ava-labs/hypersdk/vm" "github.com/nuklai/nuklaivm/actions" @@ -351,598 +354,711 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { } }) - // var transferTxRoot *chain.Transaction - // ginkgo.It("Gossip TransferTx to a different node", func() { - // ginkgo.By("issue TransferTx", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 100_000, // must be more than StateLockup - // }, - // factory, - // ) - // transferTxRoot = transferTx - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) - // }) - - // ginkgo.By("skip duplicate", func() { - // _, err := instances[0].hcli.SubmitTx( - // context.Background(), - // transferTxRoot.Bytes(), - // ) - // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - // }) - - // ginkgo.By("send gossip from node 0 to 1", func() { - // err := instances[0].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - // }) - - // ginkgo.By("skip invalid time", func() { - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: 0, - // MaxFee: 1000, - // }, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 110, - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // 0 timestamp) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - // }) - - // ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { - // _, err := instances[0].hcli.SubmitTx( - // context.Background(), - // transferTxRoot.Bytes(), - // ) - // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - // }) - - // ginkgo.By("receive gossip in the node 1, and signal block build", func() { - // gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - // <-instances[1].toEngine - // }) - - // ginkgo.By("build block in the node 1", func() { - // ctx := context.TODO() - // blk, err := instances[1].vm.BuildBlock(ctx) - // gomega.Ω(err).To(gomega.BeNil()) - - // gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) - // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - // err = instances[1].vm.SetPreference(ctx, blk.ID()) - // gomega.Ω(err).To(gomega.BeNil()) - - // gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - // blocks = append(blocks, blk) - - // lastAccepted, err := instances[1].vm.LastAccepted(ctx) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - // results := blk.(*chain.StatelessBlock).Results() - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // gomega.Ω(results[0].Output).Should(gomega.BeNil()) - - // // Unit explanation - // // - // // bandwidth: tx size - // // compute: 5 for signature, 1 for base, 1 for transfer - // // read: 2 keys reads, 1 had 0 chunks - // // allocate: 1 key created - // // write: 1 key modified, 1 key new - // transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} - // gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) - - // // Fee explanation - // // - // // Multiply all unit consumption by 1 and sum - // gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) - // }) - - // ginkgo.By("ensure balance is updated", func() { - // balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) - // balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) - // }) - // }) - - // ginkgo.It("ensure multiple txs work ", func() { - // ginkgo.By("transfer funds again", func() { - // parser, err := instances[1].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 101, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // time.Sleep(2 * time.Second) // for replay test - // accept := expectBlk(instances[1]) - // results := accept(true) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) - // }) - // }) - - // ginkgo.It("Test processing block handling", func() { - // var accept, accept2 func(bool) []*chain.Result - - // ginkgo.By("create processing tip", func() { - // parser, err := instances[1].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 200, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // time.Sleep(2 * time.Second) // for replay test - // accept = expectBlk(instances[1]) - - // submit, _, _, err = instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 201, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // time.Sleep(2 * time.Second) // for replay test - // accept2 = expectBlk(instances[1]) - // }) - - // ginkgo.By("clear processing tip", func() { - // results := accept(true) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // results = accept2(true) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // }) - // }) - - // ginkgo.It("ensure mempool works", func() { - // ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { - // parser, err := instances[1].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: rsender2, - // Value: 203, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - // err = instances[1].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // mempool in 0 should be 1 (old amount), since gossip/submit failed - // gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // }) - // }) - - // ginkgo.It("ensure unprocessed tip and replay protection works", func() { - // ginkgo.By("import accepted blocks to instance 2", func() { - // ctx := context.TODO() - - // gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) - - // n := instances[2] - // blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Verify(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Parse tip - // blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Verify tip - // err = blk2.Verify(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk3.Verify(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Check if tx from old block would be considered a repeat on processing tip - // tx := blk2.(*chain.StatelessBlock).Txs[0] - // sblk3 := blk3.(*chain.StatelessBlock) - // sblk3t := sblk3.Timestamp().UnixMilli() - // ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - - // // Accept tip - // err = blk1.Accept(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Accept(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk3.Accept(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Parse another - // blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk4.Verify(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk4.Accept(ctx) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Check if tx from old block would be considered a repeat on accepted tip - // time.Sleep(2 * time.Second) - // gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) - // }) - // }) - - // ginkgo.It("processes valid index transactions (w/block listening)", func() { - // // Clear previous txs on instance 0 - // accept := expectBlk(instances[0]) - // accept(false) // don't care about results - - // // Subscribe to blocks - // hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) - - // // Wait for message to be sent - // time.Sleep(2 * pubsub.MaxMessageWait) - - // // Fetch balances - // balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Send tx - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // transfer := &actions.Transfer{ - // To: auth.NewED25519Address(other.PublicKey()), - // Value: 1, - // } - - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // transfer, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - // gomega.Ω(err).Should(gomega.BeNil()) - // accept = expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // // Read item from connection - // blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) - // tx := blk.Txs[0].Action.(*actions.Transfer) - // gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) - // gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) - // gomega.Ω(lresults).Should(gomega.Equal(results)) - // gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) - - // // Check balance modifications are correct - // balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) - - // // Close connection when done - // gomega.Ω(hcli.Close()).Should(gomega.BeNil()) - // }) - - // ginkgo.It("processes valid index transactions (w/streaming verification)", func() { - // // Create streaming client - // hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Create tx - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // transfer := &actions.Transfer{ - // To: auth.NewED25519Address(other.PublicKey()), - // Value: 1, - // } - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // _, tx, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // transfer, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - - // // Submit tx and accept block - // gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) - - // // Wait for message to be sent - // time.Sleep(2 * pubsub.MaxMessageWait) - - // for instances[0].vm.Mempool().Len(context.TODO()) == 0 { - // // We need to wait for mempool to be populated because issuance will - // // return as soon as bytes are on the channel. - // hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") - // time.Sleep(500 * time.Millisecond) - // } - // gomega.Ω(err).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // // Read decision from connection - // txID, dErr, result, err := hcli.ListenTx(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(txID).Should(gomega.Equal(tx.ID())) - // gomega.Ω(dErr).Should(gomega.BeNil()) - // gomega.Ω(result.Success).Should(gomega.BeTrue()) - // gomega.Ω(result).Should(gomega.Equal(results[0])) - - // // Close connection when done - // gomega.Ω(hcli.Close()).Should(gomega.BeNil()) - // }) - - // ginkgo.It("transfer an asset with a memo", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.Transfer{ - // To: auth.NewED25519Address(other.PublicKey()), - // Value: 10, - // Memo: []byte("hello"), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeTrue()) - // }) - - // ginkgo.It("transfer an asset with large memo", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1001, - // }, - // nil, - // &actions.Transfer{ - // To: auth.NewED25519Address(other.PublicKey()), - // Value: 10, - // Memo: make([]byte, 1000), - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // too large) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) - // }) - - // ginkgo.It("mint an asset that doesn't exist", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // assetID := ids.GenerateTestID() - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.MintAsset{ - // To: auth.NewED25519Address(other.PublicKey()), - // Asset: assetID, - // Value: 10, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)). - // Should(gomega.ContainSubstring("asset missing")) - - // exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(exists).Should(gomega.BeFalse()) - // }) - - // ginkgo.It("create a new asset (no metadata)", func() { - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1001, - // }, - // nil, - // &actions.CreateAsset{ - // Symbol: []byte("s0"), - // Decimals: 0, - // Metadata: nil, - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // too large) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - // }) - - // ginkgo.It("create a new asset (no symbol)", func() { - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1001, - // }, - // nil, - // &actions.CreateAsset{ - // Symbol: nil, - // Decimals: 0, - // Metadata: []byte("m"), - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // too large) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - // }) - - // ginkgo.It("create asset with too long of metadata", func() { - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // nil, - // &actions.CreateAsset{ - // Symbol: []byte("s0"), - // Decimals: 0, - // Metadata: make([]byte, actions.MaxMetadataSize*2), - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // too large) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) - // }) + var transferTxRoot *chain.Transaction + ginkgo.It("Gossip TransferTx to a different node", func() { + ginkgo.By("issue TransferTx", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 100_000, // must be more than StateLockup + }, + factory, + ) + transferTxRoot = transferTx + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + }) + + ginkgo.By("skip duplicate", func() { + _, err := instances[0].hcli.SubmitTx( + context.Background(), + transferTxRoot.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("send gossip from node 0 to 1", func() { + err := instances[0].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + }) + + ginkgo.By("skip invalid time", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: 0, + MaxFee: 1000, + }, + nil, + &actions.Transfer{ + To: rsender2, + Value: 110, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // 0 timestamp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { + _, err := instances[0].hcli.SubmitTx( + context.Background(), + transferTxRoot.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("receive gossip in the node 1, and signal block build", func() { + gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + <-instances[1].toEngine + }) + + ginkgo.By("build block in the node 1", func() { + ctx := context.TODO() + blk, err := instances[1].vm.BuildBlock(ctx) + gomega.Ω(err).To(gomega.BeNil()) + + gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = instances[1].vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + blocks = append(blocks, blk) + + lastAccepted, err := instances[1].vm.LastAccepted(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + results := blk.(*chain.StatelessBlock).Results() + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(results[0].Output).Should(gomega.BeNil()) + + // Unit explanation + // + // bandwidth: tx size + // compute: 5 for signature, 1 for base, 1 for transfer + // read: 2 keys reads, 1 had 0 chunks + // allocate: 1 key created + // write: 1 key modified, 1 key new + transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} + gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) + + // Fee explanation + // + // Multiply all unit consumption by 1 and sum + gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) + }) + + ginkgo.By("ensure balance is updated", func() { + balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) + balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) + }) + }) + + ginkgo.It("ensure multiple txs work ", func() { + ginkgo.By("transfer funds again", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 101, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept := expectBlk(instances[1]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) + }) + }) + + ginkgo.It("Test processing block handling", func() { + var accept, accept2 func(bool) []*chain.Result + + ginkgo.By("create processing tip", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 200, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept = expectBlk(instances[1]) + + submit, _, _, err = instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 201, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept2 = expectBlk(instances[1]) + }) + + ginkgo.By("clear processing tip", func() { + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + results = accept2(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + }) + }) + + ginkgo.It("ensure mempool works", func() { + ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 203, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + err = instances[1].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + + // mempool in 0 should be 1 (old amount), since gossip/submit failed + gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + }) + }) + + ginkgo.It("ensure unprocessed tip and replay protection works", func() { + ginkgo.By("import accepted blocks to instance 2", func() { + ctx := context.TODO() + + gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) + + n := instances[2] + blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + + // Parse tip + blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + + // Verify tip + err = blk2.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk3.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + + // Check if tx from old block would be considered a repeat on processing tip + tx := blk2.(*chain.StatelessBlock).Txs[0] + sblk3 := blk3.(*chain.StatelessBlock) + sblk3t := sblk3.Timestamp().UnixMilli() + ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(ok.Len()).Should(gomega.Equal(1)) + + // Accept tip + err = blk1.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk3.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + + // Parse another + blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk4.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk4.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + + // Check if tx from old block would be considered a repeat on accepted tip + time.Sleep(2 * time.Second) + gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) + }) + }) + + ginkgo.It("processes valid index transactions (w/block listening)", func() { + // Clear previous txs on instance 0 + accept := expectBlk(instances[0]) + accept(false) // don't care about results + + // Subscribe to blocks + hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) + + // Wait for message to be sent + time.Sleep(2 * pubsub.MaxMessageWait) + + // Fetch balances + balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + + // Send tx + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + transfer := &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 1, + } + + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + transfer, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + gomega.Ω(err).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // Read item from connection + blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) + tx := blk.Txs[0].Action.(*actions.Transfer) + gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) + gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) + gomega.Ω(lresults).Should(gomega.Equal(results)) + gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) + + // Check balance modifications are correct + balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) + + // Close connection when done + gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + }) + + ginkgo.It("processes valid index transactions (w/streaming verification)", func() { + // Create streaming client + hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + gomega.Ω(err).Should(gomega.BeNil()) + + // Create tx + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + transfer := &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 1, + } + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + _, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + transfer, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + + // Submit tx and accept block + gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) + + // Wait for message to be sent + time.Sleep(2 * pubsub.MaxMessageWait) + + for instances[0].vm.Mempool().Len(context.TODO()) == 0 { + // We need to wait for mempool to be populated because issuance will + // return as soon as bytes are on the channel. + hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") + time.Sleep(500 * time.Millisecond) + } + gomega.Ω(err).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // Read decision from connection + txID, dErr, result, err := hcli.ListenTx(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(txID).Should(gomega.Equal(tx.ID())) + gomega.Ω(dErr).Should(gomega.BeNil()) + gomega.Ω(result.Success).Should(gomega.BeTrue()) + gomega.Ω(result).Should(gomega.Equal(results[0])) + + // Close connection when done + gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + }) + + ginkgo.It("transfer an asset with a memo", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + Memo: []byte("hello"), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeTrue()) + }) + + ginkgo.It("transfer an asset with large memo", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + Memo: make([]byte, 1000), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + }) + + ginkgo.It("mint an asset that doesn't exist", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + assetID := ids.GenerateTestID() + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: assetID, + Value: 10, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("asset missing")) + + exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeFalse()) + }) + + ginkgo.It("create a new asset (no metadata)", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.CreateAsset{ + Symbol: []byte("s0"), + Decimals: 0, + Metadata: nil, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + }) + + ginkgo.It("create a new asset (no symbol)", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.CreateAsset{ + Symbol: nil, + Decimals: 0, + Metadata: []byte("m"), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + }) + + ginkgo.It("create asset with too long of metadata", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.CreateAsset{ + Symbol: []byte("s0"), + Decimals: 0, + Metadata: make([]byte, actions.MaxMetadataSize*2), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + }) + + ginkgo.It("create a new asset (simple metadata)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset1Symbol, + Decimals: asset1Decimals, + Metadata: asset1, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + asset1ID = tx.ID() + balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(0))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) + + ginkgo.It("mint a new asset", func() { + fmt.Println("MINT ASSET") + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender2, + Asset: asset1ID, + Value: 15, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(15))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) + + ginkgo.It("mint asset from wrong owner", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: asset1ID, + Value: 10, + }, + factory2, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("wrong owner")) - ginkgo.It("create a new asset (simple metadata)", func() { + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) + + ginkgo.It("burn new asset", func() { parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[0].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.CreateAsset{ - Symbol: asset1Symbol, - Decimals: asset1Decimals, - Metadata: asset1, + &actions.BurnAsset{ + Asset: asset1ID, + Value: 5, }, - factory, + factory2, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) @@ -951,8 +1067,10 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - asset1ID = tx.ID() - balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(0))) @@ -962,13 +1080,78 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(0))) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) gomega.Ω(owner).Should(gomega.Equal(sender)) gomega.Ω(warp).Should(gomega.BeFalse()) }) - ginkgo.It("mint a new asset", func() { - fmt.Println("MINT ASSET") + ginkgo.It("burn missing asset", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.BurnAsset{ + Asset: asset1ID, + Value: 10, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("invalid balance")) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) + + ginkgo.It("rejects empty mint", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: asset1ID, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // bad codec) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) + }) + + ginkgo.It("reject max mint", func() { parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err := instances[0].hcli.GenerateTransaction( @@ -978,7 +1161,7 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { &actions.MintAsset{ To: rsender2, Asset: asset1ID, - Value: 15, + Value: hconsts.MaxUint64, }, factory, ) @@ -987,11 +1170,14 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { accept := expectBlk(instances[0]) results := accept(false) gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("overflow")) balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(15))) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(0))) @@ -1002,569 +1188,386 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) gomega.Ω(owner).Should(gomega.Equal(sender)) gomega.Ω(warp).Should(gomega.BeFalse()) }) - // ginkgo.It("mint asset from wrong owner", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.MintAsset{ - // To: auth.NewED25519Address(other.PublicKey()), - // Asset: asset1ID, - // Value: 10, - // }, - // factory2, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)). - // Should(gomega.ContainSubstring("wrong owner")) - - // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(exists).Should(gomega.BeTrue()) - // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - // gomega.Ω(metadata).Should(gomega.Equal(asset1)) - // gomega.Ω(supply).Should(gomega.Equal(uint64(15))) - // gomega.Ω(owner).Should(gomega.Equal(sender)) - // gomega.Ω(warp).Should(gomega.BeFalse()) - // }) - - // ginkgo.It("burn new asset", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.BurnAsset{ - // Asset: asset1ID, - // Value: 5, - // }, - // factory2, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - // balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(exists).Should(gomega.BeTrue()) - // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - // gomega.Ω(metadata).Should(gomega.Equal(asset1)) - // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - // gomega.Ω(owner).Should(gomega.Equal(sender)) - // gomega.Ω(warp).Should(gomega.BeFalse()) - // }) - - // ginkgo.It("burn missing asset", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.BurnAsset{ - // Asset: asset1ID, - // Value: 10, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)). - // Should(gomega.ContainSubstring("invalid balance")) - - // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(exists).Should(gomega.BeTrue()) - // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - // gomega.Ω(metadata).Should(gomega.Equal(asset1)) - // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - // gomega.Ω(owner).Should(gomega.Equal(sender)) - // gomega.Ω(warp).Should(gomega.BeFalse()) - // }) - - // ginkgo.It("rejects empty mint", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // nil, - // &actions.MintAsset{ - // To: auth.NewED25519Address(other.PublicKey()), - // Asset: asset1ID, - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // bad codec) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) - // }) - - // ginkgo.It("reject max mint", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.MintAsset{ - // To: rsender2, - // Asset: asset1ID, - // Value: hconsts.MaxUint64, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)). - // Should(gomega.ContainSubstring("overflow")) - - // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - // balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - - // exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(exists).Should(gomega.BeTrue()) - // gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - // gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - // gomega.Ω(metadata).Should(gomega.Equal(asset1)) - // gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - // gomega.Ω(owner).Should(gomega.Equal(sender)) - // gomega.Ω(warp).Should(gomega.BeFalse()) - // }) - - // ginkgo.It("rejects mint of native token", func() { - // other, err := ed25519.GeneratePrivateKey() - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // nil, - // &actions.MintAsset{ - // To: auth.NewED25519Address(other.PublicKey()), - // Value: 10, - // }, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // bad codec) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) - // }) - - // ginkgo.It("mints another new asset (to self)", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, tx, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.CreateAsset{ - // Symbol: asset2Symbol, - // Decimals: asset2Decimals, - // Metadata: asset2, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // asset2ID = tx.ID() - - // submit, _, _, err = instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.MintAsset{ - // To: rsender, - // Asset: asset2ID, - // Value: 10, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept = expectBlk(instances[0]) - // results = accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - // }) - - // ginkgo.It("mints another new asset (to self) on another account", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, tx, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.CreateAsset{ - // Symbol: asset3Symbol, - // Decimals: asset3Decimals, - // Metadata: asset3, - // }, - // factory2, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // asset3ID = tx.ID() - - // submit, _, _, err = instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.MintAsset{ - // To: rsender2, - // Asset: asset3ID, - // Value: 10, - // }, - // factory2, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept = expectBlk(instances[0]) - // results = accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - // balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - // }) - - // ginkgo.It("import warp message with nil when expected", func() { - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // nil, - // &actions.ImportAsset{}, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // empty warp) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) - // }) - - // ginkgo.It("import warp message empty", func() { - // wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // wm, - // &actions.ImportAsset{}, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // empty warp) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) - // }) - - // ginkgo.It("import with wrong payload", func() { - // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) - // gomega.Ω(err).Should(gomega.BeNil()) - // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // wm, - // &actions.ImportAsset{}, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // invalid object) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) - // }) - - // ginkgo.It("import with invalid payload", func() { - // wt := &actions.WarpTransfer{} - // wtb, err := wt.Marshal() - // gomega.Ω(err).Should(gomega.BeNil()) - // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - // gomega.Ω(err).Should(gomega.BeNil()) - // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - // gomega.Ω(err).Should(gomega.BeNil()) - // tx := chain.NewTx( - // &chain.Base{ - // ChainID: instances[0].chainID, - // Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - // MaxFee: 1000, - // }, - // wm, - // &actions.ImportAsset{}, - // ) - // // Must do manual construction to avoid `tx.Sign` error (would fail with - // // invalid object) - // msg, err := tx.Digest() - // gomega.Ω(err).To(gomega.BeNil()) - // auth, err := factory.Sign(msg) - // gomega.Ω(err).To(gomega.BeNil()) - // tx.Auth = auth - // p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - // gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - // gomega.Ω(p.Err()).To(gomega.BeNil()) - // _, err = instances[0].hcli.SubmitTx( - // context.Background(), - // p.Bytes(), - // ) - // gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) - // }) - - // ginkgo.It("import with wrong destination", func() { - // wt := &actions.WarpTransfer{ - // To: rsender, - // Symbol: []byte("s"), - // Decimals: 2, - // Asset: ids.GenerateTestID(), - // Value: 100, - // Return: false, - // Reward: 100, - // TxID: ids.GenerateTestID(), - // DestinationChainID: ids.GenerateTestID(), - // } - // wtb, err := wt.Marshal() - // gomega.Ω(err).Should(gomega.BeNil()) - // uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - // gomega.Ω(err).Should(gomega.BeNil()) - // wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - // gomega.Ω(err).Should(gomega.BeNil()) - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // wm, - // &actions.ImportAsset{}, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - // // Build block with no context (should fail) - // gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - // <-instances[0].toEngine - // blk, err := instances[0].vm.BuildBlock(context.TODO()) - // gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - // gomega.Ω(blk).To(gomega.BeNil()) - - // // Wait for mempool to be size 1 (txs are restored async) - // for { - // if instances[0].vm.Mempool().Len(context.Background()) > 0 { - // break - // } - // log.Info("waiting for txs to be restored") - // time.Sleep(100 * time.Millisecond) - // } - - // // Build block with context - // accept := expectBlkWithContext(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) - // }) - - // ginkgo.It("export native asset", func() { - // dest := ids.GenerateTestID() - // loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(loan).Should(gomega.Equal(uint64(0))) - - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, tx, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.ExportAsset{ - // To: rsender, - // Asset: ids.Empty, - // Value: 100, - // Return: false, - // Reward: 10, - // Destination: dest, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeTrue()) - // wt := &actions.WarpTransfer{ - // To: rsender, - // Symbol: []byte(nconsts.Symbol), - // Decimals: nconsts.Decimals, - // Asset: ids.Empty, - // Value: 100, - // Return: false, - // Reward: 10, - // TxID: tx.ID(), - // DestinationChainID: dest, - // } - // wtb, err := wt.Marshal() - // gomega.Ω(err).Should(gomega.BeNil()) - // wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) - - // loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(loan).Should(gomega.Equal(uint64(110))) - // }) - - // ginkgo.It("export native asset (invalid return)", func() { - // parser, err := instances[0].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.ExportAsset{ - // To: rsender, - // Asset: ids.Empty, - // Value: 100, - // Return: true, - // Reward: 10, - // Destination: ids.GenerateTestID(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // accept := expectBlk(instances[0]) - // results := accept(false) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // result := results[0] - // gomega.Ω(result.Success).Should(gomega.BeFalse()) - // gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) - // }) + ginkgo.It("rejects mint of native token", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // bad codec) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) + }) + + ginkgo.It("mints another new asset (to self)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset2Symbol, + Decimals: asset2Decimals, + Metadata: asset2, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + asset2ID = tx.ID() + + submit, _, _, err = instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender, + Asset: asset2ID, + Value: 10, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results = accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + }) + + ginkgo.It("mints another new asset (to self) on another account", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset3Symbol, + Decimals: asset3Decimals, + Metadata: asset3, + }, + factory2, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + asset3ID = tx.ID() + + submit, _, _, err = instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender2, + Asset: asset3ID, + Value: 10, + }, + factory2, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results = accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + }) + + ginkgo.It("import warp message with nil when expected", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // empty warp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) + }) + + ginkgo.It("import warp message empty", func() { + wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // empty warp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) + }) + + ginkgo.It("import with wrong payload", func() { + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // invalid object) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) + }) + + ginkgo.It("import with invalid payload", func() { + wt := &actions.WarpTransfer{} + wtb, err := wt.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // invalid object) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) + }) + + ginkgo.It("import with wrong destination", func() { + wt := &actions.WarpTransfer{ + To: rsender, + Symbol: []byte("s"), + Decimals: 2, + Asset: ids.GenerateTestID(), + Value: 100, + Return: false, + Reward: 100, + TxID: ids.GenerateTestID(), + DestinationChainID: ids.GenerateTestID(), + } + wtb, err := wt.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + wm, + &actions.ImportAsset{}, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + // Build block with no context (should fail) + gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + <-instances[0].toEngine + blk, err := instances[0].vm.BuildBlock(context.TODO()) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + gomega.Ω(blk).To(gomega.BeNil()) + + // Wait for mempool to be size 1 (txs are restored async) + for { + if instances[0].vm.Mempool().Len(context.Background()) > 0 { + break + } + log.Info("waiting for txs to be restored") + time.Sleep(100 * time.Millisecond) + } + + // Build block with context + accept := expectBlkWithContext(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) + }) + + ginkgo.It("export native asset", func() { + dest := ids.GenerateTestID() + loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(loan).Should(gomega.Equal(uint64(0))) + + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ExportAsset{ + To: rsender, + Asset: ids.Empty, + Value: 100, + Return: false, + Reward: 10, + Destination: dest, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeTrue()) + wt := &actions.WarpTransfer{ + To: rsender, + Symbol: []byte(nconsts.Symbol), + Decimals: nconsts.Decimals, + Asset: ids.Empty, + Value: 100, + Return: false, + Reward: 10, + TxID: tx.ID(), + DestinationChainID: dest, + } + wtb, err := wt.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) + + loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(loan).Should(gomega.Equal(uint64(110))) + }) + + ginkgo.It("export native asset (invalid return)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ExportAsset{ + To: rsender, + Asset: ids.Empty, + Value: 100, + Return: true, + Reward: 10, + Destination: ids.GenerateTestID(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) + }) }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { From fc585d82cb8fb9783377ac783d0a02ed29cfae40 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 16 Apr 2024 10:44:26 +0100 Subject: [PATCH 17/78] emission instances --- emission/emission.go | 5 + tests/integration/integration_test.go | 174 ++++++++++++++++---------- 2 files changed, 113 insertions(+), 66 deletions(-) diff --git a/emission/emission.go b/emission/emission.go index be4d367..b0baeb8 100644 --- a/emission/emission.go +++ b/emission/emission.go @@ -591,3 +591,8 @@ func (e *Emission) GetLastAcceptedBlockHeight() uint64 { e.c.Logger().Info("fetching last accepted block height") return e.nuklaivm.LastAcceptedBlock().Height() } + +func (e *Emission) GetEmissionValidators() map[ids.NodeID]*Validator { + e.c.Logger().Info("fetching emission validators") + return e.validators +} diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 70ceffc..3493303 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -39,6 +39,7 @@ import ( "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/pubsub" hrpc "github.com/ava-labs/hypersdk/rpc" + "github.com/ava-labs/hypersdk/state" hutils "github.com/ava-labs/hypersdk/utils" "github.com/ava-labs/hypersdk/vm" @@ -49,6 +50,7 @@ import ( "github.com/nuklai/nuklaivm/emission" "github.com/nuklai/nuklaivm/genesis" nrpc "github.com/nuklai/nuklaivm/rpc" + "github.com/nuklai/nuklaivm/storage" ) var ( @@ -138,6 +140,8 @@ var ( // err error nodesFactories []*auth.BLSFactory nodesAddresses []codec.Address + emissions []*emission.Emission + nodesPubKeys []*bls.PublicKey ) type instance struct { @@ -193,6 +197,8 @@ var _ = ginkgo.BeforeSuite(func() { instances = make([]instance, vms) nodesFactories = make([]*auth.BLSFactory, vms) nodesAddresses = make([]codec.Address, vms) + emissions = make([]*emission.Emission, vms) + nodesPubKeys = make([]*bls.PublicKey, vms) gen = genesis.Default() gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} @@ -238,6 +244,7 @@ var _ = ginkgo.BeforeSuite(func() { } nodesFactories[i] = auth.NewBLSFactory(sk) nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) + nodesPubKeys[i] = snowCtx.PublicKey toEngine := make(chan common.Message, 1) db := memdb.New() @@ -257,11 +264,12 @@ var _ = ginkgo.BeforeSuite(func() { app, ) gomega.Ω(err).Should(gomega.BeNil()) - var hd map[string]http.Handler hd, err = v.CreateHandlers(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) + emissions[i] = emission.GetEmission() + hjsonRPCServer := httptest.NewServer(hd[hrpc.JSONRPCEndpoint]) njsonRPCServer := httptest.NewServer(hd[nrpc.JSONRPCEndpoint]) webSocketServer := httptest.NewServer(hd[hrpc.WebSocketEndpoint]) @@ -474,7 +482,8 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { ginkgo.By("ensure balance is updated", func() { balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) + gomega.Ω(balance).To(gomega.Equal(uint64(9999999999899703))) + balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) gomega.Ω(err).To(gomega.BeNil()) gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) @@ -1571,7 +1580,7 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.It("Setup and get initial staked validators", func() { + ginkgo.FIt("Setup and get initial staked validators", func() { currentTime = time.Now().UTC() stakeStartTime = currentTime.Add(2 * time.Minute) stakeEndTime = currentTime.Add(15 * time.Minute) @@ -1613,27 +1622,59 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) - time.Sleep(5 * time.Second) - accept := expectBlk(instances[3]) - results := accept(true) + gomega.Ω(instances[3].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + <-instances[3].toEngine + + blk, err := instances[3].vm.BuildBlock(context.TODO()) + gomega.Ω(err).To(gomega.BeNil()) + + gomega.Ω(blk.Verify(context.TODO())).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = instances[3].vm.SetPreference(context.TODO(), blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + fmt.Println(len(blocks)) + gomega.Ω(blk.Accept(context.TODO())).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + blocks = append(blocks, blk) + fmt.Println(len(blocks)) + + lastAccepted, err := instances[3].vm.LastAccepted(context.TODO()) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + results := blk.(*chain.StatelessBlock).Results() + fmt.Println(results[0].Output) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(results[0].Output).Should(gomega.BeNil()) + + time.Sleep(5 * time.Second) + + // lastAccepted, err = instances[4].vm.LastAccepted(context.TODO()) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) fmt.Printf("balance factory %s %d\n", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) }) ginkgo.By("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[3].nodeID.Bytes(), StakeStartTime: uint64(stakeStartTime.Unix()), @@ -1643,88 +1684,89 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { RewardAddress: rwithdraw0, } - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := nodesFactories[3].Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - nodesFactories[3], - ) - fmt.Println(err) - gomega.Ω(err).Should(gomega.BeNil()) - - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + emissionInstance := emissions[3] + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(0)) + err = emissionInstance.RegisterValidatorStake(instances[3].nodeID, nodesPubKeys[3], stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate) + _, exists := emissionInstance.GetEmissionValidators()[instances[3].nodeID] + gomega.Ω(exists).To(gomega.Equal(true)) + stakedValidator = emissionInstance.GetStakedValidator(instances[3].nodeID) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + validator := stakedValidator[0] + gomega.Ω(validator.IsActive).To(gomega.Equal(true)) + gomega.Ω(validator.StakedAmount).To(gomega.Equal(100_000_000_000)) + err := storage.SubBalance(context.Background(), &state.MockMutable{}, nodesAddresses[3], ids.Empty, stakeInfo.StakedAmount) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(5 * time.Second) - - balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + err = storage.SetRegisterValidatorStake(context.Background(), &state.MockMutable{}, instances[3].nodeID, stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate, stakeInfo.RewardAddress, nodesAddresses[3]) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - - emissionInstance := emission.GetEmission() - currentValidators := emissionInstance.GetAllValidators(context.TODO()) - fmt.Println(currentValidators) - stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - fmt.Println(stakedValidator) - }) - ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) - }) + // OLD ONES - // ginkgo.By("Register validator stake node 1", func() { + // ginkgo.By("Register validator stake node 3", func() { + // parser, err := instances[3].ncli.Parser(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) // stakeInfo := &actions.ValidatorStakeInfo{ - // NodeID: instances[1].nodeID.Bytes(), + // NodeID: instances[3].nodeID.Bytes(), // StakeStartTime: uint64(stakeStartTime.Unix()), // StakeEndTime: uint64(stakeEndTime.Unix()), - // StakedAmount: 100, // TO DO: SAME TEST WITH 50 TO THROUGH ERROR + // StakedAmount: 100_000_000_000, // DelegationFeeRate: uint64(delegationFeeRate), - // RewardAddress: rwithdraw1, + // RewardAddress: rwithdraw0, // } + // stakeInfoBytes, err := stakeInfo.Marshal() // gomega.Ω(err).Should(gomega.BeNil()) - // signature, err := factory.Sign(stakeInfoBytes) + // signature, err := nodesFactories[3].Sign(stakeInfoBytes) // gomega.Ω(err).Should(gomega.BeNil()) // signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) // signature.Marshal(signaturePacker) // authSignature := signaturePacker.Bytes() - // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // submit, _, _, err := instances[3].hcli.GenerateTransaction( // context.Background(), - // parser1, + // parser, // nil, // &actions.RegisterValidatorStake{ // StakeInfo: stakeInfoBytes, // AuthSignature: authSignature, // }, - // factory, + // nodesFactories[3], // ) - // gomega.Ω(err).Should(gomega.HaveOccurred()) - // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) - // }) + // fmt.Println(err) + // gomega.Ω(err).Should(gomega.BeNil()) - // ginkgo.By("Get staked validators", func() { - // validators, err := instances[0].ncli.StakedValidators(context.Background()) + // balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + // fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // time.Sleep(5 * time.Second) + + // balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + // gomega.Ω(err).Should(gomega.BeNil()) + // fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + // // check if gossip/ new state happens + // balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(len(validators)).Should(gomega.Equal(3)) + // fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + + // emissionInstance := emissions[3] + // currentValidators := emissionInstance.GetAllValidators(context.TODO()) + // fmt.Println(currentValidators) + // stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + // fmt.Println(stakedValidator) + // gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + // }) + ginkgo.By("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) + }) + // ginkgo.By("Get validator staked amount after staking", func() { // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) // gomega.Ω(err).Should(gomega.BeNil()) From 52fca7f9e4f8abfda15931c93a03ef878b909b23 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 17 Apr 2024 15:30:59 +0100 Subject: [PATCH 18/78] transfer works and register is called --- tests/integration/new_actions_test.go | 900 ++++++++++++++++++++++++++ 1 file changed, 900 insertions(+) create mode 100644 tests/integration/new_actions_test.go diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go new file mode 100644 index 0000000..442147e --- /dev/null +++ b/tests/integration/new_actions_test.go @@ -0,0 +1,900 @@ +// Copyright (C) 2024, AllianceBlock. All rights reserved. +// See the file LICENSE for licensing terms. + +package integration_test + +import ( + "context" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "net/http" + "net/http/httptest" + "os" + "testing" + "time" + + "github.com/ava-labs/avalanchego/api/metrics" + "github.com/ava-labs/avalanchego/database/memdb" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/snow/choices" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/fatih/color" + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + "go.uber.org/zap" + + "github.com/ava-labs/hypersdk/chain" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/ed25519" + hrpc "github.com/ava-labs/hypersdk/rpc" + "github.com/ava-labs/hypersdk/vm" + + "github.com/nuklai/nuklaivm/actions" + "github.com/nuklai/nuklaivm/auth" + nconsts "github.com/nuklai/nuklaivm/consts" + "github.com/nuklai/nuklaivm/controller" + "github.com/nuklai/nuklaivm/emission" + "github.com/nuklai/nuklaivm/genesis" + nrpc "github.com/nuklai/nuklaivm/rpc" +) + +var ( + logFactory logging.Factory + log logging.Logger +) + +func init() { + logFactory = logging.NewFactory(logging.Config{ + DisplayLevel: logging.Debug, + }) + l, err := logFactory.Make("main") + if err != nil { + panic(err) + } + log = l +} + +func TestIntegration(t *testing.T) { + gomega.RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, "nuklaivm integration test suites") +} + +var ( + requestTimeout time.Duration + vms int + app *appSender +) + +func init() { + flag.DurationVar( + &requestTimeout, + "request-timeout", + 120*time.Second, + "timeout for transaction issuance and confirmation", + ) + flag.IntVar( + &vms, + "vms", + 5, + "number of VMs to create", + ) +} + +var ( + priv ed25519.PrivateKey + factory *auth.ED25519Factory + rsender codec.Address + sender string + + priv2 ed25519.PrivateKey + factory2 *auth.ED25519Factory + rsender2 codec.Address + sender2 string + + asset1 []byte + asset1Symbol []byte + asset1Decimals uint8 + asset1ID ids.ID + asset2 []byte + asset2Symbol []byte + asset2Decimals uint8 + asset2ID ids.ID + asset3 []byte + asset3Symbol []byte + asset3Decimals uint8 + asset3ID ids.ID + + // when used with embedded VMs + genesisBytes []byte + instances []instance + blocks []snowman.Block + + networkID uint32 + gen *genesis.Genesis + + //to be reordered staking vars + currentTime time.Time + stakeStartTime time.Time + stakeEndTime time.Time + delegationFeeRate int + withdraw0 string + withdraw1 string + rwithdraw0 codec.Address + rwithdraw1 codec.Address + rdelegate codec.Address + // parser0 chain.Parser + // err error + nodesFactories []*auth.BLSFactory + nodesAddresses []codec.Address + emissions []*emission.Emission + nodesPubKeys []*bls.PublicKey +) + +type instance struct { + chainID ids.ID + nodeID ids.NodeID + vm *vm.VM + toEngine chan common.Message + JSONRPCServer *httptest.Server + NuklaiJSONRPCServer *httptest.Server + WebSocketServer *httptest.Server + hcli *hrpc.JSONRPCClient // clients for embedded VMs + ncli *nrpc.JSONRPCClient +} + +var _ = ginkgo.BeforeSuite(func() { + log.Info("VMID", zap.Stringer("id", nconsts.ID)) + gomega.Ω(vms).Should(gomega.BeNumerically(">", 1)) + + var err error + priv, err = ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + factory = auth.NewED25519Factory(priv) + rsender = auth.NewED25519Address(priv.PublicKey()) + sender = codec.MustAddressBech32(nconsts.HRP, rsender) + log.Debug( + "generated key", + zap.String("addr", sender), + zap.String("pk", hex.EncodeToString(priv[:])), + ) + + priv2, err = ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + factory2 = auth.NewED25519Factory(priv2) + rsender2 = auth.NewED25519Address(priv2.PublicKey()) + sender2 = codec.MustAddressBech32(nconsts.HRP, rsender2) + log.Debug( + "generated key", + zap.String("addr", sender2), + zap.String("pk", hex.EncodeToString(priv2[:])), + ) + + asset1 = []byte("1") + asset1Symbol = []byte("s1") + asset1Decimals = uint8(1) + asset2 = []byte("2") + asset2Symbol = []byte("s2") + asset2Decimals = uint8(2) + asset3 = []byte("3") + asset3Symbol = []byte("s3") + asset3Decimals = uint8(3) + + // create embedded VMs + instances = make([]instance, vms) + nodesFactories = make([]*auth.BLSFactory, vms) + nodesAddresses = make([]codec.Address, vms) + emissions = make([]*emission.Emission, vms) + nodesPubKeys = make([]*bls.PublicKey, vms) + + gen = genesis.Default() + gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} + gen.MinBlockGap = 0 + gen.CustomAllocation = []*genesis.CustomAllocation{ + { + Address: sender, + Balance: 10_000_000_000_000_000, + }, + } + gen.EmissionBalancer = genesis.EmissionBalancer{ + TotalSupply: 10_000_000, + MaxSupply: 10_000_000_000, + EmissionAddress: sender, + } + genesisBytes, err = json.Marshal(gen) + gomega.Ω(err).Should(gomega.BeNil()) + + networkID = uint32(1) + subnetID := ids.GenerateTestID() + chainID := ids.GenerateTestID() + + app = &appSender{} + for i := range instances { + nodeID := ids.GenerateTestNodeID() + sk, err := bls.NewSecretKey() + gomega.Ω(err).Should(gomega.BeNil()) + l, err := logFactory.Make(nodeID.String()) + gomega.Ω(err).Should(gomega.BeNil()) + dname, err := os.MkdirTemp("", fmt.Sprintf("%s-chainData", nodeID.String())) + gomega.Ω(err).Should(gomega.BeNil()) + snowCtx := &snow.Context{ + NetworkID: networkID, + SubnetID: subnetID, + ChainID: chainID, + NodeID: nodeID, + Log: l, + ChainDataDir: dname, + Metrics: metrics.NewOptionalGatherer(), + PublicKey: bls.PublicFromSecretKey(sk), + WarpSigner: warp.NewSigner(sk, networkID, chainID), + ValidatorState: &validators.TestState{}, + } + nodesFactories[i] = auth.NewBLSFactory(sk) + nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) + nodesPubKeys[i] = snowCtx.PublicKey + + toEngine := make(chan common.Message, 1) + db := memdb.New() + + v := controller.New() + err = v.Initialize( + context.TODO(), + snowCtx, + db, + genesisBytes, + nil, + []byte( + `{"parallelism":3, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, + ), + toEngine, + nil, + app, + ) + gomega.Ω(err).Should(gomega.BeNil()) + var hd map[string]http.Handler + hd, err = v.CreateHandlers(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + + emissions[i] = emission.GetEmission() + + hjsonRPCServer := httptest.NewServer(hd[hrpc.JSONRPCEndpoint]) + njsonRPCServer := httptest.NewServer(hd[nrpc.JSONRPCEndpoint]) + webSocketServer := httptest.NewServer(hd[hrpc.WebSocketEndpoint]) + instances[i] = instance{ + chainID: snowCtx.ChainID, + nodeID: snowCtx.NodeID, + vm: v, + toEngine: toEngine, + JSONRPCServer: hjsonRPCServer, + NuklaiJSONRPCServer: njsonRPCServer, + WebSocketServer: webSocketServer, + hcli: hrpc.NewJSONRPCClient(hjsonRPCServer.URL), + ncli: nrpc.NewJSONRPCClient(njsonRPCServer.URL, snowCtx.NetworkID, snowCtx.ChainID), + } + + // Force sync ready (to mimic bootstrapping from genesis) + v.ForceReady() + } + + // Verify genesis allocates loaded correctly (do here otherwise test may + // check during and it will be inaccurate) + for _, inst := range instances { + ncli := inst.ncli + g, err := ncli.Genesis(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + csupply := uint64(0) + for _, alloc := range g.CustomAllocation { + balance, err := ncli.Balance(context.Background(), alloc.Address, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(alloc.Balance)) + csupply += alloc.Balance + } + exists, symbol, decimals, metadata, supply, owner, warp, err := ncli.Asset(context.Background(), ids.Empty, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(string(symbol)).Should(gomega.Equal(nconsts.Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(uint8(nconsts.Decimals))) + gomega.Ω(string(metadata)).Should(gomega.Equal(nconsts.Name)) + gomega.Ω(supply).Should(gomega.Equal(csupply)) + gomega.Ω(owner).Should(gomega.Equal(codec.MustAddressBech32(nconsts.HRP, codec.EmptyAddress))) + gomega.Ω(warp).Should(gomega.BeFalse()) + } + blocks = []snowman.Block{} + + app.instances = instances + color.Blue("created %d VMs", vms) +}) + +var _ = ginkgo.AfterSuite(func() { + for _, iv := range instances { + iv.JSONRPCServer.Close() + iv.NuklaiJSONRPCServer.Close() + iv.WebSocketServer.Close() + err := iv.vm.Shutdown(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + } +}) + +var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { + ginkgo.FIt("Setup and get initial staked validators", func() { + currentTime = time.Now().UTC() + stakeStartTime = currentTime.Add(2 * time.Second) + stakeEndTime = currentTime.Add(15 * time.Minute) + delegationFeeRate = 50 + + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) + + withdraw1Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) + withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) + + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + validators, err := instances[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + + ginkgo.By("Funding node 3", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[3], + Asset: ids.Empty, + Value: 200_000_000_000, + }, + factory, + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + // app.SendAppGossip(context.Background(), tx.Bytes()) + + // txID, err := instances[3].hcli.SubmitTx(context.Background(), tx.Bytes()) + // fmt.Println(txID) + // gomega.Ω(err).Should(gomega.BeNil()) + + // gomega.Ω(instances[3].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) + + // gomega.Ω(instances[3].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + // <-instances[3].toEngine + + // blk, err := instances[3].vm.BuildBlock(context.TODO()) + // gomega.Ω(err).To(gomega.BeNil()) + + // gomega.Ω(blk.Verify(context.TODO())).To(gomega.BeNil()) + // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + // err = instances[3].vm.SetPreference(context.TODO(), blk.ID()) + // gomega.Ω(err).To(gomega.BeNil()) + + // fmt.Println(len(blocks)) + // gomega.Ω(blk.Accept(context.TODO())).To(gomega.BeNil()) + // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + // blocks = append(blocks, blk) + // fmt.Println(len(blocks)) + + // lastAccepted, err := instances[3].vm.LastAccepted(context.TODO()) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + // results := blk.(*chain.StatelessBlock).Results() + // fmt.Println(results[0].Output) + // gomega.Ω(results).Should(gomega.HaveLen(1)) + // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // gomega.Ω(results[0].Output).Should(gomega.BeNil()) + + // lastAccepted, err = instances[4].vm.LastAccepted(context.TODO()) + // gomega.Ω(err).To(gomega.BeNil()) + // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + // sps := state.NewSimpleMutable(instances[3]) + // instances[3].vm.Gossiper().Force(context.TODO()) + // instances[3].vm.Builder().Force(context.TODO()) + // instances[3].vm.ForceReady() + // instances[3].vm.PutDiskIsSyncing(true) + + // time.Sleep(5 * time.Second) + + accept := expectBlk(instances[0]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(1)) + + blk1, err := instances[3].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk1, err = instances[4].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk1, err = instances[2].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk1, err = instances[1].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) + fmt.Printf("balance factory %s %d\n", sender, balance) + gomega.Ω(err).Should(gomega.BeNil()) + }) + + // ginkgo.By("Register validator stake node 3", func() { + // stakeInfo := &actions.ValidatorStakeInfo{ + // NodeID: instances[3].nodeID.Bytes(), + // StakeStartTime: uint64(stakeStartTime.Unix()), + // StakeEndTime: uint64(stakeEndTime.Unix()), + // StakedAmount: 100_000_000_000, + // DelegationFeeRate: uint64(delegationFeeRate), + // RewardAddress: rwithdraw0, + // } + + // emissionInstance := emissions[3] + // stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + // gomega.Ω(len(stakedValidator)).To(gomega.Equal(0)) + // err = emissionInstance.RegisterValidatorStake(instances[3].nodeID, nodesPubKeys[3], stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate) + // _, exists := emissionInstance.GetEmissionValidators()[instances[3].nodeID] + // gomega.Ω(exists).To(gomega.Equal(true)) + // stakedValidator = emissionInstance.GetStakedValidator(instances[3].nodeID) + // gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + // validator := stakedValidator[0] + // gomega.Ω(validator.IsActive).To(gomega.Equal(true)) + // gomega.Ω(validator.StakedAmount).To(gomega.Equal(100_000_000_000)) + // err := storage.SubBalance(context.Background(), &state.MockMutable{}, nodesAddresses[3], ids.Empty, stakeInfo.StakedAmount) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = storage.SetRegisterValidatorStake(context.Background(), &state.MockMutable{}, instances[3].nodeID, stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate, stakeInfo.RewardAddress, nodesAddresses[3]) + // gomega.Ω(err).Should(gomega.BeNil()) + // }) + + // OLD ONES + + ginkgo.By("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[3].Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[3], + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(5 * time.Second) + + fmt.Println(len(blocks)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + // gomega.Ω(len(blocks)).Should(gomega.Equal(2)) + + blk2, err := instances[0].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk2, err = instances[1].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk2, err = instances[2].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + blk2, err = instances[4].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + + emissionInstance := emissions[3] + currentValidators := emissionInstance.GetAllValidators(context.TODO()) + fmt.Println(currentValidators) + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + fmt.Println(stakedValidator) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + + }) + + ginkgo.By("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) + }) + + // ginkgo.By("Get validator staked amount after staking", func() { + // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + // _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) + // }) + + // ginkgo.By("Get staked validators", func() { + // validators, err := instances[0].ncli.StakedValidators(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(len(validators)).Should(gomega.Equal(2)) + // }) + + // ginkgo.By("Transfer NAI to user and delegate stake to node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.Transfer{ + // To: rdelegate, + // Asset: ids.Empty, + // Value: 100, + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // currentTime := time.Now().UTC() + // userStakeStartTime := currentTime.Add(2 * time.Minute) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err = instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.DelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // StakeStartTime: uint64(userStakeStartTime.Unix()), + // StakedAmount: 50, + // RewardAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Delegate stake to node 1", func() { + // currentTime = time.Now().UTC() + // userStakeStartTime := currentTime.Add(2 * time.Minute) + // gomega.Ω(err).Should(gomega.BeNil()) + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.DelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // StakeStartTime: uint64(userStakeStartTime.Unix()), + // StakedAmount: 50, + // RewardAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get user stake before claim", func() { + // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) + // }) + + // ginkgo.By("Claim delegation stake rewards from node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.ClaimDelegationStakeRewards{ + // NodeID: instances[0].nodeID.Bytes(), + // UserStakeAddress: rdelegate, + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get user stake after claim", func() { + // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) + // }) + + // ginkgo.By("Undelegate user stake from node 0", func() { + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.UndelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // add more ginko.By where error should be thrown with wrong data input + // ginkgo.By("Claim validator node 0 stake reward", func() { + // // ClaimValidatorStakeRewards + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.ClaimValidatorStakeRewards{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Withdraw validator node 0 stake", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[0].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Get validator stake after staking withdraw ", func() { + // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + // }) + + // ginkgo.By("Withdraw validator node 1 stake with wrong key", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[1].nodeID.Bytes(), + // }, + // factory2, + // ) + // gomega.Ω(err).ShouldNot(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) + // }) + + // staking withdraw then user delegate withdraw on node 1 + // ginkgo.By("Withdraw validator node 1 stake", func() { + // // WithdrawValidatorStake + // // TO DO: test claim with a wrong key + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.WithdrawValidatorStake{ + // NodeID: instances[1].nodeID.Bytes(), + // }, + // factory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + + // ginkgo.By("Undelegate user stake from node 1", func() { + // submit, _, _, err := instances[1].hcli.GenerateTransaction( + // context.Background(), + // parser0, + // nil, + // &actions.UndelegateUserStake{ + // NodeID: instances[0].nodeID.Bytes(), + // }, + // delegateFactory, + // ) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + // }) + }) + +}) + +func expectBlk(i instance) func(bool) []*chain.Result { + ctx := context.TODO() + + // manually signal ready + gomega.Ω(i.vm.Builder().Force(ctx)).To(gomega.BeNil()) + // manually ack ready sig as in engine + <-i.toEngine + + blk, err := i.vm.BuildBlock(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) + + gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = i.vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + return func(add bool) []*chain.Result { + gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + + if add { + blocks = append(blocks, blk) + } + + lastAccepted, err := i.vm.LastAccepted(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + return blk.(*chain.StatelessBlock).Results() + } +} + +// TODO: unify with expectBlk +func expectBlkWithContext(i instance) func(bool) []*chain.Result { + ctx := context.TODO() + + // manually signal ready + gomega.Ω(i.vm.Builder().Force(ctx)).To(gomega.BeNil()) + // manually ack ready sig as in engine + <-i.toEngine + + bctx := &block.Context{PChainHeight: 1} + blk, err := i.vm.BuildBlockWithContext(ctx, bctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) + cblk := blk.(block.WithVerifyContext) + + gomega.Ω(cblk.VerifyWithContext(ctx, bctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = i.vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + return func(add bool) []*chain.Result { + gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + + if add { + blocks = append(blocks, blk) + } + + lastAccepted, err := i.vm.LastAccepted(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + return blk.(*chain.StatelessBlock).Results() + } +} + +var _ common.AppSender = &appSender{} + +type appSender struct { + next int + instances []instance +} + +func (app *appSender) SendAppGossip(ctx context.Context, appGossipBytes []byte) error { + n := len(app.instances) + sender := app.instances[app.next].nodeID + app.next++ + app.next %= n + return app.instances[app.next].vm.AppGossip(ctx, sender, appGossipBytes) +} + +func (*appSender) SendAppRequest(context.Context, set.Set[ids.NodeID], uint32, []byte) error { + return nil +} + +func (*appSender) SendAppResponse(context.Context, ids.NodeID, uint32, []byte) error { + return nil +} + +func (*appSender) SendAppGossipSpecific(context.Context, set.Set[ids.NodeID], []byte) error { + return nil +} + +func (*appSender) SendCrossChainAppRequest(context.Context, ids.ID, uint32, []byte) error { + return nil +} + +func (*appSender) SendCrossChainAppResponse(context.Context, ids.ID, uint32, []byte) error { + return nil +} From 305eb67b1ab4615a2008c9b21d4b6f86ab398b85 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 17 Apr 2024 15:47:21 +0100 Subject: [PATCH 19/78] add import function --- tests/integration/new_actions_test.go | 162 +++++++++++--------------- 1 file changed, 66 insertions(+), 96 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 442147e..021442c 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -369,54 +369,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // app.SendAppGossip(context.Background(), tx.Bytes()) - // txID, err := instances[3].hcli.SubmitTx(context.Background(), tx.Bytes()) - // fmt.Println(txID) - // gomega.Ω(err).Should(gomega.BeNil()) - - // gomega.Ω(instances[3].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // gomega.Ω(instances[3].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - // <-instances[3].toEngine - - // blk, err := instances[3].vm.BuildBlock(context.TODO()) - // gomega.Ω(err).To(gomega.BeNil()) - - // gomega.Ω(blk.Verify(context.TODO())).To(gomega.BeNil()) - // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - // err = instances[3].vm.SetPreference(context.TODO(), blk.ID()) - // gomega.Ω(err).To(gomega.BeNil()) - - // fmt.Println(len(blocks)) - // gomega.Ω(blk.Accept(context.TODO())).To(gomega.BeNil()) - // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - // blocks = append(blocks, blk) - // fmt.Println(len(blocks)) - - // lastAccepted, err := instances[3].vm.LastAccepted(context.TODO()) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - // results := blk.(*chain.StatelessBlock).Results() - // fmt.Println(results[0].Output) - // gomega.Ω(results).Should(gomega.HaveLen(1)) - // gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // gomega.Ω(results[0].Output).Should(gomega.BeNil()) - - // lastAccepted, err = instances[4].vm.LastAccepted(context.TODO()) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - // sps := state.NewSimpleMutable(instances[3]) - // instances[3].vm.Gossiper().Force(context.TODO()) - // instances[3].vm.Builder().Force(context.TODO()) - // instances[3].vm.ForceReady() - // instances[3].vm.PutDiskIsSyncing(true) - - // time.Sleep(5 * time.Second) - accept := expectBlk(instances[0]) results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) @@ -424,33 +376,42 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(blocks)).Should(gomega.Equal(1)) - blk1, err := instances[3].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk1, err := instances[3].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) - blk1, err = instances[4].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + blk := blocks[0] + ImportBlockToInstance(instances[3].vm, blk) - blk1, err = instances[2].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk1, err = instances[4].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) - blk1, err = instances[1].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + ImportBlockToInstance(instances[4].vm, blk) + + // blk1, err = instances[2].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + + ImportBlockToInstance(instances[2].vm, blk) + + // blk1, err = instances[1].vm.ParseBlock(context.Background(), blocks[0].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk1.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + + ImportBlockToInstance(instances[1].vm, blk) balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -543,33 +504,33 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // gomega.Ω(len(blocks)).Should(gomega.Equal(2)) - blk2, err := instances[0].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk2, err := instances[0].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) - blk2, err = instances[1].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk2, err = instances[1].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) - blk2, err = instances[2].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk2, err = instances[2].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) - blk2, err = instances[4].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) + // blk2, err = instances[4].vm.ParseBlock(context.Background(), blocks[1].Bytes()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Verify(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) + // err = blk2.Accept(context.Background()) + // gomega.Ω(err).Should(gomega.BeNil()) balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -898,3 +859,12 @@ func (*appSender) SendCrossChainAppRequest(context.Context, ids.ID, uint32, []by func (*appSender) SendCrossChainAppResponse(context.Context, ids.ID, uint32, []byte) error { return nil } + +func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { + blk, err := vm.ParseBlock(context.Background(), block.Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) +} From eff65cde73d766fcea9345b31002625e45151c32 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 17 Apr 2024 15:48:12 +0100 Subject: [PATCH 20/78] clean code --- tests/integration/new_actions_test.go | 29 --------------------------- 1 file changed, 29 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 021442c..4441dbc 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -427,35 +427,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) }) - // ginkgo.By("Register validator stake node 3", func() { - // stakeInfo := &actions.ValidatorStakeInfo{ - // NodeID: instances[3].nodeID.Bytes(), - // StakeStartTime: uint64(stakeStartTime.Unix()), - // StakeEndTime: uint64(stakeEndTime.Unix()), - // StakedAmount: 100_000_000_000, - // DelegationFeeRate: uint64(delegationFeeRate), - // RewardAddress: rwithdraw0, - // } - - // emissionInstance := emissions[3] - // stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - // gomega.Ω(len(stakedValidator)).To(gomega.Equal(0)) - // err = emissionInstance.RegisterValidatorStake(instances[3].nodeID, nodesPubKeys[3], stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate) - // _, exists := emissionInstance.GetEmissionValidators()[instances[3].nodeID] - // gomega.Ω(exists).To(gomega.Equal(true)) - // stakedValidator = emissionInstance.GetStakedValidator(instances[3].nodeID) - // gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - // validator := stakedValidator[0] - // gomega.Ω(validator.IsActive).To(gomega.Equal(true)) - // gomega.Ω(validator.StakedAmount).To(gomega.Equal(100_000_000_000)) - // err := storage.SubBalance(context.Background(), &state.MockMutable{}, nodesAddresses[3], ids.Empty, stakeInfo.StakedAmount) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = storage.SetRegisterValidatorStake(context.Background(), &state.MockMutable{}, instances[3].nodeID, stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate, stakeInfo.RewardAddress, nodesAddresses[3]) - // gomega.Ω(err).Should(gomega.BeNil()) - // }) - - // OLD ONES - ginkgo.By("Register validator stake node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) From 4d538393d3bbad2532fcf7235e6b009046f0cf40 Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 18 Apr 2024 15:35:28 +0100 Subject: [PATCH 21/78] create interface to be able to mock emission --- controller/controller.go | 33 +- controller/resolutions.go | 3 +- emission/emission.go | 132 +++--- emission/helpers.go | 49 +++ emission/manual.go | 607 ++++++++++++++++++++++++++ emission/tracker.go | 39 ++ tests/integration/new_actions_test.go | 22 +- 7 files changed, 808 insertions(+), 77 deletions(-) create mode 100644 emission/helpers.go create mode 100644 emission/manual.go create mode 100644 emission/tracker.go diff --git a/controller/controller.go b/controller/controller.go index ce4a809..78696d1 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -45,7 +45,7 @@ type Controller struct { metaDB database.Database - emission *emission.Emission // Emission Balancer for NuklaiVM + emission emission.Tracker // Emission Balancer for NuklaiVM } func New() *vm.VM { @@ -123,13 +123,24 @@ func (c *Controller) Initialize( // Create builder and gossiper var ( - build builder.Builder - gossip gossiper.Gossiper + build builder.Builder + gossip gossiper.Gossiper + tracker emission.Tracker ) + + // Initialize emission balancer + emissionAddr, err := codec.ParseAddressBech32(nconsts.HRP, c.genesis.EmissionBalancer.EmissionAddress) + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err + } + + fmt.Println("-------------CONTROLLER/CONTROLLER.GO %b", c.config) if c.config.TestMode { c.inner.Logger().Info("running build and gossip in test mode") build = builder.NewManual(inner) gossip = gossiper.NewManual(inner) + tracker = emission.NewManual(c, c.inner, c.genesis.EmissionBalancer.TotalSupply, c.genesis.EmissionBalancer.MaxSupply, emissionAddr) + c.emission = tracker } else { build = builder.NewTime(inner) gcfg := gossiper.DefaultProposerConfig() @@ -142,15 +153,10 @@ func (c *Controller) Initialize( if err != nil { return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err } + tracker = emission.NewEmission(c, c.inner, c.genesis.EmissionBalancer.TotalSupply, c.genesis.EmissionBalancer.MaxSupply, emissionAddr) + c.emission = tracker } - // Initialize emission balancer - emissionAddr, err := codec.ParseAddressBech32(nconsts.HRP, c.genesis.EmissionBalancer.EmissionAddress) - if err != nil { - return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err - } - c.emission = emission.New(c, c.inner, c.genesis.EmissionBalancer.TotalSupply, c.genesis.EmissionBalancer.MaxSupply, emissionAddr) - return c.config, c.genesis, build, gossip, blockDB, stateDB, apis, nconsts.ActionRegistry, nconsts.AuthRegistry, auth.Engines(), nil } @@ -247,14 +253,15 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er } } + emissionAccount, totalSupply, maxSupply, _, _ := c.emission.GetInfo() // Distribute fees if totalFee > 0 { c.emission.DistributeFees(totalFee) - emissionAddress, err := codec.AddressBech32(nconsts.HRP, c.emission.EmissionAccount.Address) + emissionAddress, err := codec.AddressBech32(nconsts.HRP, emissionAccount.Address) if err != nil { return err // This should never happen } - c.inner.Logger().Info("distributed fees to Emission and Validators", zap.Uint64("current block height", c.inner.LastAcceptedBlock().Height()), zap.Uint64("total fee", totalFee), zap.Uint64("total supply", c.emission.TotalSupply), zap.Uint64("max supply", c.emission.MaxSupply), zap.Uint64("rewards per epock", c.emission.GetRewardsPerEpoch()), zap.String("emission address", emissionAddress), zap.Uint64("emission address unclaimed balance", c.emission.EmissionAccount.UnclaimedBalance)) + c.inner.Logger().Info("distributed fees to Emission and Validators", zap.Uint64("current block height", c.inner.LastAcceptedBlock().Height()), zap.Uint64("total fee", totalFee), zap.Uint64("total supply", totalSupply), zap.Uint64("max supply", maxSupply), zap.Uint64("rewards per epock", c.emission.GetRewardsPerEpoch()), zap.String("emission address", emissionAddress), zap.Uint64("emission address unclaimed balance", emissionAccount.UnclaimedBalance)) c.metrics.feesDistributed.Add(float64(totalFee)) } @@ -262,7 +269,7 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er mintNewNAI := c.emission.MintNewNAI() if mintNewNAI > 0 { c.emission.AddToTotalSupply(mintNewNAI) - c.inner.Logger().Info("minted new NAI", zap.Uint64("current block height", c.inner.LastAcceptedBlock().Height()), zap.Uint64("newly minted NAI", mintNewNAI), zap.Uint64("total supply", c.emission.TotalSupply), zap.Uint64("max supply", c.emission.MaxSupply)) + c.inner.Logger().Info("minted new NAI", zap.Uint64("current block height", c.inner.LastAcceptedBlock().Height()), zap.Uint64("newly minted NAI", mintNewNAI), zap.Uint64("total supply", totalSupply), zap.Uint64("max supply", maxSupply)) } return batch.Write() diff --git a/controller/resolutions.go b/controller/resolutions.go index 2db7f91..5e682e8 100644 --- a/controller/resolutions.go +++ b/controller/resolutions.go @@ -59,7 +59,8 @@ func (c *Controller) GetLoanFromState( } func (c *Controller) GetEmissionInfo() (uint64, uint64, uint64, uint64, emission.EmissionAccount, emission.EpochTracker, error) { - return c.emission.TotalSupply, c.emission.MaxSupply, c.emission.TotalStaked, c.emission.GetRewardsPerEpoch(), c.emission.EmissionAccount, c.emission.EpochTracker, nil + emissionAccount, totalSupply, maxSupply, totalStaked, epochTracker := c.emission.GetInfo() + return totalSupply, maxSupply, totalStaked, c.emission.GetRewardsPerEpoch(), emissionAccount, epochTracker, nil } func (c *Controller) GetValidators(ctx context.Context, staked bool) ([]*emission.Validator, error) { diff --git a/emission/emission.go b/emission/emission.go index b0baeb8..7d919e4 100644 --- a/emission/emission.go +++ b/emission/emission.go @@ -15,37 +15,38 @@ import ( "github.com/nuklai/nuklaivm/storage" ) -var ( - emission *Emission - once sync.Once -) - -type Validator struct { - IsActive bool `json:"isActive"` // Indicates if the validator is currently active - NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator - PublicKey []byte `json:"publicKey"` // Public key of the validator - StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator - UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator - DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations - DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator - UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators - - delegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height - epochRewards map[uint64]uint64 // Rewards per epoch - stakeStartTime time.Time // Start time of the stake - stakeEndTime time.Time // End time of the stake -} - -type EmissionAccount struct { - Address codec.Address `json:"address"` - UnclaimedBalance uint64 `json:"unclaimedBalance"` -} - -type EpochTracker struct { - BaseAPR float64 `json:"baseAPR"` // Base APR to use - BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use - EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch -} +var _ Tracker = (*Emission)(nil) + +// var ( +// emission *Emission +// ) + +// type Validator struct { +// IsActive bool `json:"isActive"` // Indicates if the validator is currently active +// NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator +// PublicKey []byte `json:"publicKey"` // Public key of the validator +// StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator +// UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator +// DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations +// DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator +// UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators + +// DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height +// epochRewards map[uint64]uint64 // Rewards per epoch +// stakeStartTime time.Time // Start time of the stake +// stakeEndTime time.Time // End time of the stake +// } + +// type EmissionAccount struct { +// Address codec.Address `json:"address"` +// UnclaimedBalance uint64 `json:"unclaimedBalance"` +// } + +// type EpochTracker struct { +// BaseAPR float64 `json:"baseAPR"` // Base APR to use +// BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use +// EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch +// } type Emission struct { c Controller @@ -65,7 +66,7 @@ type Emission struct { // New initializes the Emission struct with initial parameters and sets up the validators heap // and indices map. -func New(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddress codec.Address) *Emission { +func NewEmission(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddress codec.Address) *Emission { once.Do(func() { c.Logger().Info("Initializing emission with max supply and rewards per block settings") @@ -91,13 +92,13 @@ func New(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddre }, } }) - return emission + return emission.(*Emission) } -// GetEmission returns the singleton instance of Emission -func GetEmission() *Emission { - return emission -} +// // GetEmission returns the singleton instance of Emission +// func GetEmission() *Emission { +// return emission +// } // AddToTotalSupply increases the total supply of NAI by a specified amount, ensuring it // does not exceed the max supply. @@ -121,12 +122,12 @@ func (e *Emission) GetNumDelegators(nodeID ids.NodeID) int { // Get delegators for all validators if nodeID == ids.EmptyNodeID { for _, validator := range e.validators { - numDelegators += len(validator.delegatorsLastClaim) + numDelegators += len(validator.DelegatorsLastClaim) } } else { // Get delegators for a specific validator if validator, exists := e.validators[nodeID]; exists { - numDelegators = len(validator.delegatorsLastClaim) + numDelegators = len(validator.DelegatorsLastClaim) } } @@ -173,7 +174,7 @@ func (e *Emission) CalculateUserDelegationRewards(nodeID ids.NodeID, actor codec } // Check if the delegator exists - lastClaimHeight, exists := validator.delegatorsLastClaim[actor] + lastClaimHeight, exists := validator.DelegatorsLastClaim[actor] if !exists { return 0, ErrDelegatorNotFound } @@ -236,7 +237,7 @@ func (e *Emission) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls. PublicKey: bls.PublicKeyToBytes(nodePublicKey), StakedAmount: stakedAmount, DelegationFeeRate: float64(delegationFeeRate) / 100.0, // Convert to decimal - delegatorsLastClaim: make(map[codec.Address]uint64), + DelegatorsLastClaim: make(map[codec.Address]uint64), epochRewards: make(map[uint64]uint64), stakeStartTime: time.Unix(int64(stakeStartTime), 0).UTC(), stakeEndTime: time.Unix(int64(stakeEndTime), 0).UTC(), @@ -272,7 +273,7 @@ func (e *Emission) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { validator.IsActive = false // If there are no more delegators, get the rewards and remove the validator - if len(validator.delegatorsLastClaim) == 0 { + if len(validator.DelegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 e.TotalStaked -= validator.DelegatedAmount @@ -296,7 +297,7 @@ func (e *Emission) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.A } // Check if the delegator was already staked - if _, exists := validator.delegatorsLastClaim[delegatorAddress]; exists { + if _, exists := validator.DelegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } @@ -311,7 +312,7 @@ func (e *Emission) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.A } // Update the delegator's stake - validator.delegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() + validator.DelegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() return nil } @@ -330,7 +331,7 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s } // Check if the delegator exists - if _, exists := validator.delegatorsLastClaim[actor]; !exists { + if _, exists := validator.DelegatorsLastClaim[actor]; !exists { return 0, ErrDelegatorNotFound } @@ -340,7 +341,7 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s if err != nil { return 0, err } - validator.delegatorsLastClaim[actor] = currentBlockHeight + validator.DelegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= rewardAmount // Reset unclaimed rewards // Update the validator's stake @@ -353,10 +354,10 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s } // Remove the delegator's entry - delete(validator.delegatorsLastClaim, actor) + delete(validator.DelegatorsLastClaim, actor) // If the validator is inactive and has no more delegators, remove the validator - if !validator.IsActive && len(validator.delegatorsLastClaim) == 0 { + if !validator.IsActive && len(validator.DelegatorsLastClaim) == 0 { delete(e.validators, nodeID) } @@ -383,7 +384,7 @@ func (e *Emission) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) ( validator.UnclaimedStakedReward = 0 // Reset unclaimed rewards // If there are no more delegators, get the rewards - if len(validator.delegatorsLastClaim) == 0 { + if len(validator.DelegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 } @@ -394,7 +395,7 @@ func (e *Emission) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) ( if err != nil { return 0, err } - validator.delegatorsLastClaim[actor] = currentBlockHeight + validator.DelegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= reward // Reset unclaimed rewards rewardAmount = reward } @@ -446,7 +447,7 @@ func (e *Emission) MintNewNAI() uint64 { // Calculate the rewards for the validator and for delegation validatorReward, delegationReward := uint64(0), uint64(0) - if len(validator.delegatorsLastClaim) > 0 { + if len(validator.DelegatorsLastClaim) > 0 { validatorReward, delegationReward = distributeValidatorRewards(totalValidatorReward, validator.DelegationFeeRate, validator.DelegatedAmount) } @@ -519,7 +520,7 @@ func (e *Emission) DistributeFees(fee uint64) { totalValidatorFee := uint64(float64(validatorStake) * feesPerStakeUnit) validatorFee, delegationFee := uint64(0), uint64(0) - if len(validator.delegatorsLastClaim) > 0 { + if len(validator.DelegatorsLastClaim) > 0 { validatorFee, delegationFee = distributeValidatorRewards(totalValidatorFee, validator.DelegationFeeRate, validator.DelegatedAmount) } validator.UnclaimedStakedReward += validatorFee @@ -527,14 +528,19 @@ func (e *Emission) DistributeFees(fee uint64) { } } -func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { - delegationRewards := uint64(0) - if delegatedAmount > 0 { - delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) - } - validatorRewards := totalValidatorReward - delegationRewards - return validatorRewards, delegationRewards -} +// func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { +// delegationRewards := uint64(0) +// if delegatedAmount > 0 { +// delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) +// } +// validatorRewards := totalValidatorReward - delegationRewards +// return validatorRewards, delegationRewards +// } + +// GetEmission returns the singleton instance of Emission +// func GetEmission() *Emission { +// return emission +// } // GetStakedValidator retrieves the details of a specific validator by their NodeID. func (e *Emission) GetStakedValidator(nodeID ids.NodeID) []*Validator { @@ -573,7 +579,7 @@ func (e *Emission) GetAllValidators(ctx context.Context) []*Validator { v.DelegationFeeRate = stakedValidator[0].DelegationFeeRate v.DelegatedAmount = stakedValidator[0].DelegatedAmount v.UnclaimedDelegatedReward = stakedValidator[0].UnclaimedDelegatedReward - v.delegatorsLastClaim = stakedValidator[0].delegatorsLastClaim + v.DelegatorsLastClaim = stakedValidator[0].DelegatorsLastClaim } validators = append(validators, &v) } @@ -596,3 +602,7 @@ func (e *Emission) GetEmissionValidators() map[ids.NodeID]*Validator { e.c.Logger().Info("fetching emission validators") return e.validators } + +func (e *Emission) GetInfo() (emissionAccount EmissionAccount, totalSupply uint64, maxSupply uint64, totalStaked uint64, epochTracker EpochTracker) { + return e.EmissionAccount, e.TotalSupply, e.MaxSupply, e.TotalStaked, e.EpochTracker +} diff --git a/emission/helpers.go b/emission/helpers.go new file mode 100644 index 0000000..3844c1f --- /dev/null +++ b/emission/helpers.go @@ -0,0 +1,49 @@ +package emission + +import ( + "sync" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/codec" +) + +var ( + once sync.Once +) + +type Validator struct { + IsActive bool `json:"isActive"` // Indicates if the validator is currently active + NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator + PublicKey []byte `json:"publicKey"` // Public key of the validator + StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator + UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator + DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations + DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator + UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators + + DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height + epochRewards map[uint64]uint64 // Rewards per epoch + stakeStartTime time.Time // Start time of the stake + stakeEndTime time.Time // End time of the stake +} + +type EmissionAccount struct { + Address codec.Address `json:"address"` + UnclaimedBalance uint64 `json:"unclaimedBalance"` +} + +type EpochTracker struct { + BaseAPR float64 `json:"baseAPR"` // Base APR to use + BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use + EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch +} + +func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { + delegationRewards := uint64(0) + if delegatedAmount > 0 { + delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) + } + validatorRewards := totalValidatorReward - delegationRewards + return validatorRewards, delegationRewards +} diff --git a/emission/manual.go b/emission/manual.go new file mode 100644 index 0000000..1b4865e --- /dev/null +++ b/emission/manual.go @@ -0,0 +1,607 @@ +// Copyright (C) 2024, AllianceBlock. All rights reserved. +// See the file LICENSE for licensing terms. + +package emission + +import ( + "context" + "sync" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/bls" + "github.com/ava-labs/hypersdk/state" + "github.com/nuklai/nuklaivm/storage" +) + +var _ Tracker = (*Manual)(nil) + +// var ( +// manualEmission *Manual +// ) + +// var ( +// emission *Emission +// once sync.Once +// ) + +// type Validator struct { +// IsActive bool `json:"isActive"` // Indicates if the validator is currently active +// NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator +// PublicKey []byte `json:"publicKey"` // Public key of the validator +// StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator +// UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator +// DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations +// DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator +// UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators + +// DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height +// epochRewards map[uint64]uint64 // Rewards per epoch +// stakeStartTime time.Time // Start time of the stake +// stakeEndTime time.Time // End time of the stake +// } + +// type EmissionAccount struct { +// Address codec.Address `json:"address"` +// UnclaimedBalance uint64 `json:"unclaimedBalance"` +// } + +// type EpochTracker struct { +// BaseAPR float64 `json:"baseAPR"` // Base APR to use +// BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use +// EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch +// } + +type Manual struct { + c Controller + nuklaivm NuklaiVM + + TotalSupply uint64 `json:"totalSupply"` // Total supply of NAI + MaxSupply uint64 `json:"maxSupply"` // Max supply of NAI + EmissionAccount EmissionAccount `json:"emissionAccount"` // Emission Account Info + + validators map[ids.NodeID]*Validator + CurrentValidators []*Validator + TotalStaked uint64 `json:"totalStaked"` // Total staked NAI + + EpochTracker EpochTracker `json:"epochTracker"` // Epoch Tracker Info + + lock sync.RWMutex +} + +// New initializes the Emission struct with initial parameters and sets up the validators heap +// and indices map. +func NewManual(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddress codec.Address) *Manual { + once.Do(func() { + c.Logger().Info("Initializing emission with max supply and rewards per block settings") + + if maxSupply == 0 { + maxSupply = GetStakingConfig().RewardConfig.SupplyCap // Use the staking config's supply cap if maxSupply is not specified + } + + emission = &Manual{ // Create the Emission instance with initialized values + c: c, + nuklaivm: vm, + TotalSupply: totalSupply, + MaxSupply: maxSupply, + EmissionAccount: EmissionAccount{ // Setup the emission account with the provided address + Address: emissionAddress, + }, + validators: make(map[ids.NodeID]*Validator), + EpochTracker: EpochTracker{ + BaseAPR: 0.25, // 25% APR + BaseValidators: 100, + EpochLength: 10, + // TODO: Enable this in production + // EpochLength: 1200, // roughly 1 hour with 3 sec block time + }, + } + }) + return emission.(*Manual) +} + +// // GetEmission returns the singleton instance of Emission +// func GetEmission() *Emission { +// return emission +// } + +// AddToTotalSupply increases the total supply of NAI by a specified amount, ensuring it +// does not exceed the max supply. +func (e *Manual) AddToTotalSupply(amount uint64) uint64 { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("adding to the total supply of NAI") + if e.TotalSupply+amount > e.MaxSupply { + amount = e.MaxSupply - e.TotalSupply // Adjust to not exceed max supply + } + e.TotalSupply += amount + return e.TotalSupply +} + +// GetNumDelegators returns the total number of delegators across all validators. +func (e *Manual) GetNumDelegators(nodeID ids.NodeID) int { + e.c.Logger().Info("fetching total number of delegators") + + numDelegators := 0 + // Get delegators for all validators + if nodeID == ids.EmptyNodeID { + for _, validator := range e.validators { + numDelegators += len(validator.DelegatorsLastClaim) + } + } else { + // Get delegators for a specific validator + if validator, exists := e.validators[nodeID]; exists { + numDelegators = len(validator.DelegatorsLastClaim) + } + } + + return numDelegators +} + +// GetAPRForValidators calculates the Annual Percentage Rate (APR) for validators +// based on the number of validators. +func (e *Manual) GetAPRForValidators() float64 { + e.c.Logger().Info("getting APR for validators") + + apr := e.EpochTracker.BaseAPR // APR is expressed per year as a decimal, e.g., 0.25 for 25% + // Beyond baseValidators, APR decreases proportionately + baseValidators := int(e.EpochTracker.BaseValidators) + if len(e.validators) > baseValidators { + apr /= float64(len(e.validators)) / float64(baseValidators) + } + return apr +} + +// GetRewardsPerEpoch calculates the rewards per epock based on the total staked amount +// and the APR for validators. +func (e *Manual) GetRewardsPerEpoch() uint64 { + e.c.Logger().Info("getting rewards per epock") + + // Calculate total rewards for the epoch based on APR and staked amount + rewardsPerBlock := uint64((float64(e.TotalStaked) * e.GetAPRForValidators() / 365 / 24 / 60 / 60) * (float64(e.EpochTracker.EpochLength) * 3)) // 3 seconds per block + + if e.TotalSupply+rewardsPerBlock > e.MaxSupply { + rewardsPerBlock = e.MaxSupply - e.TotalSupply // Adjust to not exceed max supply + } + return rewardsPerBlock +} + +// CalculateUserDelegationRewards computes the rewards for a user's delegated stake to a +// validator, factoring in the delegation duration and amount. +func (e *Manual) CalculateUserDelegationRewards(nodeID ids.NodeID, actor codec.Address, currentBlockHeight uint64) (uint64, error) { + e.c.Logger().Info("calculating rewards for user delegation") + + // Find the validator + validator, exists := e.validators[nodeID] + if !exists { + return 0, ErrValidatorNotFound + } + + // Check if the delegator exists + lastClaimHeight, exists := validator.DelegatorsLastClaim[actor] + if !exists { + return 0, ErrDelegatorNotFound + } + + stateDB, err := e.nuklaivm.State() + if err != nil { + return 0, err + } + mu := state.NewSimpleMutable(stateDB) + + // Get user's delegation stake info + exists, _, userStakedAmount, _, _, _ := storage.GetDelegateUserStake(context.TODO(), mu, actor, nodeID) + if !exists { + return 0, ErrStakeNotFound + } + + // Iterate over each epoch since the last claim + startEpoch := lastClaimHeight / e.EpochTracker.EpochLength + endEpoch := currentBlockHeight / e.EpochTracker.EpochLength + totalReward := uint64(0) + + for epoch := startEpoch; epoch < endEpoch; epoch++ { + if reward, ok := validator.epochRewards[epoch]; ok { + // Calculate reward for this epoch + delegatorShare := float64(userStakedAmount) / float64(validator.DelegatedAmount) + epochReward := delegatorShare * float64(reward) + totalReward += uint64(epochReward) + } + } + + return totalReward, nil +} + +// RegisterValidatorStake adds a new validator to the heap with the specified staked amount +// and updates the total staked amount. +func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.PublicKey, stakeStartTime, stakeEndTime, stakedAmount, delegationFeeRate uint64) error { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("registering validator stake") + + // Check if the validator was already registered and is active + validator, exists := e.validators[nodeID] + if exists && validator.IsActive { + return ErrValidatorAlreadyRegistered + } + + if exists { + // If validator exists, it's a re-registration, update necessary fields + validator.PublicKey = bls.PublicKeyToBytes(nodePublicKey) // Update public key if needed + validator.StakedAmount += stakedAmount // Adjust the staked amount + validator.DelegationFeeRate = float64(delegationFeeRate) / 100.0 // Update delegation fee rate if needed + validator.stakeStartTime = time.Unix(int64(stakeStartTime), 0).UTC() + validator.stakeEndTime = time.Unix(int64(stakeEndTime), 0).UTC() + // Note: We might want to keep some attributes unchanged, such as delegatorsLastClaim, epochRewards, etc. + } else { + // If validator does not exist, create a new entry + e.validators[nodeID] = &Validator{ + NodeID: nodeID, + PublicKey: bls.PublicKeyToBytes(nodePublicKey), + StakedAmount: stakedAmount, + DelegationFeeRate: float64(delegationFeeRate) / 100.0, // Convert to decimal + DelegatorsLastClaim: make(map[codec.Address]uint64), + epochRewards: make(map[uint64]uint64), + stakeStartTime: time.Unix(int64(stakeStartTime), 0).UTC(), + stakeEndTime: time.Unix(int64(stakeEndTime), 0).UTC(), + } + } + + return nil +} + +// WithdrawValidatorStake removes a validator from the heap and updates the total +// staked amount accordingly. +func (e *Manual) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("unregistering validator stake") + + // Find the validator + validator, exists := e.validators[nodeID] + if !exists { + return 0, ErrValidatorNotFound + } + + // Validator claiming their rewards and resetting unclaimed rewards + rewardAmount := validator.UnclaimedStakedReward + validator.UnclaimedStakedReward = 0 + + if validator.IsActive { + e.TotalStaked -= validator.StakedAmount + } + + // Mark the validator as inactive + validator.IsActive = false + + // If there are no more delegators, get the rewards and remove the validator + if len(validator.DelegatorsLastClaim) == 0 { + rewardAmount += validator.UnclaimedDelegatedReward + validator.UnclaimedDelegatedReward = 0 + e.TotalStaked -= validator.DelegatedAmount + delete(e.validators, nodeID) + } + + return rewardAmount, nil +} + +// DelegateUserStake increases the delegated stake for a validator and rebalances the heap. +func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Address, stakeAmount uint64) error { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("delegating user stake") + + // Find the validator + validator, exists := e.validators[nodeID] + if !exists { + return ErrValidatorNotFound + } + + // Check if the delegator was already staked + if _, exists := validator.DelegatorsLastClaim[delegatorAddress]; exists { + return ErrDelegatorAlreadyStaked + } + + // Update the validator's stake + validator.DelegatedAmount += stakeAmount + + // We only add to total staked amount if the validator is active + // If validator is inactive, we subtract from the total during distributeFees and mintNewNai functions + // This will prevent us from adding to the total staked amount twice + if validator.IsActive { + e.TotalStaked += stakeAmount + } + + // Update the delegator's stake + validator.DelegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() + + return nil +} + +// UndelegateUserStake decreases the delegated stake for a validator and rebalances the heap. +func (e *Manual) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, stakeAmount uint64) (uint64, error) { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("undelegating user stake") + + // Find the validator + validator, exists := e.validators[nodeID] + if !exists { + return 0, ErrValidatorNotFound + } + + // Check if the delegator exists + if _, exists := validator.DelegatorsLastClaim[actor]; !exists { + return 0, ErrDelegatorNotFound + } + + // Claim rewards while undelegating + currentBlockHeight := e.GetLastAcceptedBlockHeight() + rewardAmount, err := e.CalculateUserDelegationRewards(nodeID, actor, currentBlockHeight) + if err != nil { + return 0, err + } + validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.UnclaimedDelegatedReward -= rewardAmount // Reset unclaimed rewards + + // Update the validator's stake + validator.DelegatedAmount -= stakeAmount + // We only subtract from total staked amount if the validator is active + // If validator is inactive, we subtract from the total during distributeFees and mintNewNai functions + // This will prevent us from adding to the total staked amount twice + if validator.IsActive { + e.TotalStaked -= stakeAmount + } + + // Remove the delegator's entry + delete(validator.DelegatorsLastClaim, actor) + + // If the validator is inactive and has no more delegators, remove the validator + if !validator.IsActive && len(validator.DelegatorsLastClaim) == 0 { + delete(e.validators, nodeID) + } + + return rewardAmount, nil +} + +// ClaimStakingRewards lets validators and delegators claim their rewards +func (e *Manual) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) (uint64, error) { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("claiming staking rewards") + + // Find the validator + validator, exists := e.validators[nodeID] + if !exists { + return 0, ErrValidatorNotFound + } + + rewardAmount := uint64(0) + if actor == codec.EmptyAddress { + // Validator claiming their rewards + rewardAmount = validator.UnclaimedStakedReward + validator.UnclaimedStakedReward = 0 // Reset unclaimed rewards + + // If there are no more delegators, get the rewards + if len(validator.DelegatorsLastClaim) == 0 { + rewardAmount += validator.UnclaimedDelegatedReward + validator.UnclaimedDelegatedReward = 0 + } + } else { + // Delegator claiming their rewards + currentBlockHeight := e.GetLastAcceptedBlockHeight() + reward, err := e.CalculateUserDelegationRewards(nodeID, actor, currentBlockHeight) + if err != nil { + return 0, err + } + validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.UnclaimedDelegatedReward -= reward // Reset unclaimed rewards + rewardAmount = reward + } + + return rewardAmount, nil +} + +func (e *Manual) MintNewNAI() uint64 { + e.lock.Lock() + defer e.lock.Unlock() + + currentBlockHeight := e.GetLastAcceptedBlockHeight() + + // Check if the current block is the end of an epoch + if currentBlockHeight%e.EpochTracker.EpochLength == 0 { + e.c.Logger().Info("minting new NAI tokens at the end of the epoch") + + // Calculate total rewards for the epoch based on APR and staked amount + totalEpochRewards := e.GetRewardsPerEpoch() + + // Calculate rewards per unit staked to minimize iterations + rewardsPerStakeUnit := float64(0) + if e.TotalStaked > 0 { + rewardsPerStakeUnit = float64(totalEpochRewards) / float64(e.TotalStaked) + } + + actualRewards := uint64(0) + + // Distribute rewards based on stake proportion + for _, validator := range e.validators { + lastBlockTime := e.GetLastAcceptedBlockTimestamp() + // Mark validator active based on if stakeStartTime has started + if lastBlockTime.After(validator.stakeStartTime) { + validator.IsActive = true + e.TotalStaked += (validator.StakedAmount + validator.DelegatedAmount) + } + if !validator.IsActive { + continue + } + // Mark validator inactive based on if stakeEndTime has ended + if lastBlockTime.After(validator.stakeEndTime) { + validator.IsActive = false + e.TotalStaked -= (validator.StakedAmount + validator.DelegatedAmount) + continue + } + + validatorStake := validator.StakedAmount + validator.DelegatedAmount + totalValidatorReward := uint64(float64(validatorStake) * rewardsPerStakeUnit) + + // Calculate the rewards for the validator and for delegation + validatorReward, delegationReward := uint64(0), uint64(0) + if len(validator.DelegatorsLastClaim) > 0 { + validatorReward, delegationReward = distributeValidatorRewards(totalValidatorReward, validator.DelegationFeeRate, validator.DelegatedAmount) + } + + actualRewards += validatorReward + delegationReward + + // Update validator's and delegators' rewards + validator.UnclaimedStakedReward += validatorReward + validator.UnclaimedDelegatedReward += delegationReward + + // Track rewards per epoch for delegation + epochNumber := currentBlockHeight / e.EpochTracker.EpochLength + validator.epochRewards[epochNumber] = delegationReward + } + + // Update the total supply with the new minted rewards + e.TotalSupply += actualRewards + + // Return the total rewards distributed in this epoch + return actualRewards + } + + // No rewards are distributed until the end of the epoch + return 0 +} + +// DistributeFees allocates transaction fees between the emission account and validators, +// based on the total staked amount. +func (e *Manual) DistributeFees(fee uint64) { + e.lock.Lock() + defer e.lock.Unlock() + + e.c.Logger().Info("distributing transaction fees") + + if e.TotalSupply+fee > e.MaxSupply { + fee = e.MaxSupply - e.TotalSupply // Adjust to not exceed max supply + } + + // Give 50% fees to Emission Account + feesForEmission := fee / 2 + e.EmissionAccount.UnclaimedBalance += feesForEmission + + // Give remaining to Validators + feesForValidators := fee - feesForEmission + if e.TotalStaked == 0 || feesForValidators == 0 { + return // No validators or no fees to distribute + } + + // Calculate fees per unit staked to minimize iterations + feesPerStakeUnit := float64(feesForValidators) / float64(e.TotalStaked) + + // Distribute fees based on stake proportion + for _, validator := range e.validators { + lastBlockTime := e.GetLastAcceptedBlockTimestamp() + // Mark validator active based on if stakeStartTime has started + if lastBlockTime.After(validator.stakeStartTime) { + validator.IsActive = true + e.TotalStaked += (validator.StakedAmount + validator.DelegatedAmount) + } + if !validator.IsActive { + continue + } + // Mark validator inactive based on if stakeEndTime has ended + if lastBlockTime.After(validator.stakeEndTime) { + validator.IsActive = false + e.TotalStaked -= (validator.StakedAmount + validator.DelegatedAmount) + continue + } + + validatorStake := validator.StakedAmount + validator.DelegatedAmount + totalValidatorFee := uint64(float64(validatorStake) * feesPerStakeUnit) + + validatorFee, delegationFee := uint64(0), uint64(0) + if len(validator.DelegatorsLastClaim) > 0 { + validatorFee, delegationFee = distributeValidatorRewards(totalValidatorFee, validator.DelegationFeeRate, validator.DelegatedAmount) + } + validator.UnclaimedStakedReward += validatorFee + validator.UnclaimedDelegatedReward += delegationFee + } +} + +// func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { +// delegationRewards := uint64(0) +// if delegatedAmount > 0 { +// delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) +// } +// validatorRewards := totalValidatorReward - delegationRewards +// return validatorRewards, delegationRewards +// } + +// GetEmission returns the singleton instance of Emission +// func GetManualEmission() *Manual { +// return manualEmission +// } + +// GetStakedValidator retrieves the details of a specific validator by their NodeID. +func (e *Manual) GetStakedValidator(nodeID ids.NodeID) []*Validator { + e.c.Logger().Info("fetching staked validator") + + if nodeID == ids.EmptyNodeID { + validators := make([]*Validator, 0, len(e.validators)) + for _, validator := range e.validators { + validators = append(validators, validator) + } + return validators + } + + // Find the validator + if validator, exists := e.validators[nodeID]; exists { + return []*Validator{validator} + } + return []*Validator{} +} + +// GetAllValidators fetches the current validators from the underlying VM +func (e *Manual) GetAllValidators(ctx context.Context) []*Validator { + e.c.Logger().Info("fetching all staked and unstaked validators") + + for _, v := range e.CurrentValidators { + stakedValidator := e.GetStakedValidator(v.NodeID) + if len(stakedValidator) > 0 { + v.StakedAmount = stakedValidator[0].StakedAmount + v.UnclaimedStakedReward = stakedValidator[0].UnclaimedStakedReward + v.DelegationFeeRate = stakedValidator[0].DelegationFeeRate + v.DelegatedAmount = stakedValidator[0].DelegatedAmount + v.UnclaimedDelegatedReward = stakedValidator[0].UnclaimedDelegatedReward + v.DelegatorsLastClaim = stakedValidator[0].DelegatorsLastClaim + } + } + return e.CurrentValidators +} + +// GetLastAcceptedBlockTimestamp retrieves the timestamp of the last accepted block from the VM. +func (e *Manual) GetLastAcceptedBlockTimestamp() time.Time { + e.c.Logger().Info("fetching last accepted block timestamp") + return e.nuklaivm.LastAcceptedBlock().Timestamp().UTC() +} + +// GetLastAcceptedBlockHeight retrieves the height of the last accepted block from the VM. +func (e *Manual) GetLastAcceptedBlockHeight() uint64 { + e.c.Logger().Info("fetching last accepted block height") + return e.nuklaivm.LastAcceptedBlock().Height() +} + +func (e *Manual) GetEmissionValidators() map[ids.NodeID]*Validator { + e.c.Logger().Info("fetching emission validators") + return e.validators +} + +func (e *Manual) GetInfo() (emissionAccount EmissionAccount, totalSupply uint64, maxSupply uint64, totalStaked uint64, epochTracker EpochTracker) { + return e.EmissionAccount, e.TotalSupply, e.MaxSupply, e.TotalStaked, e.EpochTracker +} diff --git a/emission/tracker.go b/emission/tracker.go new file mode 100644 index 0000000..78d7612 --- /dev/null +++ b/emission/tracker.go @@ -0,0 +1,39 @@ +package emission + +import ( + "context" + "time" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/bls" +) + +var ( + emission Tracker +) + +type Tracker interface { + GetStakedValidator(nodeID ids.NodeID) []*Validator + GetAllValidators(ctx context.Context) []*Validator + GetLastAcceptedBlockTimestamp() time.Time + GetLastAcceptedBlockHeight() uint64 + GetEmissionValidators() map[ids.NodeID]*Validator + DistributeFees(fee uint64) + MintNewNAI() uint64 + ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) (uint64, error) + UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, stakeAmount uint64) (uint64, error) + DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Address, stakeAmount uint64) error + WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) + RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.PublicKey, stakeStartTime, stakeEndTime, stakedAmount, delegationFeeRate uint64) error + CalculateUserDelegationRewards(nodeID ids.NodeID, actor codec.Address, currentBlockHeight uint64) (uint64, error) + GetRewardsPerEpoch() uint64 + GetAPRForValidators() float64 + GetNumDelegators(nodeID ids.NodeID) int + AddToTotalSupply(amount uint64) uint64 + GetInfo() (emissionAccount EmissionAccount, totalSupply uint64, maxSupply uint64, totalStaked uint64, epochTracker EpochTracker) +} + +func GetEmission() Tracker { + return emission +} diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 4441dbc..6c5f94a 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -136,7 +136,7 @@ var ( // err error nodesFactories []*auth.BLSFactory nodesAddresses []codec.Address - emissions []*emission.Emission + emissions []emission.Tracker nodesPubKeys []*bls.PublicKey ) @@ -193,7 +193,7 @@ var _ = ginkgo.BeforeSuite(func() { instances = make([]instance, vms) nodesFactories = make([]*auth.BLSFactory, vms) nodesAddresses = make([]codec.Address, vms) - emissions = make([]*emission.Emission, vms) + emissions = make([]emission.Tracker, vms) nodesPubKeys = make([]*bls.PublicKey, vms) gen = genesis.Default() @@ -311,6 +311,8 @@ var _ = ginkgo.BeforeSuite(func() { } blocks = []snowman.Block{} + setEmissionValidators() + app.instances = instances color.Blue("created %d VMs", vms) }) @@ -839,3 +841,19 @@ func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { err = blk.Accept(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) } + +func setEmissionValidators() { + currentValidators := make([]*emission.Validator, 0, len(instances)) + for i, inst := range instances { + val := emission.Validator{ + NodeID: inst.nodeID, + PublicKey: bls.PublicKeyToBytes(nodesPubKeys[i]), + } + currentValidators = append(currentValidators, &val) + } + fmt.Println(len(currentValidators)) + for i := range instances { + fmt.Println(emissions[i]) + emissions[i].(*emission.Manual).CurrentValidators = currentValidators + } +} From 6dff2aaec3e28cb7c0ae9571ab58bc03d1d91767 Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 18 Apr 2024 16:07:02 +0100 Subject: [PATCH 22/78] register validator stake and get staked validators tests pass --- tests/integration/new_actions_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 6c5f94a..9e5e3f1 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -466,7 +466,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(5 * time.Second) fmt.Println(len(blocks)) @@ -527,7 +526,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) // ginkgo.By("Get validator staked amount after staking", func() { From 745885162fd7182bccc1dcbff45f9c8cdab47898 Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 18 Apr 2024 19:53:12 +0100 Subject: [PATCH 23/78] height --- tests/integration/new_actions_test.go | 110 ++++++++------------------ 1 file changed, 35 insertions(+), 75 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 9e5e3f1..e009671 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -329,6 +329,7 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Setup and get initial staked validators", func() { + height := 0 currentTime = time.Now().UTC() stakeStartTime = currentTime.Add(2 * time.Second) stakeEndTime = currentTime.Add(15 * time.Minute) @@ -352,9 +353,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(validators)).Should(gomega.Equal(0)) ginkgo.By("Funding node 3", func() { - parser, err := instances[0].ncli.Parser(context.Background()) + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, @@ -371,62 +372,35 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // app.SendAppGossip(context.Background(), tx.Bytes()) - accept := expectBlk(instances[0]) + accept := expectBlk(instances[3]) results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) gomega.Ω(len(blocks)).Should(gomega.Equal(1)) - // blk1, err := instances[3].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - - blk := blocks[0] - ImportBlockToInstance(instances[3].vm, blk) - - // blk1, err = instances[4].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) ImportBlockToInstance(instances[4].vm, blk) - - // blk1, err = instances[2].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - ImportBlockToInstance(instances[2].vm, blk) - - // blk1, err = instances[1].vm.ParseBlock(context.Background(), blocks[0].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk1.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - ImportBlockToInstance(instances[1].vm, blk) + height++ balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) // check if gossip/ new state happens balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) fmt.Printf("balance factory %s %d\n", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) }) ginkgo.By("Register validator stake node 3", func() { @@ -469,40 +443,29 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(len(blocks)) + fmt.Println(blocks) + accept := expectBlk(instances[3]) results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // gomega.Ω(len(blocks)).Should(gomega.Equal(2)) - - // blk2, err := instances[0].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // blk2, err = instances[1].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // blk2, err = instances[2].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - - // blk2, err = instances[4].vm.ParseBlock(context.Background(), blocks[1].Bytes()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Verify(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // err = blk2.Accept(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + for _, b := range blocks { + fmt.Println(b.ID()) + fmt.Println(b.Parent()) + } + + fmt.Println(blocks) + + blk := blocks[1] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -515,7 +478,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { emissionInstance := emissions[3] currentValidators := emissionInstance.GetAllValidators(context.TODO()) - fmt.Println(currentValidators) + gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) @@ -529,17 +492,14 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) - // ginkgo.By("Get validator staked amount after staking", func() { - // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - // _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - // }) + ginkgo.By("Get validator staked amount after staking using instances[0] cli", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) // ginkgo.By("Get staked validators", func() { - // validators, err := instances[0].ncli.StakedValidators(context.Background()) + // validators, err := instances[3].ncli.StakedValidators(context.Background()) // gomega.Ω(err).Should(gomega.BeNil()) // gomega.Ω(len(validators)).Should(gomega.Equal(2)) // }) From 0a48b16b933c35233de44813da77502eac8fee41 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 19 Apr 2024 13:35:50 +0100 Subject: [PATCH 24/78] delegate user stake --- tests/integration/new_actions_test.go | 136 ++++++++++++++++++-------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index e009671..2a0a065 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -129,15 +129,15 @@ var ( delegationFeeRate int withdraw0 string withdraw1 string + delegate string rwithdraw0 codec.Address rwithdraw1 codec.Address rdelegate codec.Address - // parser0 chain.Parser - // err error - nodesFactories []*auth.BLSFactory - nodesAddresses []codec.Address - emissions []emission.Tracker - nodesPubKeys []*bls.PublicKey + delegateFactory *auth.ED25519Factory + nodesFactories []*auth.BLSFactory + nodesAddresses []codec.Address + emissions []emission.Tracker + nodesPubKeys []*bls.PublicKey ) type instance struct { @@ -348,9 +348,14 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) + delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) + delegateFactory = auth.NewED25519Factory(delegatePriv) + + ginkgo.By("Initial staked validators", func() { + validators, err := instances[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) ginkgo.By("Funding node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) @@ -492,50 +497,95 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) - ginkgo.By("Get validator staked amount after staking using instances[0] cli", func() { + ginkgo.By("Get validator staked amount after staking using node 0 cli", func() { _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) // ginkgo.By("Get staked validators", func() { - // validators, err := instances[3].ncli.StakedValidators(context.Background()) + // fmt.Println("GET EMISSION 3 VALIDATORS") + // fmt.Println(emissions[0].GetEmissionValidators()) + // fmt.Println(emissions[1].GetEmissionValidators()) + // fmt.Println(emissions[2].GetEmissionValidators()) + // fmt.Println(emissions[3].GetEmissionValidators()) + // fmt.Println(emissions[4].GetEmissionValidators()) + // validators, err := instances[3].ncli.StakedValidators(context.TODO()) // gomega.Ω(err).Should(gomega.BeNil()) // gomega.Ω(len(validators)).Should(gomega.Equal(2)) // }) - // ginkgo.By("Transfer NAI to user and delegate stake to node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.Transfer{ - // To: rdelegate, - // Asset: ids.Empty, - // Value: 100, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // currentTime := time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err = instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.DelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // StakeStartTime: uint64(userStakeStartTime.Unix()), - // StakedAmount: 50, - // RewardAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) + ginkgo.By("Transfer NAI to delegate user", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + }) + + ginkgo.By("delegate stake to node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + userStakeStartTime := currentTime.Add(5 * time.Second) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(userStakeStartTime.Unix()), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + }) // ginkgo.By("Delegate stake to node 1", func() { // currentTime = time.Now().UTC() From ad9f85c8fc682b7dc2d67d36b982df90436d11e5 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 22 Apr 2024 13:31:12 +0100 Subject: [PATCH 25/78] user delegate claim --- tests/integration/new_actions_test.go | 166 +++++++++++++++----------- 1 file changed, 96 insertions(+), 70 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 2a0a065..b2a36b7 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -406,6 +406,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("balance factory %s %d\n", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) + + fmt.Println("LAST ACCEPTED BLOCK") + fmt.Println(instances[3].vm.LastAccepted(context.Background())) + fmt.Println(instances[4].vm.LastAccepted(context.Background())) }) ginkgo.By("Register validator stake node 3", func() { @@ -446,10 +450,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - fmt.Println(len(blocks)) - - fmt.Println(blocks) - accept := expectBlk(instances[3]) results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) @@ -457,14 +457,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - for _, b := range blocks { - fmt.Println(b.ID()) - fmt.Println(b.Parent()) - } - - fmt.Println(blocks) - - blk := blocks[1] + blk := blocks[height] fmt.Println(blk.ID()) ImportBlockToInstance(instances[4].vm, blk) ImportBlockToInstance(instances[0].vm, blk) @@ -488,6 +481,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + fmt.Println("LAST ACCEPTED BLOCK") + fmt.Println(instances[3].vm.LastAccepted(context.Background())) + fmt.Println(instances[4].vm.LastAccepted(context.Background())) + }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { @@ -510,7 +507,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // fmt.Println(emissions[2].GetEmissionValidators()) // fmt.Println(emissions[3].GetEmissionValidators()) // fmt.Println(emissions[4].GetEmissionValidators()) - // validators, err := instances[3].ncli.StakedValidators(context.TODO()) + // validators, err := instances[3].ncli.StakedValidators(context.Background()) // gomega.Ω(err).Should(gomega.BeNil()) // gomega.Ω(len(validators)).Should(gomega.Equal(2)) // }) @@ -549,13 +546,17 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + + fmt.Println("LAST ACCEPTED BLOCK") + fmt.Println(instances[3].vm.LastAccepted(context.Background())) + fmt.Println(instances[4].vm.LastAccepted(context.Background())) }) ginkgo.By("delegate stake to node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(5 * time.Second) + userStakeStartTime := currentTime.Add(1 * time.Second) submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, @@ -578,6 +579,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + fmt.Printf("delegate stake to node 3 %d", height) + blk := blocks[height] ImportBlockToInstance(instances[0].vm, blk) ImportBlockToInstance(instances[4].vm, blk) @@ -585,68 +588,91 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ImportBlockToInstance(instances[1].vm, blk) height++ + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + + fmt.Println("LAST ACCEPTED BLOCK DELEGATE STAKE") + fmt.Println(instances[3].vm.LastAccepted(context.Background())) + fmt.Println(instances[4].vm.LastAccepted(context.Background())) + }) - // ginkgo.By("Delegate stake to node 1", func() { - // currentTime = time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.DelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // StakeStartTime: uint64(userStakeStartTime.Unix()), - // StakedAmount: 50, - // RewardAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) + ginkgo.By("Get user stake before claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + }) - // ginkgo.By("Get user stake before claim", func() { - // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) - // }) + ginkgo.By("Claim delegation stake rewards from node 3", func() { + time.Sleep(1 * time.Second) + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // ginkgo.By("Claim delegation stake rewards from node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.ClaimDelegationStakeRewards{ - // NodeID: instances[0].nodeID.Bytes(), - // UserStakeAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // ginkgo.By("Get user stake after claim", func() { - // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) - // }) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - // ginkgo.By("Undelegate user stake from node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.UndelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) + + ginkgo.By("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) + + ginkgo.By("Undelegate user stake from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) // add more ginko.By where error should be thrown with wrong data input // ginkgo.By("Claim validator node 0 stake reward", func() { From 2630622c73c505a3ec9bffcea17c242e57664b79 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 22 Apr 2024 16:19:21 +0100 Subject: [PATCH 26/78] test same block is accepted --- tests/integration/new_actions_test.go | 40 +++++++++++++++++++++------ 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index b2a36b7..78937d0 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -481,6 +481,13 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + // test the state is changed + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + fmt.Println("LAST ACCEPTED BLOCK") fmt.Println(instances[3].vm.LastAccepted(context.Background())) fmt.Println(instances[4].vm.LastAccepted(context.Background())) @@ -547,12 +554,15 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - fmt.Println("LAST ACCEPTED BLOCK") - fmt.Println(instances[3].vm.LastAccepted(context.Background())) - fmt.Println(instances[4].vm.LastAccepted(context.Background())) + // test the state is changed + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - ginkgo.By("delegate stake to node 3", func() { + ginkgo.By("delegate user stake to node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) currentTime := time.Now().UTC() @@ -574,6 +584,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { accept := expectBlk(instances[3]) results := accept(true) + fmt.Println("-----------delegate user stake to node 3") + fmt.Println(results[0].Success) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) @@ -582,24 +594,27 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("delegate stake to node 3 %d", height) blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) ImportBlockToInstance(instances[4].vm, blk) ImportBlockToInstance(instances[2].vm, blk) ImportBlockToInstance(instances[1].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) height++ _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - fmt.Println("LAST ACCEPTED BLOCK DELEGATE STAKE") - fmt.Println(instances[3].vm.LastAccepted(context.Background())) - fmt.Println(instances[4].vm.LastAccepted(context.Background())) + // test the state is changed + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) ginkgo.By("Get user stake before claim", func() { - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + _, stakedAmount, _, _, err := instances[4].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) }) @@ -635,6 +650,13 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ImportBlockToInstance(instances[2].vm, blk) ImportBlockToInstance(instances[1].vm, blk) height++ + + // test the state is changed + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) ginkgo.By("Get user stake after claim", func() { From 8a8b8c944df7374fd9ede93413a7682a46046043 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 22 Apr 2024 16:30:05 +0100 Subject: [PATCH 27/78] clean up --- emission/emission.go | 50 ------------------------ emission/helpers.go | 3 +- emission/manual.go | 55 --------------------------- emission/tracker.go | 5 +-- tests/integration/new_actions_test.go | 12 ++---- 5 files changed, 7 insertions(+), 118 deletions(-) diff --git a/emission/emission.go b/emission/emission.go index 7d919e4..3ec2921 100644 --- a/emission/emission.go +++ b/emission/emission.go @@ -17,37 +17,6 @@ import ( var _ Tracker = (*Emission)(nil) -// var ( -// emission *Emission -// ) - -// type Validator struct { -// IsActive bool `json:"isActive"` // Indicates if the validator is currently active -// NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator -// PublicKey []byte `json:"publicKey"` // Public key of the validator -// StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator -// UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator -// DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations -// DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator -// UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators - -// DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height -// epochRewards map[uint64]uint64 // Rewards per epoch -// stakeStartTime time.Time // Start time of the stake -// stakeEndTime time.Time // End time of the stake -// } - -// type EmissionAccount struct { -// Address codec.Address `json:"address"` -// UnclaimedBalance uint64 `json:"unclaimedBalance"` -// } - -// type EpochTracker struct { -// BaseAPR float64 `json:"baseAPR"` // Base APR to use -// BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use -// EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch -// } - type Emission struct { c Controller nuklaivm NuklaiVM @@ -95,11 +64,6 @@ func NewEmission(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emiss return emission.(*Emission) } -// // GetEmission returns the singleton instance of Emission -// func GetEmission() *Emission { -// return emission -// } - // AddToTotalSupply increases the total supply of NAI by a specified amount, ensuring it // does not exceed the max supply. func (e *Emission) AddToTotalSupply(amount uint64) uint64 { @@ -528,20 +492,6 @@ func (e *Emission) DistributeFees(fee uint64) { } } -// func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { -// delegationRewards := uint64(0) -// if delegatedAmount > 0 { -// delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) -// } -// validatorRewards := totalValidatorReward - delegationRewards -// return validatorRewards, delegationRewards -// } - -// GetEmission returns the singleton instance of Emission -// func GetEmission() *Emission { -// return emission -// } - // GetStakedValidator retrieves the details of a specific validator by their NodeID. func (e *Emission) GetStakedValidator(nodeID ids.NodeID) []*Validator { e.c.Logger().Info("fetching staked validator") diff --git a/emission/helpers.go b/emission/helpers.go index 3844c1f..1968d15 100644 --- a/emission/helpers.go +++ b/emission/helpers.go @@ -9,7 +9,8 @@ import ( ) var ( - once sync.Once + once sync.Once + emission Tracker ) type Validator struct { diff --git a/emission/manual.go b/emission/manual.go index 1b4865e..a1ed228 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -17,42 +17,6 @@ import ( var _ Tracker = (*Manual)(nil) -// var ( -// manualEmission *Manual -// ) - -// var ( -// emission *Emission -// once sync.Once -// ) - -// type Validator struct { -// IsActive bool `json:"isActive"` // Indicates if the validator is currently active -// NodeID ids.NodeID `json:"nodeID"` // Node ID of the validator -// PublicKey []byte `json:"publicKey"` // Public key of the validator -// StakedAmount uint64 `json:"stakedAmount"` // Total amount staked by the validator -// UnclaimedStakedReward uint64 `json:"stakedReward"` // Total rewards accumulated by the validator -// DelegationFeeRate float64 `json:"delegationFeeRate"` // Fee rate for delegations -// DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator -// UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators - -// DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height -// epochRewards map[uint64]uint64 // Rewards per epoch -// stakeStartTime time.Time // Start time of the stake -// stakeEndTime time.Time // End time of the stake -// } - -// type EmissionAccount struct { -// Address codec.Address `json:"address"` -// UnclaimedBalance uint64 `json:"unclaimedBalance"` -// } - -// type EpochTracker struct { -// BaseAPR float64 `json:"baseAPR"` // Base APR to use -// BaseValidators uint64 `json:"baseValidators"` // Base number of validators to use -// EpochLength uint64 `json:"epochLength"` // Number of blocks per reward epoch -// } - type Manual struct { c Controller nuklaivm NuklaiVM @@ -101,11 +65,6 @@ func NewManual(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissio return emission.(*Manual) } -// // GetEmission returns the singleton instance of Emission -// func GetEmission() *Emission { -// return emission -// } - // AddToTotalSupply increases the total supply of NAI by a specified amount, ensuring it // does not exceed the max supply. func (e *Manual) AddToTotalSupply(amount uint64) uint64 { @@ -534,20 +493,6 @@ func (e *Manual) DistributeFees(fee uint64) { } } -// func distributeValidatorRewards(totalValidatorReward uint64, delegationFeeRate float64, delegatedAmount uint64) (uint64, uint64) { -// delegationRewards := uint64(0) -// if delegatedAmount > 0 { -// delegationRewards = uint64(float64(totalValidatorReward) * delegationFeeRate) -// } -// validatorRewards := totalValidatorReward - delegationRewards -// return validatorRewards, delegationRewards -// } - -// GetEmission returns the singleton instance of Emission -// func GetManualEmission() *Manual { -// return manualEmission -// } - // GetStakedValidator retrieves the details of a specific validator by their NodeID. func (e *Manual) GetStakedValidator(nodeID ids.NodeID) []*Validator { e.c.Logger().Info("fetching staked validator") diff --git a/emission/tracker.go b/emission/tracker.go index 78d7612..dba96dd 100644 --- a/emission/tracker.go +++ b/emission/tracker.go @@ -9,10 +9,6 @@ import ( "github.com/ava-labs/hypersdk/crypto/bls" ) -var ( - emission Tracker -) - type Tracker interface { GetStakedValidator(nodeID ids.NodeID) []*Validator GetAllValidators(ctx context.Context) []*Validator @@ -34,6 +30,7 @@ type Tracker interface { GetInfo() (emissionAccount EmissionAccount, totalSupply uint64, maxSupply uint64, totalStaked uint64, epochTracker EpochTracker) } +// GetEmission returns the singleton instance of Emission func GetEmission() Tracker { return emission } diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 78937d0..24e208d 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -481,17 +481,13 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - // test the state is changed + // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - fmt.Println("LAST ACCEPTED BLOCK") - fmt.Println(instances[3].vm.LastAccepted(context.Background())) - fmt.Println(instances[4].vm.LastAccepted(context.Background())) - }) ginkgo.By("Get validator staked amount after node 3 validator staking", func() { @@ -554,7 +550,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - // test the state is changed + // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) @@ -604,7 +600,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - // test the state is changed + // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) @@ -651,7 +647,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ImportBlockToInstance(instances[1].vm, blk) height++ - // test the state is changed + // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) From 1184790ca99ea74b2aec53528d412ec7f4573d54 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 22 Apr 2024 17:46:13 +0100 Subject: [PATCH 28/78] set initial code int tests --- tests/integration/integration_test.go | 425 +------------------------- 1 file changed, 4 insertions(+), 421 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 3493303..963bc8e 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -39,7 +39,6 @@ import ( "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/pubsub" hrpc "github.com/ava-labs/hypersdk/rpc" - "github.com/ava-labs/hypersdk/state" hutils "github.com/ava-labs/hypersdk/utils" "github.com/ava-labs/hypersdk/vm" @@ -47,10 +46,8 @@ import ( "github.com/nuklai/nuklaivm/auth" nconsts "github.com/nuklai/nuklaivm/consts" "github.com/nuklai/nuklaivm/controller" - "github.com/nuklai/nuklaivm/emission" "github.com/nuklai/nuklaivm/genesis" nrpc "github.com/nuklai/nuklaivm/rpc" - "github.com/nuklai/nuklaivm/storage" ) var ( @@ -89,7 +86,7 @@ func init() { flag.IntVar( &vms, "vms", - 5, + 3, "number of VMs to create", ) } @@ -125,23 +122,6 @@ var ( networkID uint32 gen *genesis.Genesis - - //to be reordered staking vars - currentTime time.Time - stakeStartTime time.Time - stakeEndTime time.Time - delegationFeeRate int - withdraw0 string - withdraw1 string - rwithdraw0 codec.Address - rwithdraw1 codec.Address - rdelegate codec.Address - // parser0 chain.Parser - // err error - nodesFactories []*auth.BLSFactory - nodesAddresses []codec.Address - emissions []*emission.Emission - nodesPubKeys []*bls.PublicKey ) type instance struct { @@ -195,10 +175,6 @@ var _ = ginkgo.BeforeSuite(func() { // create embedded VMs instances = make([]instance, vms) - nodesFactories = make([]*auth.BLSFactory, vms) - nodesAddresses = make([]codec.Address, vms) - emissions = make([]*emission.Emission, vms) - nodesPubKeys = make([]*bls.PublicKey, vms) gen = genesis.Default() gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} @@ -206,7 +182,7 @@ var _ = ginkgo.BeforeSuite(func() { gen.CustomAllocation = []*genesis.CustomAllocation{ { Address: sender, - Balance: 10_000_000_000_000_000, + Balance: 10_000_000, }, } gen.EmissionBalancer = genesis.EmissionBalancer{ @@ -242,9 +218,6 @@ var _ = ginkgo.BeforeSuite(func() { WarpSigner: warp.NewSigner(sk, networkID, chainID), ValidatorState: &validators.TestState{}, } - nodesFactories[i] = auth.NewBLSFactory(sk) - nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) - nodesPubKeys[i] = snowCtx.PublicKey toEngine := make(chan common.Message, 1) db := memdb.New() @@ -264,12 +237,11 @@ var _ = ginkgo.BeforeSuite(func() { app, ) gomega.Ω(err).Should(gomega.BeNil()) + var hd map[string]http.Handler hd, err = v.CreateHandlers(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) - emissions[i] = emission.GetEmission() - hjsonRPCServer := httptest.NewServer(hd[hrpc.JSONRPCEndpoint]) njsonRPCServer := httptest.NewServer(hd[nrpc.JSONRPCEndpoint]) webSocketServer := httptest.NewServer(hd[hrpc.WebSocketEndpoint]) @@ -482,8 +454,7 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { ginkgo.By("ensure balance is updated", func() { balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance).To(gomega.Equal(uint64(9999999999899703))) - + gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) gomega.Ω(err).To(gomega.BeNil()) gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) @@ -980,7 +951,6 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { }) ginkgo.It("mint a new asset", func() { - fmt.Println("MINT ASSET") parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err := instances[0].hcli.GenerateTransaction( @@ -1579,393 +1549,6 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { }) }) -var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.FIt("Setup and get initial staked validators", func() { - currentTime = time.Now().UTC() - stakeStartTime = currentTime.Add(2 * time.Minute) - stakeEndTime = currentTime.Add(15 * time.Minute) - delegationFeeRate = 50 - - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) - withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - - withdraw1Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) - withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) - - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - - ginkgo.By("Funding node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: nodesAddresses[3], - Asset: ids.Empty, - Value: 200_000_000_000, - }, - factory, - ) - fmt.Println(err) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - gomega.Ω(instances[3].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - - gomega.Ω(instances[3].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - <-instances[3].toEngine - - blk, err := instances[3].vm.BuildBlock(context.TODO()) - gomega.Ω(err).To(gomega.BeNil()) - - gomega.Ω(blk.Verify(context.TODO())).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = instances[3].vm.SetPreference(context.TODO(), blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - fmt.Println(len(blocks)) - gomega.Ω(blk.Accept(context.TODO())).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - blocks = append(blocks, blk) - fmt.Println(len(blocks)) - - lastAccepted, err := instances[3].vm.LastAccepted(context.TODO()) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - results := blk.(*chain.StatelessBlock).Results() - fmt.Println(results[0].Output) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(results[0].Output).Should(gomega.BeNil()) - - time.Sleep(5 * time.Second) - - // lastAccepted, err = instances[4].vm.LastAccepted(context.TODO()) - // gomega.Ω(err).To(gomega.BeNil()) - // gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - - // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) - - balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) - fmt.Printf("balance factory %s %d\n", sender, balance) - gomega.Ω(err).Should(gomega.BeNil()) - - }) - - ginkgo.By("Register validator stake node 3", func() { - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100_000_000_000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - - emissionInstance := emissions[3] - stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - gomega.Ω(len(stakedValidator)).To(gomega.Equal(0)) - err = emissionInstance.RegisterValidatorStake(instances[3].nodeID, nodesPubKeys[3], stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate) - _, exists := emissionInstance.GetEmissionValidators()[instances[3].nodeID] - gomega.Ω(exists).To(gomega.Equal(true)) - stakedValidator = emissionInstance.GetStakedValidator(instances[3].nodeID) - gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - validator := stakedValidator[0] - gomega.Ω(validator.IsActive).To(gomega.Equal(true)) - gomega.Ω(validator.StakedAmount).To(gomega.Equal(100_000_000_000)) - err := storage.SubBalance(context.Background(), &state.MockMutable{}, nodesAddresses[3], ids.Empty, stakeInfo.StakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - err = storage.SetRegisterValidatorStake(context.Background(), &state.MockMutable{}, instances[3].nodeID, stakeInfo.StakeStartTime, stakeInfo.StakeEndTime, stakeInfo.StakedAmount, stakeInfo.DelegationFeeRate, stakeInfo.RewardAddress, nodesAddresses[3]) - gomega.Ω(err).Should(gomega.BeNil()) - }) - - // OLD ONES - - // ginkgo.By("Register validator stake node 3", func() { - // parser, err := instances[3].ncli.Parser(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // stakeInfo := &actions.ValidatorStakeInfo{ - // NodeID: instances[3].nodeID.Bytes(), - // StakeStartTime: uint64(stakeStartTime.Unix()), - // StakeEndTime: uint64(stakeEndTime.Unix()), - // StakedAmount: 100_000_000_000, - // DelegationFeeRate: uint64(delegationFeeRate), - // RewardAddress: rwithdraw0, - // } - - // stakeInfoBytes, err := stakeInfo.Marshal() - // gomega.Ω(err).Should(gomega.BeNil()) - // signature, err := nodesFactories[3].Sign(stakeInfoBytes) - // gomega.Ω(err).Should(gomega.BeNil()) - // signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - // signature.Marshal(signaturePacker) - // authSignature := signaturePacker.Bytes() - // submit, _, _, err := instances[3].hcli.GenerateTransaction( - // context.Background(), - // parser, - // nil, - // &actions.RegisterValidatorStake{ - // StakeInfo: stakeInfoBytes, - // AuthSignature: authSignature, - // }, - // nodesFactories[3], - // ) - // fmt.Println(err) - // gomega.Ω(err).Should(gomega.BeNil()) - - // balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // time.Sleep(5 * time.Second) - - // balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - - // // check if gossip/ new state happens - // balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - // gomega.Ω(err).Should(gomega.BeNil()) - // fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) - - // emissionInstance := emissions[3] - // currentValidators := emissionInstance.GetAllValidators(context.TODO()) - // fmt.Println(currentValidators) - // stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - // fmt.Println(stakedValidator) - // gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - - // }) - - ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(100_000_000_000)) - }) - - // ginkgo.By("Get validator staked amount after staking", func() { - // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - // _, _, stakedAmount, _, _, _, err = instances[1].ncli.ValidatorStake(context.Background(), instances[1].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(100)) - // }) - - // ginkgo.By("Get staked validators", func() { - // validators, err := instances[0].ncli.StakedValidators(context.Background()) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(len(validators)).Should(gomega.Equal(2)) - // }) - - // ginkgo.By("Transfer NAI to user and delegate stake to node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.Transfer{ - // To: rdelegate, - // Asset: ids.Empty, - // Value: 100, - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // currentTime := time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err = instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.DelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // StakeStartTime: uint64(userStakeStartTime.Unix()), - // StakedAmount: 50, - // RewardAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Delegate stake to node 1", func() { - // currentTime = time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - // gomega.Ω(err).Should(gomega.BeNil()) - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.DelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // StakeStartTime: uint64(userStakeStartTime.Unix()), - // StakedAmount: 50, - // RewardAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Get user stake before claim", func() { - // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 50)) - // }) - - // ginkgo.By("Claim delegation stake rewards from node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.ClaimDelegationStakeRewards{ - // NodeID: instances[0].nodeID.Bytes(), - // UserStakeAddress: rdelegate, - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Get user stake after claim", func() { - // _, stakedAmount, _, _, err := instances[0].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.BeNumerically("==", 0)) - // }) - - // ginkgo.By("Undelegate user stake from node 0", func() { - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.UndelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // add more ginko.By where error should be thrown with wrong data input - // ginkgo.By("Claim validator node 0 stake reward", func() { - // // ClaimValidatorStakeRewards - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.ClaimValidatorStakeRewards{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Withdraw validator node 0 stake", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Get validator stake after staking withdraw ", func() { - // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - // }) - - // ginkgo.By("Withdraw validator node 1 stake with wrong key", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[1].nodeID.Bytes(), - // }, - // factory2, - // ) - // gomega.Ω(err).ShouldNot(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) - // }) - - // staking withdraw then user delegate withdraw on node 1 - // ginkgo.By("Withdraw validator node 1 stake", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[1].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Undelegate user stake from node 1", func() { - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.UndelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - }) - -}) - func expectBlk(i instance) func(bool) []*chain.Result { ctx := context.TODO() From 9d90a255a68859a17bd833cea7612952fe08d79a Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 23 Apr 2024 15:44:54 +0100 Subject: [PATCH 29/78] update --- actions/claim_delegation_stake_rewards.go | 7 ++++ actions/delegate_user_stake.go | 17 +++++++- actions/register_validator_stake.go | 17 ++++++-- controller/controller.go | 9 +++++ controller/resolutions.go | 3 ++ emission/manual.go | 14 +++++-- tests/integration/new_actions_test.go | 48 +++++++++++------------ 7 files changed, 82 insertions(+), 33 deletions(-) diff --git a/actions/claim_delegation_stake_rewards.go b/actions/claim_delegation_stake_rewards.go index d9e4653..ef93049 100644 --- a/actions/claim_delegation_stake_rewards.go +++ b/actions/claim_delegation_stake_rewards.go @@ -5,6 +5,7 @@ package actions import ( "context" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -80,6 +81,12 @@ func (c *ClaimDelegationStakeRewards) Execute( // Convert Unix timestamps to Go's time.Time for easier manipulation startTime := time.Unix(int64(stakeStartTime), 0).UTC() // Check that currentTime and lastBlockTime are after stakeStartTime + fmt.Println("CLAIM DELEGATION STAKE REWARDS") + fmt.Println(currentTime.Before(startTime)) + fmt.Println(lastBlockTime.Before(startTime)) + fmt.Println(currentTime) + fmt.Println(startTime) + fmt.Println(lastBlockTime) if currentTime.Before(startTime) || lastBlockTime.Before(startTime) { return false, ClaimStakingRewardComputeUnits, OutputStakeNotStarted, nil, nil } diff --git a/actions/delegate_user_stake.go b/actions/delegate_user_stake.go index 951e0e4..acb6838 100644 --- a/actions/delegate_user_stake.go +++ b/actions/delegate_user_stake.go @@ -5,6 +5,7 @@ package actions import ( "context" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -60,6 +61,7 @@ func (s *DelegateUserStake) Execute( _ ids.ID, _ bool, ) (bool, uint64, []byte, *warp.UnsignedMessage, error) { + fmt.Println("DELEGATE USER STAKE") nodeID, err := ids.ToNodeID(s.NodeID) if err != nil { return false, DelegateUserStakeComputeUnits, OutputInvalidNodeID, nil, nil @@ -87,27 +89,38 @@ func (s *DelegateUserStake) Execute( // Get current time currentTime := time.Now().UTC() + fmt.Println("CURRRENT TIME") + fmt.Println(currentTime) // Get last accepted block time lastBlockTime := emissionInstance.GetLastAcceptedBlockTimestamp() // Convert Unix timestamps to Go's time.Time for easier manipulation startTime := time.Unix(int64(s.StakeStartTime), 0).UTC() // Check that stakeStartTime is after currentTime and lastBlockTime + fmt.Println(startTime.Before(currentTime)) + fmt.Println(startTime.Before(lastBlockTime)) if startTime.Before(currentTime) || startTime.Before(lastBlockTime) { return false, DelegateUserStakeComputeUnits, OutputInvalidStakeStartTime, nil, nil } - + fmt.Println("POST TIME CHECK-1") // Delegate in Emission Balancer err = emissionInstance.DelegateUserStake(nodeID, actor, s.StakedAmount) if err != nil { return false, DelegateUserStakeComputeUnits, utils.ErrBytes(err), nil, nil } - + fmt.Println("POST TIME CHECK-2") if err := storage.SubBalance(ctx, mu, actor, ids.Empty, s.StakedAmount); err != nil { return false, DelegateUserStakeComputeUnits, utils.ErrBytes(err), nil, nil } if err := storage.SetDelegateUserStake(ctx, mu, actor, nodeID, s.StakeStartTime, s.StakedAmount, s.RewardAddress); err != nil { return false, DelegateUserStakeComputeUnits, utils.ErrBytes(err), nil, nil } + fmt.Println("POST TIME CHECK-3") + exists, _, stakedAmount, _, _, err := storage.GetDelegateUserStake(context.TODO(), mu, actor, nodeID) + fmt.Println("GETDELEGATEUSERSTAKE AFTER SETDELEGATEUSERSTAKE") + fmt.Println(err) + fmt.Println(exists) + fmt.Println(stakedAmount) + return true, DelegateUserStakeComputeUnits, nil, nil, nil } diff --git a/actions/register_validator_stake.go b/actions/register_validator_stake.go index bac66ed..773501a 100644 --- a/actions/register_validator_stake.go +++ b/actions/register_validator_stake.go @@ -5,6 +5,7 @@ package actions import ( "context" + "fmt" "time" "github.com/ava-labs/avalanchego/ids" @@ -61,6 +62,9 @@ func (r *RegisterValidatorStake) Execute( _ bool, ) (bool, uint64, []byte, *warp.UnsignedMessage, error) { // Check if it's a valid signature + fmt.Println("REGISTER VALIDATOR STAKE -1 ") + fmt.Println("ACTOR %s", codec.MustAddressBech32(nconsts.HRP, actor)) + // panic("BREAK REGISTER VALIDATOR STAKE") signer, err := VerifyAuthSignature(r.StakeInfo, r.AuthSignature) if err != nil { return false, RegisterValidatorStakeComputeUnits, utils.ErrBytes(err), nil, nil @@ -70,12 +74,15 @@ func (r *RegisterValidatorStake) Execute( if actorAddress != codec.MustAddressBech32(nconsts.HRP, signer) { return false, RegisterValidatorStakeComputeUnits, OutputDifferentSignerThanActor, nil, nil } - // Check if the tx actor has signing permission for this NodeID isValidatorOwner := false // Get the emission instance emissionInstance := emission.GetEmission() + fmt.Println("GET EMISSION") + fmt.Println(&emissionInstance) + fmt.Println(emissionInstance.GetEmissionValidators()) + currentValidators := emissionInstance.GetAllValidators(ctx) var nodePublicKey *bls.PublicKey for _, validator := range currentValidators { @@ -90,10 +97,11 @@ func (r *RegisterValidatorStake) Execute( break } } + fmt.Println("REGISTER VALIDATOR STAKE -3") if !isValidatorOwner { return false, RegisterValidatorStakeComputeUnits, OutputUnauthorized, nil, nil } - + fmt.Println("REGISTER VALIDATOR STAKE -4") // Unmarshal the stake info stakeInfo, err := UnmarshalValidatorStakeInfo(r.StakeInfo) if err != nil { @@ -104,7 +112,7 @@ func (r *RegisterValidatorStake) Execute( if err != nil { return false, RegisterValidatorStakeComputeUnits, OutputInvalidNodeID, nil, nil } - + fmt.Println("REGISTER VALIDATOR STAKE -5") // Check if the validator was already registered exists, _, _, _, _, _, _, _ := storage.GetRegisterValidatorStake(ctx, mu, nodeID) if exists { @@ -127,12 +135,13 @@ func (r *RegisterValidatorStake) Execute( if startTime.Before(currentTime) || startTime.Before(lastBlockTime) { return false, RegisterValidatorStakeComputeUnits, OutputInvalidStakeStartTime, nil, nil } + fmt.Println("REGISTER VALIDATOR STAKE -6") endTime := time.Unix(int64(stakeInfo.StakeEndTime), 0).UTC() // Check that stakeEndTime is after stakeStartTime if endTime.Before(startTime) { return false, RegisterValidatorStakeComputeUnits, OutputInvalidStakeEndTime, nil, nil } - + fmt.Println("REGISTER VALIDATOR STAKE -7") // Check that the total staking period is at least the minimum staking period stakeDuration := endTime.Sub(startTime) if stakeDuration < stakingConfig.MinValidatorStakeDuration || stakeDuration > stakingConfig.MaxValidatorStakeDuration { diff --git a/controller/controller.go b/controller/controller.go index 78696d1..b1b1714 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -191,6 +191,9 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er return err } } + fmt.Println("Controller Accepted") + fmt.Println(result.Success) + fmt.Println(tx.Action.GetTypeID()) totalFee += result.Fee if result.Success { switch action := tx.Action.(type) { @@ -216,6 +219,8 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er c.metrics.registerValidatorStake.Inc() case *actions.ClaimValidatorStakeRewards: rewardResult, err := actions.UnmarshalClaimRewardsResult(result.Output) + fmt.Println("reward result") + fmt.Println(rewardResult) if err != nil { // This should never happen return err @@ -231,10 +236,14 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er c.metrics.stakeAmount.Add(float64(stakeResult.StakedAmount)) c.metrics.withdrawValidatorStake.Inc() case *actions.DelegateUserStake: + fmt.Println("Controller accepted delegate user stake") + // panic("hello") c.metrics.stakeAmount.Add(float64(action.StakedAmount)) c.metrics.delegateUserStake.Inc() case *actions.ClaimDelegationStakeRewards: rewardResult, err := actions.UnmarshalClaimRewardsResult(result.Output) + fmt.Println("reward result") + fmt.Println(rewardResult) if err != nil { // This should never happen return err diff --git a/controller/resolutions.go b/controller/resolutions.go index 5e682e8..db3d88f 100644 --- a/controller/resolutions.go +++ b/controller/resolutions.go @@ -5,6 +5,7 @@ package controller import ( "context" + "fmt" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/trace" @@ -97,5 +98,7 @@ func (c *Controller) GetDelegatedUserStakeFromState(ctx context.Context, owner c codec.Address, // OwnerAddress error, ) { + fmt.Println("GetDelegatedUserStakeFromState") + fmt.Println(c.inner.ReadState) return storage.GetDelegateUserStakeFromState(ctx, c.inner.ReadState, owner, nodeID) } diff --git a/emission/manual.go b/emission/manual.go index a1ed228..bcc13ef 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -5,6 +5,7 @@ package emission import ( "context" + "fmt" "sync" "time" @@ -37,6 +38,7 @@ type Manual struct { // New initializes the Emission struct with initial parameters and sets up the validators heap // and indices map. func NewManual(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddress codec.Address) *Manual { + fmt.Println("NewManual controller") once.Do(func() { c.Logger().Info("Initializing emission with max supply and rewards per block settings") @@ -188,6 +190,7 @@ func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.Pu } if exists { + fmt.Println("NEW VALIDATOR FOR EMISSION EXIST") // If validator exists, it's a re-registration, update necessary fields validator.PublicKey = bls.PublicKeyToBytes(nodePublicKey) // Update public key if needed validator.StakedAmount += stakedAmount // Adjust the staked amount @@ -197,6 +200,7 @@ func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.Pu // Note: We might want to keep some attributes unchanged, such as delegatorsLastClaim, epochRewards, etc. } else { // If validator does not exist, create a new entry + fmt.Println("NEW VALIDATOR FOR EMISSION") e.validators[nodeID] = &Validator{ NodeID: nodeID, PublicKey: bls.PublicKeyToBytes(nodePublicKey), @@ -250,6 +254,7 @@ func (e *Manual) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { // DelegateUserStake increases the delegated stake for a validator and rebalances the heap. func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Address, stakeAmount uint64) error { + fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-1") e.lock.Lock() defer e.lock.Unlock() @@ -257,15 +262,17 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add // Find the validator validator, exists := e.validators[nodeID] + fmt.Println(validator) if !exists { return ErrValidatorNotFound } - - // Check if the delegator was already staked + fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-2") + fmt.Println(&e) + // Check if the delegator was already staked ERROR HERE ? if _, exists := validator.DelegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } - + fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-3") // Update the validator's stake validator.DelegatedAmount += stakeAmount @@ -441,6 +448,7 @@ func (e *Manual) MintNewNAI() uint64 { // DistributeFees allocates transaction fees between the emission account and validators, // based on the total staked amount. func (e *Manual) DistributeFees(fee uint64) { + fmt.Println("DISTRIBUTE FEES") e.lock.Lock() defer e.lock.Unlock() diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 24e208d..0a71c35 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -122,22 +122,17 @@ var ( networkID uint32 gen *genesis.Genesis - //to be reordered staking vars - currentTime time.Time - stakeStartTime time.Time - stakeEndTime time.Time - delegationFeeRate int - withdraw0 string - withdraw1 string - delegate string - rwithdraw0 codec.Address - rwithdraw1 codec.Address - rdelegate codec.Address - delegateFactory *auth.ED25519Factory - nodesFactories []*auth.BLSFactory - nodesAddresses []codec.Address - emissions []emission.Tracker - nodesPubKeys []*bls.PublicKey + withdraw0 string + withdraw1 string + delegate string + rwithdraw0 codec.Address + rwithdraw1 codec.Address + rdelegate codec.Address + delegateFactory *auth.ED25519Factory + nodesFactories []*auth.BLSFactory + nodesAddresses []codec.Address + emissions []emission.Tracker + nodesPubKeys []*bls.PublicKey ) type instance struct { @@ -330,10 +325,6 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Setup and get initial staked validators", func() { height := 0 - currentTime = time.Now().UTC() - stakeStartTime = currentTime.Add(2 * time.Second) - stakeEndTime = currentTime.Add(15 * time.Minute) - delegationFeeRate = 50 withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) @@ -415,6 +406,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.By("Register validator stake node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + stakeStartTime := currentTime.Add(1 * time.Second) + stakeEndTime := currentTime.Add(15 * time.Minute) + delegationFeeRate := 50 + stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[3].nodeID.Bytes(), StakeStartTime: uint64(stakeStartTime.Unix()), @@ -481,6 +477,12 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] + gomega.Ω(exists).To(gomega.Equal(true)) + + // check when it becomes active ? + gomega.Ω(validator.IsActive).To(gomega.Equal(false)) + // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -510,9 +512,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { // fmt.Println(emissions[2].GetEmissionValidators()) // fmt.Println(emissions[3].GetEmissionValidators()) // fmt.Println(emissions[4].GetEmissionValidators()) - // validators, err := instances[3].ncli.StakedValidators(context.Background()) + // validators, err := instances[3].ncli.StakedValidators(context.TODO()) // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(len(validators)).Should(gomega.Equal(2)) + // gomega.Ω(len(validators)).Should(gomega.Equal(1)) // }) ginkgo.By("Transfer NAI to delegate user", func() { @@ -580,8 +582,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { accept := expectBlk(instances[3]) results := accept(true) - fmt.Println("-----------delegate user stake to node 3") - fmt.Println(results[0].Success) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) From b2e3aa43e5d046267bd70242ff3064669cc03c79 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 23 Apr 2024 15:48:12 +0100 Subject: [PATCH 30/78] deactivated initial integration tests for now --- .../integration/{integration_test.go => integration_test.go.old} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/integration/{integration_test.go => integration_test.go.old} (100%) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go.old similarity index 100% rename from tests/integration/integration_test.go rename to tests/integration/integration_test.go.old From 77a2752fc82534e7fa5d841878146b7e38c3b843 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 24 Apr 2024 12:31:29 +0100 Subject: [PATCH 31/78] add gossiper --- tests/integration/new_actions_test.go | 45 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 0a71c35..bf3e062 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -365,8 +365,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - // app.SendAppGossip(context.Background(), tx.Bytes()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -445,6 +446,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -533,6 +537,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -579,6 +586,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -631,6 +641,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -675,6 +688,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + err = instances[3].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -891,6 +907,31 @@ func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { gomega.Ω(err).Should(gomega.BeNil()) err = blk.Verify(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) + + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + err = vm.SetPreference(context.Background(), blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + err = blk.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) +} + +func ImportBlockToInstance2(vm *vm.VM, block snowman.Block) { + blk, err := vm.ParseBlock(context.Background(), block.Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + // err = vm.SetPreference(context.Background(), blk.ID()) + // gomega.Ω(err).To(gomega.BeNil()) + + // sblk := blk.(*chain.StatelessBlock) + // sblkt := sblk.Timestamp().UnixMilli() + // tx := blk.(*chain.StatelessBlock).Txs[0] + // ok, err := sblk.IsRepeat(ctx, vm.Rules(sblkt).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), true) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(ok.Len()).Should(gomega.Equal(1)) err = blk.Accept(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) } From 2d3129cb6a97235ba2a1708a56fc9c77c4256c33 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 24 Apr 2024 13:37:16 +0100 Subject: [PATCH 32/78] no need for gossiping (the current vm is the proposer/builder) --- tests/integration/new_actions_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index bf3e062..d60d0fe 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -366,8 +366,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -447,8 +447,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -538,8 +538,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -587,8 +587,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -642,8 +642,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -689,8 +689,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - err = instances[3].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) From 7840f97c0e26f07c6d7815c505692b9bb4d96ee7 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 24 Apr 2024 17:29:54 +0100 Subject: [PATCH 33/78] no need to delegatorsLastClaim to be public --- emission/emission.go | 32 ++++++++++++++++---------------- emission/helpers.go | 2 +- emission/manual.go | 32 ++++++++++++++++---------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/emission/emission.go b/emission/emission.go index 3ec2921..21b07ca 100644 --- a/emission/emission.go +++ b/emission/emission.go @@ -86,12 +86,12 @@ func (e *Emission) GetNumDelegators(nodeID ids.NodeID) int { // Get delegators for all validators if nodeID == ids.EmptyNodeID { for _, validator := range e.validators { - numDelegators += len(validator.DelegatorsLastClaim) + numDelegators += len(validator.delegatorsLastClaim) } } else { // Get delegators for a specific validator if validator, exists := e.validators[nodeID]; exists { - numDelegators = len(validator.DelegatorsLastClaim) + numDelegators = len(validator.delegatorsLastClaim) } } @@ -138,7 +138,7 @@ func (e *Emission) CalculateUserDelegationRewards(nodeID ids.NodeID, actor codec } // Check if the delegator exists - lastClaimHeight, exists := validator.DelegatorsLastClaim[actor] + lastClaimHeight, exists := validator.delegatorsLastClaim[actor] if !exists { return 0, ErrDelegatorNotFound } @@ -201,7 +201,7 @@ func (e *Emission) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls. PublicKey: bls.PublicKeyToBytes(nodePublicKey), StakedAmount: stakedAmount, DelegationFeeRate: float64(delegationFeeRate) / 100.0, // Convert to decimal - DelegatorsLastClaim: make(map[codec.Address]uint64), + delegatorsLastClaim: make(map[codec.Address]uint64), epochRewards: make(map[uint64]uint64), stakeStartTime: time.Unix(int64(stakeStartTime), 0).UTC(), stakeEndTime: time.Unix(int64(stakeEndTime), 0).UTC(), @@ -237,7 +237,7 @@ func (e *Emission) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { validator.IsActive = false // If there are no more delegators, get the rewards and remove the validator - if len(validator.DelegatorsLastClaim) == 0 { + if len(validator.delegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 e.TotalStaked -= validator.DelegatedAmount @@ -261,7 +261,7 @@ func (e *Emission) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.A } // Check if the delegator was already staked - if _, exists := validator.DelegatorsLastClaim[delegatorAddress]; exists { + if _, exists := validator.delegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } @@ -276,7 +276,7 @@ func (e *Emission) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.A } // Update the delegator's stake - validator.DelegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() + validator.delegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() return nil } @@ -295,7 +295,7 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s } // Check if the delegator exists - if _, exists := validator.DelegatorsLastClaim[actor]; !exists { + if _, exists := validator.delegatorsLastClaim[actor]; !exists { return 0, ErrDelegatorNotFound } @@ -305,7 +305,7 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s if err != nil { return 0, err } - validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.delegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= rewardAmount // Reset unclaimed rewards // Update the validator's stake @@ -318,10 +318,10 @@ func (e *Emission) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, s } // Remove the delegator's entry - delete(validator.DelegatorsLastClaim, actor) + delete(validator.delegatorsLastClaim, actor) // If the validator is inactive and has no more delegators, remove the validator - if !validator.IsActive && len(validator.DelegatorsLastClaim) == 0 { + if !validator.IsActive && len(validator.delegatorsLastClaim) == 0 { delete(e.validators, nodeID) } @@ -348,7 +348,7 @@ func (e *Emission) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) ( validator.UnclaimedStakedReward = 0 // Reset unclaimed rewards // If there are no more delegators, get the rewards - if len(validator.DelegatorsLastClaim) == 0 { + if len(validator.delegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 } @@ -359,7 +359,7 @@ func (e *Emission) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) ( if err != nil { return 0, err } - validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.delegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= reward // Reset unclaimed rewards rewardAmount = reward } @@ -411,7 +411,7 @@ func (e *Emission) MintNewNAI() uint64 { // Calculate the rewards for the validator and for delegation validatorReward, delegationReward := uint64(0), uint64(0) - if len(validator.DelegatorsLastClaim) > 0 { + if len(validator.delegatorsLastClaim) > 0 { validatorReward, delegationReward = distributeValidatorRewards(totalValidatorReward, validator.DelegationFeeRate, validator.DelegatedAmount) } @@ -484,7 +484,7 @@ func (e *Emission) DistributeFees(fee uint64) { totalValidatorFee := uint64(float64(validatorStake) * feesPerStakeUnit) validatorFee, delegationFee := uint64(0), uint64(0) - if len(validator.DelegatorsLastClaim) > 0 { + if len(validator.delegatorsLastClaim) > 0 { validatorFee, delegationFee = distributeValidatorRewards(totalValidatorFee, validator.DelegationFeeRate, validator.DelegatedAmount) } validator.UnclaimedStakedReward += validatorFee @@ -529,7 +529,7 @@ func (e *Emission) GetAllValidators(ctx context.Context) []*Validator { v.DelegationFeeRate = stakedValidator[0].DelegationFeeRate v.DelegatedAmount = stakedValidator[0].DelegatedAmount v.UnclaimedDelegatedReward = stakedValidator[0].UnclaimedDelegatedReward - v.DelegatorsLastClaim = stakedValidator[0].DelegatorsLastClaim + v.delegatorsLastClaim = stakedValidator[0].delegatorsLastClaim } validators = append(validators, &v) } diff --git a/emission/helpers.go b/emission/helpers.go index 1968d15..427729c 100644 --- a/emission/helpers.go +++ b/emission/helpers.go @@ -23,7 +23,7 @@ type Validator struct { DelegatedAmount uint64 `json:"delegatedAmount"` // Total amount delegated to the validator UnclaimedDelegatedReward uint64 `json:"delegatedReward"` // Total rewards accumulated by the delegators - DelegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height + delegatorsLastClaim map[codec.Address]uint64 // Map of delegator addresses to their last claim block height epochRewards map[uint64]uint64 // Rewards per epoch stakeStartTime time.Time // Start time of the stake stakeEndTime time.Time // End time of the stake diff --git a/emission/manual.go b/emission/manual.go index bcc13ef..8bf20e5 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -89,12 +89,12 @@ func (e *Manual) GetNumDelegators(nodeID ids.NodeID) int { // Get delegators for all validators if nodeID == ids.EmptyNodeID { for _, validator := range e.validators { - numDelegators += len(validator.DelegatorsLastClaim) + numDelegators += len(validator.delegatorsLastClaim) } } else { // Get delegators for a specific validator if validator, exists := e.validators[nodeID]; exists { - numDelegators = len(validator.DelegatorsLastClaim) + numDelegators = len(validator.delegatorsLastClaim) } } @@ -141,7 +141,7 @@ func (e *Manual) CalculateUserDelegationRewards(nodeID ids.NodeID, actor codec.A } // Check if the delegator exists - lastClaimHeight, exists := validator.DelegatorsLastClaim[actor] + lastClaimHeight, exists := validator.delegatorsLastClaim[actor] if !exists { return 0, ErrDelegatorNotFound } @@ -206,7 +206,7 @@ func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.Pu PublicKey: bls.PublicKeyToBytes(nodePublicKey), StakedAmount: stakedAmount, DelegationFeeRate: float64(delegationFeeRate) / 100.0, // Convert to decimal - DelegatorsLastClaim: make(map[codec.Address]uint64), + delegatorsLastClaim: make(map[codec.Address]uint64), epochRewards: make(map[uint64]uint64), stakeStartTime: time.Unix(int64(stakeStartTime), 0).UTC(), stakeEndTime: time.Unix(int64(stakeEndTime), 0).UTC(), @@ -242,7 +242,7 @@ func (e *Manual) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { validator.IsActive = false // If there are no more delegators, get the rewards and remove the validator - if len(validator.DelegatorsLastClaim) == 0 { + if len(validator.delegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 e.TotalStaked -= validator.DelegatedAmount @@ -269,7 +269,7 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-2") fmt.Println(&e) // Check if the delegator was already staked ERROR HERE ? - if _, exists := validator.DelegatorsLastClaim[delegatorAddress]; exists { + if _, exists := validator.delegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-3") @@ -284,7 +284,7 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add } // Update the delegator's stake - validator.DelegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() + validator.delegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() return nil } @@ -303,7 +303,7 @@ func (e *Manual) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, sta } // Check if the delegator exists - if _, exists := validator.DelegatorsLastClaim[actor]; !exists { + if _, exists := validator.delegatorsLastClaim[actor]; !exists { return 0, ErrDelegatorNotFound } @@ -313,7 +313,7 @@ func (e *Manual) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, sta if err != nil { return 0, err } - validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.delegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= rewardAmount // Reset unclaimed rewards // Update the validator's stake @@ -326,10 +326,10 @@ func (e *Manual) UndelegateUserStake(nodeID ids.NodeID, actor codec.Address, sta } // Remove the delegator's entry - delete(validator.DelegatorsLastClaim, actor) + delete(validator.delegatorsLastClaim, actor) // If the validator is inactive and has no more delegators, remove the validator - if !validator.IsActive && len(validator.DelegatorsLastClaim) == 0 { + if !validator.IsActive && len(validator.delegatorsLastClaim) == 0 { delete(e.validators, nodeID) } @@ -356,7 +356,7 @@ func (e *Manual) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) (ui validator.UnclaimedStakedReward = 0 // Reset unclaimed rewards // If there are no more delegators, get the rewards - if len(validator.DelegatorsLastClaim) == 0 { + if len(validator.delegatorsLastClaim) == 0 { rewardAmount += validator.UnclaimedDelegatedReward validator.UnclaimedDelegatedReward = 0 } @@ -367,7 +367,7 @@ func (e *Manual) ClaimStakingRewards(nodeID ids.NodeID, actor codec.Address) (ui if err != nil { return 0, err } - validator.DelegatorsLastClaim[actor] = currentBlockHeight + validator.delegatorsLastClaim[actor] = currentBlockHeight validator.UnclaimedDelegatedReward -= reward // Reset unclaimed rewards rewardAmount = reward } @@ -419,7 +419,7 @@ func (e *Manual) MintNewNAI() uint64 { // Calculate the rewards for the validator and for delegation validatorReward, delegationReward := uint64(0), uint64(0) - if len(validator.DelegatorsLastClaim) > 0 { + if len(validator.delegatorsLastClaim) > 0 { validatorReward, delegationReward = distributeValidatorRewards(totalValidatorReward, validator.DelegationFeeRate, validator.DelegatedAmount) } @@ -493,7 +493,7 @@ func (e *Manual) DistributeFees(fee uint64) { totalValidatorFee := uint64(float64(validatorStake) * feesPerStakeUnit) validatorFee, delegationFee := uint64(0), uint64(0) - if len(validator.DelegatorsLastClaim) > 0 { + if len(validator.delegatorsLastClaim) > 0 { validatorFee, delegationFee = distributeValidatorRewards(totalValidatorFee, validator.DelegationFeeRate, validator.DelegatedAmount) } validator.UnclaimedStakedReward += validatorFee @@ -532,7 +532,7 @@ func (e *Manual) GetAllValidators(ctx context.Context) []*Validator { v.DelegationFeeRate = stakedValidator[0].DelegationFeeRate v.DelegatedAmount = stakedValidator[0].DelegatedAmount v.UnclaimedDelegatedReward = stakedValidator[0].UnclaimedDelegatedReward - v.DelegatorsLastClaim = stakedValidator[0].DelegatorsLastClaim + v.delegatorsLastClaim = stakedValidator[0].delegatorsLastClaim } } return e.CurrentValidators From 876da14e8b68263bd0629cd13c0125a3eec2f997 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 24 Apr 2024 17:33:06 +0100 Subject: [PATCH 34/78] add staked validators test --- tests/integration/new_actions_test.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index d60d0fe..e997a2e 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -509,17 +509,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) - // ginkgo.By("Get staked validators", func() { - // fmt.Println("GET EMISSION 3 VALIDATORS") - // fmt.Println(emissions[0].GetEmissionValidators()) - // fmt.Println(emissions[1].GetEmissionValidators()) - // fmt.Println(emissions[2].GetEmissionValidators()) - // fmt.Println(emissions[3].GetEmissionValidators()) - // fmt.Println(emissions[4].GetEmissionValidators()) - // validators, err := instances[3].ncli.StakedValidators(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(len(validators)).Should(gomega.Equal(1)) - // }) + ginkgo.By("Get staked validators", func() { + validators, err := instances[4].ncli.StakedValidators(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) ginkgo.By("Transfer NAI to delegate user", func() { parser, err := instances[3].ncli.Parser(context.Background()) From a7f84d77f53c16b3e8f6e6e13b25d064235ea643 Mon Sep 17 00:00:00 2001 From: najla Date: Sat, 27 Apr 2024 19:16:00 +0100 Subject: [PATCH 35/78] fund node 0 --- tests/e2e/e2e_test.go | 69 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index c78d95f..7ecd8fc 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -32,6 +32,7 @@ import ( "github.com/nuklai/nuklaivm/actions" "github.com/nuklai/nuklaivm/auth" + "github.com/nuklai/nuklaivm/cmd/nuklai-cli/cmd" nconsts "github.com/nuklai/nuklaivm/consts" nrpc "github.com/nuklai/nuklaivm/rpc" ) @@ -74,7 +75,8 @@ var ( trackSubnetsOpt runner_sdk.OpOption - numValidators uint + numValidators uint + nodesAddresses []codec.Address ) func init() { @@ -347,7 +349,8 @@ var _ = ginkgo.BeforeSuite(func() { nodeInfos := status.GetClusterInfo().GetNodeInfos() instancesA = []instance{} - for _, nodeName := range subnetA { + nodesAddresses = make([]codec.Address, len(subnetA)) + for i, nodeName := range subnetA { info := nodeInfos[nodeName] u := fmt.Sprintf("%s/ext/bc/%s", info.Uri, blockchainIDA) bid, err := ids.FromString(blockchainIDA) @@ -380,6 +383,12 @@ var _ = ginkgo.BeforeSuite(func() { destDir := fmt.Sprintf("/tmp/nuklaivm/nodes/%s/", info.GetName()) err = copyNodeInfo(info.GetDbDir(), destDir) gomega.Expect(err).Should(gomega.BeNil()) + + validatorSignerKey, err := cmd.LoadPrivateKey("bls", fmt.Sprintf("%s/signer.key", destDir)) + fmt.Println("VALIDATOR SIGNER KEY") + fmt.Println(validatorSignerKey) + gomega.Expect(err).Should(gomega.BeNil()) + nodesAddresses[i] = validatorSignerKey.Address } if mode != modeRunSingle { @@ -1506,6 +1515,62 @@ var _ = ginkgo.Describe("[Test]", func() { // TODO: restart all nodes (crisis simulation) }) +var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { + ginkgo.FIt("Setup and get initial staked validators", func() { + ginkgo.By("Initial staked validators", func() { + validators, err := instancesA[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) + + ginkgo.By("Funding node 0", func() { + fmt.Println("-----------NODES ADDRESSES------------") + fmt.Println(len(nodesAddresses)) + parser, err := instancesA[0].ncli.Parser(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[0], + Asset: ids.Empty, + Value: 200_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}generated transaction{{/}}\n") + + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction %s on B{{/}}\n", tx.ID()) + + balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") + + // check if gossip/ new state happens + balance, err = instancesA[1].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") + + balance, err = instancesA[1].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(852_999_799_999_970_300))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") + }) + + }) +}) + func awaitHealthy(cli runner_sdk.Client) { for { time.Sleep(healthPollInterval) From 8ad0c98c2e231541714652bd408384684107c24d Mon Sep 17 00:00:00 2001 From: najla Date: Sat, 27 Apr 2024 20:16:47 +0100 Subject: [PATCH 36/78] register validator stake node 0 --- tests/e2e/e2e_test.go | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 7ecd8fc..bdc8916 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -26,6 +26,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/crypto/bls" "github.com/ava-labs/hypersdk/crypto/ed25519" hrpc "github.com/ava-labs/hypersdk/rpc" hutils "github.com/ava-labs/hypersdk/utils" @@ -77,6 +78,7 @@ var ( numValidators uint nodesAddresses []codec.Address + nodesFactories []*auth.BLSFactory ) func init() { @@ -350,6 +352,7 @@ var _ = ginkgo.BeforeSuite(func() { instancesA = []instance{} nodesAddresses = make([]codec.Address, len(subnetA)) + nodesFactories = make([]*auth.BLSFactory, len(subnetA)) for i, nodeName := range subnetA { info := nodeInfos[nodeName] u := fmt.Sprintf("%s/ext/bc/%s", info.Uri, blockchainIDA) @@ -389,6 +392,9 @@ var _ = ginkgo.BeforeSuite(func() { fmt.Println(validatorSignerKey) gomega.Expect(err).Should(gomega.BeNil()) nodesAddresses[i] = validatorSignerKey.Address + sk, err := bls.PrivateKeyFromBytes(validatorSignerKey.Bytes) + gomega.Expect(err).Should(gomega.BeNil()) + nodesFactories[i] = auth.NewBLSFactory(sk) } if mode != modeRunSingle { @@ -1568,6 +1574,70 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) + ginkgo.By("Register validator stake node 3", func() { + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) + parser, err := instancesA[0].ncli.Parser(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + stakeStartTime := currentTime.Add(1 * time.Second) + stakeEndTime := currentTime.Add(15 * time.Minute) + delegationFeeRate := 50 + + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instancesA[0].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[0].Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[0], + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + + balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction{{/}}\n") + + balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + + // check if gossip/ new state happens + balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) + + }) + }) }) From 48e2d7bd1e68a9e62463d98f3e382a8f11a78808 Mon Sep 17 00:00:00 2001 From: najla Date: Sun, 28 Apr 2024 19:08:53 +0100 Subject: [PATCH 37/78] delegate user stake to node 0 --- tests/e2e/e2e_test.go | 89 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index bdc8916..fd3b33c 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -76,9 +76,11 @@ var ( trackSubnetsOpt runner_sdk.OpOption - numValidators uint - nodesAddresses []codec.Address - nodesFactories []*auth.BLSFactory + numValidators uint + nodesAddresses []codec.Address + nodesFactories []*auth.BLSFactory + rdelegate codec.Address + delegateFactory *auth.ED25519Factory ) func init() { @@ -1638,6 +1640,87 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) + ginkgo.By("Get validator staked amount after node 0 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instancesA[1].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) + + ginkgo.By("Get staked validators", func() { + validators, err := instancesA[1].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) + + ginkgo.By("Transfer NAI to delegate user", func() { + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + delegate := codec.MustAddressBech32(nconsts.HRP, rdelegate) + delegateFactory = auth.NewED25519Factory(delegatePriv) + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction{{/}}\n") + + balance, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + time.Sleep(5 * time.Second) + }) + + ginkgo.By("delegate user stake to node 0", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + userStakeStartTime := currentTime.Add(1 * time.Second) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instancesA[0].nodeID.Bytes(), + StakeStartTime: uint64(userStakeStartTime.Unix()), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction{{/}}\n") + + _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + + }) + }) }) From ccca0bfd56a0b1f4e8248bc476fc9aa2ed6d00d9 Mon Sep 17 00:00:00 2001 From: najla Date: Sun, 28 Apr 2024 20:27:05 +0100 Subject: [PATCH 38/78] user delegate passes --- tests/e2e/e2e_test.go | 50 +++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index fd3b33c..f6256a4 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1682,17 +1682,31 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found transaction{{/}}\n") - balance, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - time.Sleep(5 * time.Second) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + + balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + + } }) - ginkgo.By("delegate user stake to node 0", func() { + ginkgo.By("Delegate user stake to node 0", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(1 * time.Second) + userStakeStartTime := currentTime.Add(2 * time.Second) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( context.Background(), parser, @@ -1707,17 +1721,31 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + hutils.Outf("{{yellow}}submitted delegate user stake transaction{{/}}\n") ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) cancel() gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found transaction{{/}}\n") + hutils.Outf("{{yellow}}found delegate user stake transaction{{/}}\n") - _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + } }) From d5079d7f88636ae4b3ebfc7e8c3dd5492e716cb2 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 29 Apr 2024 09:27:12 +0100 Subject: [PATCH 39/78] delegate user passes (unstable test) --- tests/e2e/e2e_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index f6256a4..31d0b25 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1739,7 +1739,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { if h > 0 { break } - time.Sleep(1 * time.Second) + time.Sleep(2 * time.Second) } _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) @@ -1749,6 +1749,12 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) + // ginkgo.By("Get user stake before claim", func() { + // _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + // }) + }) }) From 33223206febd64b15e4f1dda923d767979dc7371 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 29 Apr 2024 10:16:35 +0100 Subject: [PATCH 40/78] delegate user passes (unstable test) --- tests/e2e/e2e_test.go | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 31d0b25..d46e644 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1526,7 +1526,7 @@ var _ = ginkgo.Describe("[Test]", func() { var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Setup and get initial staked validators", func() { ginkgo.By("Initial staked validators", func() { - validators, err := instancesA[3].ncli.StakedValidators(context.Background()) + validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) }) @@ -1576,7 +1576,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) - ginkgo.By("Register validator stake node 3", func() { + ginkgo.By("Register validator stake node 0", func() { withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) @@ -1621,23 +1621,36 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + hutils.Outf("{{yellow}}submitted register validator stake transaction{{/}}\n") ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) cancel() gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found transaction{{/}}\n") + hutils.Outf("{{yellow}}found register validator stake transaction{{/}}\n") - balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) - // check if gossip/ new state happens - balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + + balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + // check if gossip/ new state happens + balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) + } }) ginkgo.By("Get validator staked amount after node 0 validator staking", func() { @@ -1706,7 +1719,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(2 * time.Second) + // userStakeStartTime := currentTime.Add(2 * time.Minute) + userStakeStartTime := currentTime.Add(2 * time.Minute) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( context.Background(), parser, From ce5e47513912df4d7762dbfbcadb6868a0f0078a Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 29 Apr 2024 10:24:33 +0100 Subject: [PATCH 41/78] passes --- tests/e2e/e2e_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index d46e644..1aec44d 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1763,11 +1763,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - // ginkgo.By("Get user stake before claim", func() { - // _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - // }) + ginkgo.By("Get user stake before claim", func() { + _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + }) }) }) From 7506eb45d5fb23e39f737f2a72199b322894e3d2 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 29 Apr 2024 11:48:11 +0100 Subject: [PATCH 42/78] should pass till before claim delegation reward --- tests/e2e/e2e_test.go | 541 ++++++++++++++++++++++++++---------------- 1 file changed, 334 insertions(+), 207 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 1aec44d..8b75493 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -79,6 +79,7 @@ var ( numValidators uint nodesAddresses []codec.Address nodesFactories []*auth.BLSFactory + delegate string rdelegate codec.Address delegateFactory *auth.ED25519Factory ) @@ -1524,252 +1525,378 @@ var _ = ginkgo.Describe("[Test]", func() { }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.FIt("Setup and get initial staked validators", func() { - ginkgo.By("Initial staked validators", func() { - validators, err := instancesA[0].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) + // ginkgo.FIt("Setup and get initial staked validators", func() { + ginkgo.FIt("Initial staked validators", func() { + validators, err := instancesA[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) - ginkgo.By("Funding node 0", func() { - fmt.Println("-----------NODES ADDRESSES------------") - fmt.Println(len(nodesAddresses)) - parser, err := instancesA[0].ncli.Parser(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: nodesAddresses[0], - Asset: ids.Empty, - Value: 200_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}generated transaction{{/}}\n") + ginkgo.FIt("Funding node 0", func() { + fmt.Println("-----------NODES ADDRESSES------------") + fmt.Println(len(nodesAddresses)) + parser, err := instancesA[0].ncli.Parser(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[0], + Asset: ids.Empty, + Value: 200_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}generated transaction{{/}}\n") - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted transaction{{/}}\n") - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) - cancel() - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found transaction %s on B{{/}}\n", tx.ID()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction %s on B{{/}}\n", tx.ID()) - balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) - hutils.Outf("{{yellow}}fetched balance{{/}}\n") + balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") - // check if gossip/ new state happens - balance, err = instancesA[1].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) - hutils.Outf("{{yellow}}fetched balance{{/}}\n") + // check if gossip/ new state happens + balance, err = instancesA[1].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") - balance, err = instancesA[1].ncli.Balance(context.TODO(), sender, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(852_999_799_999_970_300))) - hutils.Outf("{{yellow}}fetched balance{{/}}\n") - }) + balance, err = instancesA[1].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(852_999_799_999_970_300))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") + }) - ginkgo.By("Register validator stake node 0", func() { - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) - parser, err := instancesA[0].ncli.Parser(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - stakeStartTime := currentTime.Add(1 * time.Second) - stakeEndTime := currentTime.Add(15 * time.Minute) - delegationFeeRate := 50 - - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instancesA[0].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100_000_000_000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, + ginkgo.FIt("Register validator stake node 0", func() { + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) + parser, err := instancesA[0].ncli.Parser(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + stakeStartTime := currentTime.Add(30 * time.Second) + stakeEndTime := currentTime.Add(15 * time.Minute) + delegationFeeRate := 50 + + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instancesA[0].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[0].Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[0], + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + + balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted register validator stake transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found register validator stake transaction{{/}}\n") + + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) } - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := nodesFactories[0].Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - nodesFactories[0], - ) - fmt.Println(err) + balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) - balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + // check if gossip/ new state happens + balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) + } + }) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted register validator stake transaction{{/}}\n") - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) - cancel() - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found register validator stake transaction{{/}}\n") + ginkgo.FIt("Get validator staked amount after node 0 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instancesA[1].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) - for _, inst := range instancesA { - color.Blue("checking %q", inst.uri) + ginkgo.FIt("Get staked validators", func() { + validators, err := instancesA[1].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) - } + ginkgo.FIt("Transfer NAI to delegate user", func() { + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) + delegateFactory = auth.NewED25519Factory(delegatePriv) + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction{{/}}\n") - balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) - // check if gossip/ new state happens - balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) + if h > 0 { + break + } + time.Sleep(1 * time.Second) } - }) - ginkgo.By("Get validator staked amount after node 0 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instancesA[1].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - ginkgo.By("Get staked validators", func() { - validators, err := instancesA[1].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) + } + }) - ginkgo.By("Transfer NAI to delegate user", func() { - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - delegate := codec.MustAddressBech32(nconsts.HRP, rdelegate) - delegateFactory = auth.NewED25519Factory(delegatePriv) - parser, err := instancesA[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rdelegate, - Asset: ids.Empty, - Value: 100_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted transaction{{/}}\n") - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) - cancel() - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found transaction{{/}}\n") + ginkgo.FIt("Delegate user stake to node 0", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + // userStakeStartTime := currentTime.Add(2 * time.Minute) + userStakeStartTime := currentTime.Add(1 * time.Minute) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instancesA[0].nodeID.Bytes(), + StakeStartTime: uint64(userStakeStartTime.Unix()), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted delegate user stake transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found delegate user stake transaction{{/}}\n") - for _, inst := range instancesA { - color.Blue("checking %q", inst.uri) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break } + time.Sleep(2 * time.Second) + } - balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + } + + }) + + ginkgo.FIt("Get user stake before claim", func() { + _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + }) + + ginkgo.FIt("Claim delegation stake rewards from node 0", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instancesA[0].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted claim delegation stake transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found claim delegation stake transaction{{/}}\n") + + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(2 * time.Second) } - }) - ginkgo.By("Delegate user stake to node 0", func() { - parser, err := instancesA[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - userStakeStartTime := currentTime.Add(2 * time.Minute) - submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.DelegateUserStake{ - NodeID: instancesA[0].nodeID.Bytes(), - StakeStartTime: uint64(userStakeStartTime.Unix()), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, - }, - delegateFactory, - ) + balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - hutils.Outf("{{yellow}}submitted delegate user stake transaction{{/}}\n") - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) - cancel() - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(success).Should(gomega.BeTrue()) - hutils.Outf("{{yellow}}found delegate user stake transaction{{/}}\n") + gomega.Ω(balance).Should(gomega.BeNumerically(">", 70_000_000_000)) + } - for _, inst := range instancesA { - color.Blue("checking %q", inst.uri) + }) - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(2 * time.Second) - } + ginkgo.FIt("Undelegate user stake from node 0", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instancesA[0].nodeID.Bytes(), + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted undelegate user stake transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found undelegate user stake transaction{{/}}\n") - _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + if h > 0 { + break + } + time.Sleep(2 * time.Second) } - }) - - ginkgo.By("Get user stake before claim", func() { - _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) + balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - }) + gomega.Ω(balance).Should(gomega.BeNumerically(">", 100_000_000_000)) + } + + }) + + ginkgo.FIt("Withdraw validator node 0 stake", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instancesA[0].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted withdraw validator node stake transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found withdraw validator node stake transaction{{/}}\n") + }) + + ginkgo.FIt("Get validator stake after staking withdraw ", func() { + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(2 * time.Second) + } + _, _, stakedAmount, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + } }) + }) func awaitHealthy(cli runner_sdk.Client) { From c04bd5ee2b6535b93fc97edc5dfc73597c4c5741 Mon Sep 17 00:00:00 2001 From: najla Date: Mon, 29 Apr 2024 18:16:16 +0100 Subject: [PATCH 43/78] By -> It --- tests/integration/new_actions_test.go | 814 +++++++++++++------------- 1 file changed, 400 insertions(+), 414 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index e997a2e..0de4698 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -7,6 +7,7 @@ import ( "context" "encoding/hex" "encoding/json" + "errors" "flag" "fmt" "net/http" @@ -133,6 +134,7 @@ var ( nodesAddresses []codec.Address emissions []emission.Tracker nodesPubKeys []*bls.PublicKey + height int ) type instance struct { @@ -324,8 +326,7 @@ var _ = ginkgo.AfterSuite(func() { var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Setup and get initial staked validators", func() { - height := 0 - + height = 0 withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) @@ -342,452 +343,392 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) delegateFactory = auth.NewED25519Factory(delegatePriv) - ginkgo.By("Initial staked validators", func() { - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) + validators, err := instances[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) - ginkgo.By("Funding node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: nodesAddresses[3], - Asset: ids.Empty, - Value: 200_000_000_000, - }, - factory, - ) - fmt.Println(err) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(1)) - - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + ginkgo.FIt("Funding node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[3], + Asset: ids.Empty, + Value: 200_000_000_000, + }, + factory, + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + // err = instances[3].vm.Gossiper().Force(context.TODO()) + // gomega.Ω(err).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) - // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) - gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) - balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) - fmt.Printf("balance factory %s %d\n", sender, balance) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) + fmt.Printf("balance factory %s %d\n", sender, balance) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) - fmt.Println("LAST ACCEPTED BLOCK") - fmt.Println(instances[3].vm.LastAccepted(context.Background())) - fmt.Println(instances[4].vm.LastAccepted(context.Background())) - }) + fmt.Println("LAST ACCEPTED BLOCK") + fmt.Println(instances[3].vm.LastAccepted(context.Background())) + fmt.Println(instances[4].vm.LastAccepted(context.Background())) + }) - ginkgo.By("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - stakeStartTime := currentTime.Add(1 * time.Second) - stakeEndTime := currentTime.Add(15 * time.Minute) - delegationFeeRate := 50 - - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), - StakedAmount: 100_000_000_000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := nodesFactories[3].Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - nodesFactories[3], - ) - fmt.Println(err) - gomega.Ω(err).Should(gomega.BeNil()) + ginkgo.FIt("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + stakeStartTime := currentTime.Add(1 * time.Second) + stakeEndTime := currentTime.Add(15 * time.Minute) + delegationFeeRate := 50 + + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(stakeStartTime.Unix()), + StakeEndTime: uint64(stakeEndTime.Unix()), + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[3].Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[3], + ) + fmt.Println(err) + gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) + balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) - emissionInstance := emissions[3] - currentValidators := emissionInstance.GetAllValidators(context.TODO()) - gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) - stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - fmt.Println(stakedValidator) - gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) - validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] - gomega.Ω(exists).To(gomega.Equal(true)) + emissionInstance := emissions[3] + currentValidators := emissionInstance.GetAllValidators(context.TODO()) + gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + fmt.Println(stakedValidator) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - // check when it becomes active ? - gomega.Ω(validator.IsActive).To(gomega.Equal(false)) + validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] + gomega.Ω(exists).To(gomega.Equal(true)) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + // check when it becomes active ? + gomega.Ω(validator.IsActive).To(gomega.Equal(false)) - }) + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - ginkgo.By("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) + }) - ginkgo.By("Get validator staked amount after staking using node 0 cli", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) + ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) - ginkgo.By("Get staked validators", func() { - validators, err := instances[4].ncli.StakedValidators(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) + ginkgo.FIt("Get validator staked amount after staking using node 0 cli", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) - ginkgo.By("Transfer NAI to delegate user", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rdelegate, - Asset: ids.Empty, - Value: 100_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + ginkgo.FIt("Get staked validators", func() { + validators, err := instances[4].ncli.StakedValidators(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) + ginkgo.FIt("Transfer NAI to delegate user", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - ginkgo.By("delegate user stake to node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(1 * time.Second) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.DelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(userStakeStartTime.Unix()), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - fmt.Printf("delegate stake to node 3 %d", height) + balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - blk := blocks[height] - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - height++ + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + ginkgo.FIt("delegate user stake to node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentTime := time.Now().UTC() + userStakeStartTime := currentTime.Add(1 * time.Second) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartTime: uint64(userStakeStartTime.Unix()), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - }) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - ginkgo.By("Get user stake before claim", func() { - _, stakedAmount, _, _, err := instances[4].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - }) + fmt.Printf("delegate stake to node 3 %d", height) - ginkgo.By("Claim delegation stake rewards from node 3", func() { - time.Sleep(1 * time.Second) - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ClaimDelegationStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - UserStakeAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) + blk := blocks[height] + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + height++ - ginkgo.By("Get user stake after claim", func() { - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - }) + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - ginkgo.By("Undelegate user stake from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.UndelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - }) - - // add more ginko.By where error should be thrown with wrong data input - // ginkgo.By("Claim validator node 0 stake reward", func() { - // // ClaimValidatorStakeRewards - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.ClaimValidatorStakeRewards{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Withdraw validator node 0 stake", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[0].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Get validator stake after staking withdraw ", func() { - // _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - // }) - - // ginkgo.By("Withdraw validator node 1 stake with wrong key", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[1].nodeID.Bytes(), - // }, - // factory2, - // ) - // gomega.Ω(err).ShouldNot(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).ShouldNot(gomega.BeNil()) - // }) - - // staking withdraw then user delegate withdraw on node 1 - // ginkgo.By("Withdraw validator node 1 stake", func() { - // // WithdrawValidatorStake - // // TO DO: test claim with a wrong key - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.WithdrawValidatorStake{ - // NodeID: instances[1].nodeID.Bytes(), - // }, - // factory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) - - // ginkgo.By("Undelegate user stake from node 1", func() { - // submit, _, _, err := instances[1].hcli.GenerateTransaction( - // context.Background(), - // parser0, - // nil, - // &actions.UndelegateUserStake{ - // NodeID: instances[0].nodeID.Bytes(), - // }, - // delegateFactory, - // ) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - // }) + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + + }) + + ginkgo.FIt("Get user stake before claim", func() { + _, stakedAmount, _, _, err := instances[4].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + }) + + ginkgo.FIt("Claim delegation stake rewards from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) + + // ginkgo.By("Get user stake after claim", func() { + // _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + // gomega.Ω(err).Should(gomega.BeNil()) + // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + // }) + + ginkgo.FIt("Undelegate user stake from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) + + // add more ginko.By where error should be thrown with wrong data input + ginkgo.FIt("Claim validator node 0 stake reward", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.FIt("Withdraw validator node 0 stake", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instances[0].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + }) + + ginkgo.FIt("Get validator stake after staking withdraw ", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) }) }) @@ -930,6 +871,51 @@ func ImportBlockToInstance2(vm *vm.VM, block snowman.Block) { gomega.Ω(err).Should(gomega.BeNil()) } +func produceBlock(i *instance) (*chain.StatelessBlock, func()) { + ctx := context.TODO() + + blk, err := i.vm.BuildBlock(ctx) + if errors.Is(err, chain.ErrNoTxs) { + return nil, nil + } + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) + + gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = i.vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + return blk.(*chain.StatelessBlock), func() { + gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + + lastAccepted, err := i.vm.LastAccepted(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + } +} + +func addBlock(i *instance, blk *chain.StatelessBlock) func() { + ctx := context.TODO() + // start := time.Now() + tblk, err := i.vm.ParseBlock(ctx, blk.Bytes()) + // i.parse = append(i.parse, time.Since(start).Seconds()) + gomega.Ω(err).Should(gomega.BeNil()) + // start = time.Now() + gomega.Ω(tblk.Verify(ctx)).Should(gomega.BeNil()) + // i.verify = append(i.verify, time.Since(start).Seconds()) + // blk.MarkAccepted(context.Background()) + // err = i.vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + return func() { + // start = time.Now() + gomega.Ω(blk.Accept(ctx)).Should(gomega.BeNil()) + // i.accept = append(i.accept, time.Since(start).Seconds()) + } +} + func setEmissionValidators() { currentValidators := make([]*emission.Validator, 0, len(instances)) for i, inst := range instances { From 24904227bf73c246e9ad6f7df72ddb471a000427 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 30 Apr 2024 12:12:26 +0100 Subject: [PATCH 44/78] update tests with start/end block --- actions/register_validator_stake.go | 1 + cmd/nuklai-cli/cmd/key.go | 4 ++-- tests/e2e/e2e_test.go | 23 ++++++++--------------- tests/integration/new_actions_test.go | 19 ++++++++----------- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/actions/register_validator_stake.go b/actions/register_validator_stake.go index 5fd6503..e05bd37 100644 --- a/actions/register_validator_stake.go +++ b/actions/register_validator_stake.go @@ -5,6 +5,7 @@ package actions import ( "context" + "fmt" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/platformvm/warp" diff --git a/cmd/nuklai-cli/cmd/key.go b/cmd/nuklai-cli/cmd/key.go index 4eef690..5d1ae9c 100644 --- a/cmd/nuklai-cli/cmd/key.go +++ b/cmd/nuklai-cli/cmd/key.go @@ -90,7 +90,7 @@ func generatePrivateKey(k string) (*cli.PrivateKey, error) { } } -func loadPrivateKey(k string, path string) (*cli.PrivateKey, error) { +func LoadPrivateKey(k string, path string) (*cli.PrivateKey, error) { switch k { case ed25519Key: p, err := hutils.LoadBytes(path, ed25519.PrivateKeyLen) @@ -174,7 +174,7 @@ var importKeyCmd = &cobra.Command{ return checkKeyType(args[0]) }, RunE: func(_ *cobra.Command, args []string) error { - priv, err := loadPrivateKey(args[0], args[1]) + priv, err := LoadPrivateKey(args[0], args[1]) if err != nil { return err } diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 8b75493..4d69632 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1525,7 +1525,6 @@ var _ = ginkgo.Describe("[Test]", func() { }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - // ginkgo.FIt("Setup and get initial staked validators", func() { ginkgo.FIt("Initial staked validators", func() { validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1533,8 +1532,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) ginkgo.FIt("Funding node 0", func() { - fmt.Println("-----------NODES ADDRESSES------------") - fmt.Println(len(nodesAddresses)) parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1583,15 +1580,15 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - stakeStartTime := currentTime.Add(30 * time.Second) - stakeEndTime := currentTime.Add(15 * time.Minute) + currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) + stakeStartBlock := currentBlockHeight + 2 + stakeEndBlock := currentBlockHeight + 100 delegationFeeRate := 50 stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instancesA[0].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), + StakeStartBlock: stakeStartBlock, + StakeEndBlock: stakeEndBlock, StakedAmount: 100_000_000_000, DelegationFeeRate: uint64(delegationFeeRate), RewardAddress: rwithdraw0, @@ -1719,18 +1716,14 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Delegate user stake to node 0", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - // userStakeStartTime := currentTime.Add(2 * time.Minute) - userStakeStartTime := currentTime.Add(1 * time.Minute) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( context.Background(), parser, nil, &actions.DelegateUserStake{ - NodeID: instancesA[0].nodeID.Bytes(), - StakeStartTime: uint64(userStakeStartTime.Unix()), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, + NodeID: instancesA[0].nodeID.Bytes(), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, }, delegateFactory, ) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 0de4698..22fda81 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -407,15 +407,15 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Register validator stake node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - stakeStartTime := currentTime.Add(1 * time.Second) - stakeEndTime := currentTime.Add(15 * time.Minute) + currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() + stakeStartBlock := currentBlockHeight + 2 + stakeEndBlock := currentBlockHeight + 50 delegationFeeRate := 50 stakeInfo := &actions.ValidatorStakeInfo{ NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(stakeStartTime.Unix()), - StakeEndTime: uint64(stakeEndTime.Unix()), + StakeStartBlock: stakeStartBlock, + StakeEndBlock: stakeEndBlock, StakedAmount: 100_000_000_000, DelegationFeeRate: uint64(delegationFeeRate), RewardAddress: rwithdraw0, @@ -560,17 +560,14 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("delegate user stake to node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - currentTime := time.Now().UTC() - userStakeStartTime := currentTime.Add(1 * time.Second) submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, &actions.DelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartTime: uint64(userStakeStartTime.Unix()), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, + NodeID: instances[3].nodeID.Bytes(), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, }, delegateFactory, ) From 2126c8e9d3800a860036c5fb6b8c157d526c343f Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 30 Apr 2024 12:12:51 +0100 Subject: [PATCH 45/78] update tests with start/end block --- cmd/nuklai-cli/cmd/action.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nuklai-cli/cmd/action.go b/cmd/nuklai-cli/cmd/action.go index fad9203..fe9e3a2 100644 --- a/cmd/nuklai-cli/cmd/action.go +++ b/cmd/nuklai-cli/cmd/action.go @@ -580,7 +580,7 @@ var registerValidatorStakeCmd = &cobra.Command{ if autoRegister { hutils.Outf("{{yellow}}Loading private key for %s{{/}}\n", nodeNumber) - validatorSignerKey, err := loadPrivateKey("bls", fmt.Sprintf("/tmp/nuklaivm/nodes/%s-bls/signer.key", nodeNumber)) + validatorSignerKey, err := LoadPrivateKey("bls", fmt.Sprintf("/tmp/nuklaivm/nodes/%s-bls/signer.key", nodeNumber)) if err != nil { return err } From 64763e02ae2ebf542565323a354a53ba01ac0993 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 1 May 2024 12:24:35 +0100 Subject: [PATCH 46/78] claim user reward --- tests/e2e/e2e_test.go | 53 ++++++++++++++++++--------- tests/integration/new_actions_test.go | 41 +++++++++++++++++++-- 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 4d69632..ba197bd 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1562,13 +1562,25 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) hutils.Outf("{{yellow}}fetched balance{{/}}\n") - // check if gossip/ new state happens - balance, err = instancesA[1].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) - hutils.Outf("{{yellow}}fetched balance{{/}}\n") + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) - balance, err = instancesA[1].ncli.Balance(context.TODO(), sender, ids.Empty) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + balance, err = inst.ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + hutils.Outf("{{yellow}}fetched balance{{/}}\n") + } + + balance, err = instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(852_999_799_999_970_300))) hutils.Outf("{{yellow}}fetched balance{{/}}\n") @@ -1645,21 +1657,21 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balance) // check if gossip/ new state happens - balanceOther, err := instancesA[1].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) + balanceOther, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) } }) ginkgo.FIt("Get validator staked amount after node 0 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instancesA[1].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + _, _, stakedAmount, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) ginkgo.FIt("Get staked validators", func() { - validators, err := instancesA[1].ncli.StakedValidators(context.Background()) + validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(1)) }) @@ -1747,7 +1759,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { if h > 0 { break } - time.Sleep(2 * time.Second) + time.Sleep(1 * time.Second) } _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) @@ -1764,6 +1776,12 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) ginkgo.FIt("Claim delegation stake rewards from node 0", func() { + balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Println(balanceBefore) + + // wait for blocks otherwise reward = 0 and error on UnpackUint64 while unmarshalling the data + time.Sleep(1 * time.Minute) parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1780,7 +1798,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) hutils.Outf("{{yellow}}submitted claim delegation stake transaction{{/}}\n") ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + success, fee, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) cancel() gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) @@ -1799,14 +1817,15 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { time.Sleep(2 * time.Second) } - balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) + balanceAfter, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) + fmt.Println(balanceAfter) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.BeNumerically(">", 70_000_000_000)) + gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } }) - ginkgo.FIt("Undelegate user stake from node 0", func() { + ginkgo.It("Undelegate user stake from node 0", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1838,7 +1857,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { if h > 0 { break } - time.Sleep(2 * time.Second) + time.Sleep(1 * time.Second) } balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) @@ -1848,7 +1867,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Withdraw validator node 0 stake", func() { + ginkgo.It("Withdraw validator node 0 stake", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1871,7 +1890,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { hutils.Outf("{{yellow}}found withdraw validator node stake transaction{{/}}\n") }) - ginkgo.FIt("Get validator stake after staking withdraw ", func() { + ginkgo.It("Get validator stake after staking withdraw ", func() { for _, inst := range instancesA { color.Blue("checking %q", inst.uri) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 22fda81..d8a285c 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -409,7 +409,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() stakeStartBlock := currentBlockHeight + 2 - stakeEndBlock := currentBlockHeight + 50 + stakeEndBlock := currentBlockHeight + 100 delegationFeeRate := 50 stakeInfo := &actions.ValidatorStakeInfo{ @@ -702,24 +702,57 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { factory, ) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(instances[0].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) }) ginkgo.FIt("Withdraw validator node 0 stake", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, &actions.WithdrawValidatorStake{ - NodeID: instances[0].nodeID.Bytes(), + NodeID: instances[3].nodeID.Bytes(), }, factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) ginkgo.FIt("Get validator stake after staking withdraw ", func() { From edb54edd077b1013b0bb89fe0338d9643eab5995 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 1 May 2024 12:38:21 +0100 Subject: [PATCH 47/78] undelegate stake user --- tests/e2e/e2e_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index ba197bd..a907acf 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1825,7 +1825,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.It("Undelegate user stake from node 0", func() { + ginkgo.FIt("Undelegate user stake from node 0", func() { + balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) + fmt.Println(balanceBefore) + gomega.Ω(err).Should(gomega.BeNil()) parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1841,7 +1844,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) hutils.Outf("{{yellow}}submitted undelegate user stake transaction{{/}}\n") ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + success, fee, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) cancel() gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) @@ -1860,9 +1863,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { time.Sleep(1 * time.Second) } - balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) + balanceAfter, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.BeNumerically(">", 100_000_000_000)) + gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } }) From 28ae4448f9a58651adfd308a3a05e95da0418c6d Mon Sep 17 00:00:00 2001 From: Kiran Pachhai Date: Wed, 1 May 2024 10:24:52 -0400 Subject: [PATCH 48/78] Made rewardamount to be equal to 0 --- actions/claim_validator_stake_rewards.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/claim_validator_stake_rewards.go b/actions/claim_validator_stake_rewards.go index 3b5f204..7be7838 100644 --- a/actions/claim_validator_stake_rewards.go +++ b/actions/claim_validator_stake_rewards.go @@ -127,7 +127,7 @@ type ClaimRewardsResult struct { func UnmarshalClaimRewardsResult(b []byte) (*ClaimRewardsResult, error) { p := codec.NewReader(b, hconsts.Uint64Len) var result ClaimRewardsResult - result.RewardAmount = p.UnpackUint64(true) + result.RewardAmount = p.UnpackUint64(false) return &result, p.Err() } From f533cc6ed31b1c5cebf391c71e47fbee28682cf0 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 1 May 2024 15:34:27 +0100 Subject: [PATCH 49/78] claim validator rewards --- tests/e2e/e2e_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index a907acf..22114c5 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -81,6 +81,7 @@ var ( nodesFactories []*auth.BLSFactory delegate string rdelegate codec.Address + withdraw0 string delegateFactory *auth.ED25519Factory ) @@ -1590,6 +1591,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) @@ -1870,6 +1872,54 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) + ginkgo.FIt("Claim node 0 stake reward", func() { + balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), withdraw0, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + fmt.Println(balanceBefore) + gomega.Ω(balanceBefore).Should(gomega.Equal(uint64(0))) + + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instancesA[0].nodeID.Bytes(), + }, + nodesFactories[0], + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted claim validator stake reward transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, fee, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found claim validator stake reward transaction{{/}}\n") + + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(2 * time.Second) + } + + balanceAfter, err := inst.ncli.Balance(context.Background(), withdraw0, ids.Empty) + fmt.Println(balanceAfter) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) + } + + }) + ginkgo.It("Withdraw validator node 0 stake", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1891,6 +1941,20 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found withdraw validator node stake transaction{{/}}\n") + + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + } }) ginkgo.It("Get validator stake after staking withdraw ", func() { From 21625eec761735a98921eaf13e5f6e4093c46ce4 Mon Sep 17 00:00:00 2001 From: najla Date: Wed, 1 May 2024 17:03:26 +0100 Subject: [PATCH 50/78] claim validator stake reward --- tests/e2e/e2e_test.go | 67 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 22114c5..fb132e0 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -76,13 +76,15 @@ var ( trackSubnetsOpt runner_sdk.OpOption - numValidators uint - nodesAddresses []codec.Address - nodesFactories []*auth.BLSFactory - delegate string - rdelegate codec.Address - withdraw0 string - delegateFactory *auth.ED25519Factory + numValidators uint + nodesAddresses []codec.Address + nodesFactories []*auth.BLSFactory + delegate string + rdelegate codec.Address + withdraw0 string + rwithdraw0 codec.Address + withdraw0Factory *auth.ED25519Factory + delegateFactory *auth.ED25519Factory ) func init() { @@ -1590,7 +1592,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Register validator stake node 0", func() { withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 := auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0Factory = auth.NewED25519Factory(withdraw0Priv) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1872,11 +1875,55 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) + ginkgo.FIt("Transfer NAI to withdraw node 0 address for fees", func() { + parser, err := instancesA[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rwithdraw0, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + hutils.Outf("{{yellow}}submitted transaction{{/}}\n") + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + cancel() + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(success).Should(gomega.BeTrue()) + hutils.Outf("{{yellow}}found transaction{{/}}\n") + + for _, inst := range instancesA { + color.Blue("checking %q", inst.uri) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + + balance, err := inst.ncli.Balance(context.Background(), withdraw0, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + + } + }) + ginkgo.FIt("Claim node 0 stake reward", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), withdraw0, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Println(balanceBefore) - gomega.Ω(balanceBefore).Should(gomega.Equal(uint64(0))) + gomega.Ω(balanceBefore).Should(gomega.Equal(uint64(100_000_000_000))) parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1887,7 +1934,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { &actions.ClaimValidatorStakeRewards{ NodeID: instancesA[0].nodeID.Bytes(), }, - nodesFactories[0], + withdraw0Factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) From 44149d74e11636e7a3dfb8ce59c200b01c293c52 Mon Sep 17 00:00:00 2001 From: najla Date: Thu, 2 May 2024 17:32:28 +0100 Subject: [PATCH 51/78] withdraw validator --- tests/e2e/e2e_test.go | 45 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index fb132e0..931d62e 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -85,6 +85,7 @@ var ( rwithdraw0 codec.Address withdraw0Factory *auth.ED25519Factory delegateFactory *auth.ED25519Factory + stakeEndBlock uint64 ) func init() { @@ -1599,7 +1600,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) stakeStartBlock := currentBlockHeight + 2 - stakeEndBlock := currentBlockHeight + 100 + stakeEndBlock = currentBlockHeight + 100 delegationFeeRate := 50 stakeInfo := &actions.ValidatorStakeInfo{ @@ -1654,7 +1655,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { if h > 0 { break } - time.Sleep(1 * time.Second) + time.Sleep(2 * time.Second) } balance, err = instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) @@ -1967,7 +1968,21 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.It("Withdraw validator node 0 stake", func() { + ginkgo.FIt("Withdraw validator node 0 stake", func() { + for { + currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) + fmt.Println("CURRENT BLOCK HEIGHT") + fmt.Println(currentBlockHeight) + fmt.Println("STAKE END BLOCK") + fmt.Println(stakeEndBlock) + if stakeEndBlock < currentBlockHeight { + break + } + time.Sleep(2 * time.Second) + } + _, _, _, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1977,7 +1992,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { &actions.WithdrawValidatorStake{ NodeID: instancesA[0].nodeID.Bytes(), }, - factory, + nodesFactories[0], ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) @@ -1989,22 +2004,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found withdraw validator node stake transaction{{/}}\n") - for _, inst := range instancesA { - color.Blue("checking %q", inst.uri) - - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) - } - } - }) - - ginkgo.It("Get validator stake after staking withdraw ", func() { for _, inst := range instancesA { color.Blue("checking %q", inst.uri) @@ -2017,9 +2016,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } time.Sleep(2 * time.Second) } - _, _, stakedAmount, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + _, _, _, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) + gomega.Ω(err).ShouldNot(gomega.BeNil()) + validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) } }) From 9902cec6b6eaa0f24612c04359e58ac223383def Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 3 May 2024 09:18:17 +0100 Subject: [PATCH 52/78] desc --- tests/e2e/e2e_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 931d62e..5714ae5 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1876,7 +1876,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Transfer NAI to withdraw node 0 address for fees", func() { + ginkgo.FIt("Transfer NAI to node 0 withdraw address for fees", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( From 1e967db4506a1cd836e153e188fe46de0bad23ee Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 3 May 2024 11:42:20 +0100 Subject: [PATCH 53/78] withdraw stake --- tests/e2e/e2e_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 5714ae5..9bbca7b 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1842,7 +1842,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { parser, nil, &actions.UndelegateUserStake{ - NodeID: instancesA[0].nodeID.Bytes(), + NodeID: instancesA[0].nodeID.Bytes(), + RewardAddress: rdelegate, }, delegateFactory, ) @@ -1990,7 +1991,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { parser, nil, &actions.WithdrawValidatorStake{ - NodeID: instancesA[0].nodeID.Bytes(), + NodeID: instancesA[0].nodeID.Bytes(), + RewardAddress: rwithdraw0, }, nodesFactories[0], ) From 83686e569a7e314526613bbc2631403e7f99ab10 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 3 May 2024 14:01:30 +0100 Subject: [PATCH 54/78] reward not required --- actions/undelegate_user_stake.go | 2 +- actions/withdraw_validator_stake.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/undelegate_user_stake.go b/actions/undelegate_user_stake.go index 94fb472..167f575 100644 --- a/actions/undelegate_user_stake.go +++ b/actions/undelegate_user_stake.go @@ -138,7 +138,7 @@ func UnmarshalUndelegateUserStakeResult(b []byte) (*UndelegateUserStakeResult, e p := codec.NewReader(b, 2*hconsts.Uint64Len) var result UndelegateUserStakeResult result.StakedAmount = p.UnpackUint64(true) - result.RewardAmount = p.UnpackUint64(true) + result.RewardAmount = p.UnpackUint64(false) return &result, p.Err() } diff --git a/actions/withdraw_validator_stake.go b/actions/withdraw_validator_stake.go index ad1d0ff..2e49e20 100644 --- a/actions/withdraw_validator_stake.go +++ b/actions/withdraw_validator_stake.go @@ -141,7 +141,7 @@ func UnmarshalWithdrawValidatorStakeResult(b []byte) (*WithdrawStakeResult, erro p := codec.NewReader(b, 2*hconsts.Uint64Len) var result WithdrawStakeResult result.StakedAmount = p.UnpackUint64(true) - result.RewardAmount = p.UnpackUint64(true) + result.RewardAmount = p.UnpackUint64(false) return &result, p.Err() } From 1d6443bbb74afafb6de22c00cd0ac4b8aa62660a Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 3 May 2024 15:53:01 +0100 Subject: [PATCH 55/78] FIt -> It --- tests/e2e/e2e_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 9bbca7b..41e47a2 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1529,13 +1529,13 @@ var _ = ginkgo.Describe("[Test]", func() { }) var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.FIt("Initial staked validators", func() { + ginkgo.It("Initial staked validators", func() { validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) }) - ginkgo.FIt("Funding node 0", func() { + ginkgo.It("Funding node 0", func() { parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1590,7 +1590,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) - ginkgo.FIt("Register validator stake node 0", func() { + ginkgo.It("Register validator stake node 0", func() { withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) withdraw0Factory = auth.NewED25519Factory(withdraw0Priv) @@ -1669,20 +1669,20 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.FIt("Get validator staked amount after node 0 validator staking", func() { + ginkgo.It("Get validator staked amount after node 0 validator staking", func() { _, _, stakedAmount, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) - ginkgo.FIt("Get staked validators", func() { + ginkgo.It("Get staked validators", func() { validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(1)) }) - ginkgo.FIt("Transfer NAI to delegate user", func() { + ginkgo.It("Transfer NAI to delegate user", func() { delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) @@ -1731,7 +1731,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.FIt("Delegate user stake to node 0", func() { + ginkgo.It("Delegate user stake to node 0", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1775,13 +1775,13 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Get user stake before claim", func() { + ginkgo.It("Get user stake before claim", func() { _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) }) - ginkgo.FIt("Claim delegation stake rewards from node 0", func() { + ginkgo.It("Claim delegation stake rewards from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Println(balanceBefore) @@ -1831,7 +1831,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Undelegate user stake from node 0", func() { + ginkgo.It("Undelegate user stake from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) fmt.Println(balanceBefore) gomega.Ω(err).Should(gomega.BeNil()) @@ -1877,7 +1877,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Transfer NAI to node 0 withdraw address for fees", func() { + ginkgo.It("Transfer NAI to node 0 withdraw address for fees", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( @@ -1921,7 +1921,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.FIt("Claim node 0 stake reward", func() { + ginkgo.It("Claim node 0 stake reward", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), withdraw0, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) fmt.Println(balanceBefore) @@ -1969,7 +1969,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Withdraw validator node 0 stake", func() { + ginkgo.It("Withdraw validator node 0 stake", func() { for { currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) fmt.Println("CURRENT BLOCK HEIGHT") From c568b5998fafb5497587c421b7425db6da902cb3 Mon Sep 17 00:00:00 2001 From: najla Date: Fri, 3 May 2024 19:07:18 +0100 Subject: [PATCH 56/78] int test --- tests/integration/new_actions_test.go | 54 +++++++++++++++++---------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index d8a285c..54bdb0c 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -492,6 +492,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + validators, err := instances[4].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { @@ -557,7 +561,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - ginkgo.FIt("delegate user stake to node 3", func() { + ginkgo.FIt("Delegate user stake to node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) submit, _, _, err := instances[3].hcli.GenerateTransaction( @@ -591,23 +595,32 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ImportBlockToInstance(instances[0].vm, blk) height++ - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - // test same block is accepted lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) ginkgo.FIt("Get user stake before claim", func() { - _, stakedAmount, _, _, err := instances[4].ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + for _, inst := range instances { + color.Blue("checking %q", inst.nodeID) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + + } }) ginkgo.FIt("Claim delegation stake rewards from node 3", func() { @@ -650,11 +663,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - // ginkgo.By("Get user stake after claim", func() { - // _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - // }) + ginkgo.FIt("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) ginkgo.FIt("Undelegate user stake from node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) @@ -664,7 +677,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { parser, nil, &actions.UndelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rdelegate, }, delegateFactory, ) @@ -688,7 +702,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { height++ }) - // add more ginko.By where error should be thrown with wrong data input ginkgo.FIt("Claim validator node 0 stake reward", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -731,7 +744,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { parser, nil, &actions.WithdrawValidatorStake{ - NodeID: instances[3].nodeID.Bytes(), + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rwithdraw0, }, factory, ) @@ -755,10 +769,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) - ginkgo.FIt("Get validator stake after staking withdraw ", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[0].nodeID) + ginkgo.FIt("Get staked validators after staking withdraw ", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) }) }) From 6a2621798a6e95500a60d013005c9e8668482f07 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 15:40:10 +0100 Subject: [PATCH 57/78] integration tests --- tests/integration/new_actions_test.go | 336 ++++++++++++-------------- 1 file changed, 161 insertions(+), 175 deletions(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 54bdb0c..1801d9d 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -362,12 +362,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }, factory, ) - fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - // err = instances[3].vm.Gossiper().Force(context.TODO()) - // gomega.Ω(err).Should(gomega.BeNil()) accept := expectBlk(instances[3]) results := accept(true) @@ -385,23 +382,16 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) // check if gossip/ new state happens balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) - fmt.Printf("balance factory %s %d\n", sender, balance) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) - - fmt.Println("LAST ACCEPTED BLOCK") - fmt.Println(instances[3].vm.LastAccepted(context.Background())) - fmt.Println(instances[4].vm.LastAccepted(context.Background())) }) ginkgo.FIt("Register validator stake node 3", func() { @@ -438,12 +428,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }, nodesFactories[3], ) - fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 %s balance before staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) @@ -456,21 +444,18 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) blk := blocks[height] - fmt.Println(blk.ID()) ImportBlockToInstance(instances[4].vm, blk) ImportBlockToInstance(instances[0].vm, blk) ImportBlockToInstance(instances[2].vm, blk) ImportBlockToInstance(instances[1].vm, blk) height++ - balance, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[3] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balance) // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + _, err = instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), balanceOther) emissionInstance := emissions[3] currentValidators := emissionInstance.GetAllValidators(context.TODO()) @@ -500,7 +485,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) @@ -603,178 +587,180 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - ginkgo.FIt("Get user stake before claim", func() { - for _, inst := range instances { - color.Blue("checking %q", inst.nodeID) - - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) - } - _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - - } - }) - - ginkgo.FIt("Claim delegation stake rewards from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ClaimDelegationStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - UserStakeAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + /* - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + ginkgo.FIt("Get user stake before claim", func() { + for _, inst := range instances { + color.Blue("checking %q", inst.nodeID) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) - - ginkgo.FIt("Get user stake after claim", func() { - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - }) - - ginkgo.FIt("Undelegate user stake from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.UndelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + } + }) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - }) + ginkgo.It("Claim delegation stake rewards from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) - ginkgo.FIt("Claim validator node 0 stake reward", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ClaimValidatorStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + ginkgo.It("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + ginkgo.It("Undelegate user stake from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) + + ginkgo.It("Claim validator node 0 stake reward", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) - }) + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - ginkgo.FIt("Withdraw validator node 0 stake", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.WithdrawValidatorStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rwithdraw0, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + }) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + ginkgo.It("Withdraw validator node 0 stake", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rwithdraw0, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - }) + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - ginkgo.FIt("Get staked validators after staking withdraw ", func() { - validators, err := instances[0].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) + }) + ginkgo.It("Get staked validators after staking withdraw ", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) + */ }) func expectBlk(i instance) func(bool) []*chain.Result { From bbe3fae8b16448dd6a90a950d3a16e6175458266 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 15:43:28 +0100 Subject: [PATCH 58/78] add TODO --- tests/integration/new_actions_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/new_actions_test.go b/tests/integration/new_actions_test.go index 1801d9d..ae14336 100644 --- a/tests/integration/new_actions_test.go +++ b/tests/integration/new_actions_test.go @@ -587,8 +587,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - /* + // TODO: GetUserStakeFromState is returning an empty value + // TODO: transactions are played twice because of Verify and Accept (block is already processed) + /* ginkgo.FIt("Get user stake before claim", func() { for _, inst := range instances { color.Blue("checking %q", inst.nodeID) From 0c4e2f300942fc94fb862a868d270e71dc3d8590 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 16:24:39 +0100 Subject: [PATCH 59/78] remove println --- actions/register_validator_stake.go | 14 +++----------- controller/resolutions.go | 3 --- emission/manual.go | 10 ---------- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/actions/register_validator_stake.go b/actions/register_validator_stake.go index e05bd37..1184dcc 100644 --- a/actions/register_validator_stake.go +++ b/actions/register_validator_stake.go @@ -5,7 +5,6 @@ package actions import ( "context" - "fmt" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/platformvm/warp" @@ -61,9 +60,6 @@ func (r *RegisterValidatorStake) Execute( _ bool, ) (bool, uint64, []byte, *warp.UnsignedMessage, error) { // Check if it's a valid signature - fmt.Println("REGISTER VALIDATOR STAKE -1 ") - fmt.Println("ACTOR %s", codec.MustAddressBech32(nconsts.HRP, actor)) - // panic("BREAK REGISTER VALIDATOR STAKE") signer, err := VerifyAuthSignature(r.StakeInfo, r.AuthSignature) if err != nil { return false, RegisterValidatorStakeComputeUnits, utils.ErrBytes(err), nil, nil @@ -79,9 +75,6 @@ func (r *RegisterValidatorStake) Execute( // Get the emission instance emissionInstance := emission.GetEmission() - fmt.Println("GET EMISSION") - fmt.Println(&emissionInstance) - fmt.Println(emissionInstance.GetEmissionValidators()) currentValidators := emissionInstance.GetAllValidators(ctx) var nodePublicKey *bls.PublicKey @@ -97,11 +90,10 @@ func (r *RegisterValidatorStake) Execute( break } } - fmt.Println("REGISTER VALIDATOR STAKE -3") + if !isValidatorOwner { return false, RegisterValidatorStakeComputeUnits, OutputUnauthorized, nil, nil } - fmt.Println("REGISTER VALIDATOR STAKE -4") // Unmarshal the stake info stakeInfo, err := UnmarshalValidatorStakeInfo(r.StakeInfo) if err != nil { @@ -112,7 +104,7 @@ func (r *RegisterValidatorStake) Execute( if err != nil { return false, RegisterValidatorStakeComputeUnits, OutputInvalidNodeID, nil, nil } - fmt.Println("REGISTER VALIDATOR STAKE -5") + // Check if the validator was already registered exists, _, _, _, _, _, _, _ := storage.GetRegisterValidatorStake(ctx, mu, nodeID) if exists { @@ -136,7 +128,7 @@ func (r *RegisterValidatorStake) Execute( if stakeInfo.StakeEndBlock < stakeInfo.StakeStartBlock { return false, RegisterValidatorStakeComputeUnits, OutputInvalidStakeEndBlock, nil, nil } - fmt.Println("REGISTER VALIDATOR STAKE -7") + // Check that the total staking period is at least the minimum staking period stakeDuration := stakeInfo.StakeEndBlock - stakeInfo.StakeStartBlock if stakeDuration < stakingConfig.MinValidatorStakeDuration || stakeDuration > stakingConfig.MaxValidatorStakeDuration { diff --git a/controller/resolutions.go b/controller/resolutions.go index 197a0d8..38d3436 100644 --- a/controller/resolutions.go +++ b/controller/resolutions.go @@ -5,7 +5,6 @@ package controller import ( "context" - "fmt" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/trace" @@ -98,7 +97,5 @@ func (c *Controller) GetDelegatedUserStakeFromState(ctx context.Context, owner c codec.Address, // OwnerAddress error, ) { - fmt.Println("GetDelegatedUserStakeFromState") - fmt.Println(c.inner.ReadState) return storage.GetDelegateUserStakeFromState(ctx, c.inner.ReadState, owner, nodeID) } diff --git a/emission/manual.go b/emission/manual.go index ec66390..819db71 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -5,7 +5,6 @@ package emission import ( "context" - "fmt" "sync" "time" @@ -38,7 +37,6 @@ type Manual struct { // New initializes the Emission struct with initial parameters and sets up the validators heap // and indices map. func NewManual(c Controller, vm NuklaiVM, totalSupply, maxSupply uint64, emissionAddress codec.Address) *Manual { - fmt.Println("NewManual controller") once.Do(func() { c.Logger().Info("Initializing emission with max supply and rewards per block settings") @@ -190,7 +188,6 @@ func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.Pu } if exists { - fmt.Println("NEW VALIDATOR FOR EMISSION EXIST") // If validator exists, it's a re-registration, update necessary fields validator.PublicKey = bls.PublicKeyToBytes(nodePublicKey) // Update public key if needed validator.StakedAmount += stakedAmount // Adjust the staked amount @@ -200,7 +197,6 @@ func (e *Manual) RegisterValidatorStake(nodeID ids.NodeID, nodePublicKey *bls.Pu // Note: We might want to keep some attributes unchanged, such as delegatorsLastClaim, epochRewards, etc. } else { // If validator does not exist, create a new entry - fmt.Println("NEW VALIDATOR FOR EMISSION") e.validators[nodeID] = &Validator{ NodeID: nodeID, PublicKey: bls.PublicKeyToBytes(nodePublicKey), @@ -254,7 +250,6 @@ func (e *Manual) WithdrawValidatorStake(nodeID ids.NodeID) (uint64, error) { // DelegateUserStake increases the delegated stake for a validator and rebalances the heap. func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Address, stakeStartBlock, stakeAmount uint64) error { - fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-1") e.lock.Lock() defer e.lock.Unlock() @@ -262,17 +257,13 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add // Find the validator validator, exists := e.validators[nodeID] - fmt.Println(validator) if !exists { return ErrValidatorNotFound } - fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-2") - fmt.Println(&e) // Check if the delegator was already staked ERROR HERE ? if _, exists := validator.delegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } - fmt.Println("EMISSION MANUAL DELEGATE USER STAKE-3") // Update the validator's stake validator.DelegatedAmount += stakeAmount @@ -448,7 +439,6 @@ func (e *Manual) MintNewNAI() uint64 { // DistributeFees allocates transaction fees between the emission account and validators, // based on the total staked amount. func (e *Manual) DistributeFees(fee uint64) { - fmt.Println("DISTRIBUTE FEES") e.lock.Lock() defer e.lock.Unlock() From d61bc74d68bd302a02e9e98dd3de6d6a94402cc6 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 16:33:19 +0100 Subject: [PATCH 60/78] rename file --- tests/integration/{new_actions_test.go => test_new_actions.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/integration/{new_actions_test.go => test_new_actions.go} (100%) diff --git a/tests/integration/new_actions_test.go b/tests/integration/test_new_actions.go similarity index 100% rename from tests/integration/new_actions_test.go rename to tests/integration/test_new_actions.go From 56d21fda4a2e43709405f75d28f5625b434e66f9 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 16:36:10 +0100 Subject: [PATCH 61/78] restore integration tests file --- .../integration/{integration_test.go.old => integration_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/integration/{integration_test.go.old => integration_test.go} (100%) diff --git a/tests/integration/integration_test.go.old b/tests/integration/integration_test.go similarity index 100% rename from tests/integration/integration_test.go.old rename to tests/integration/integration_test.go From aad19452aa7de4ddc7e3384a0d490d206c172eb3 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:12:09 +0100 Subject: [PATCH 62/78] put integration tests in one file --- tests/integration/integration_test.go | 496 +++++++++++++++++- ...ctions.go => new_actions_test.go.separate} | 240 --------- 2 files changed, 493 insertions(+), 243 deletions(-) rename tests/integration/{test_new_actions.go => new_actions_test.go.separate} (78%) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 963bc8e..cae8471 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -46,6 +46,7 @@ import ( "github.com/nuklai/nuklaivm/auth" nconsts "github.com/nuklai/nuklaivm/consts" "github.com/nuklai/nuklaivm/controller" + "github.com/nuklai/nuklaivm/emission" "github.com/nuklai/nuklaivm/genesis" nrpc "github.com/nuklai/nuklaivm/rpc" ) @@ -86,7 +87,7 @@ func init() { flag.IntVar( &vms, "vms", - 3, + 5, "number of VMs to create", ) } @@ -122,6 +123,18 @@ var ( networkID uint32 gen *genesis.Genesis + app *appSender + + withdraw0 string + delegate string + rwithdraw0 codec.Address + rdelegate codec.Address + delegateFactory *auth.ED25519Factory + nodesFactories []*auth.BLSFactory + nodesAddresses []codec.Address + emissions []emission.Tracker + nodesPubKeys []*bls.PublicKey + height int ) type instance struct { @@ -175,6 +188,10 @@ var _ = ginkgo.BeforeSuite(func() { // create embedded VMs instances = make([]instance, vms) + nodesFactories = make([]*auth.BLSFactory, vms) + nodesAddresses = make([]codec.Address, vms) + emissions = make([]emission.Tracker, vms) + nodesPubKeys = make([]*bls.PublicKey, vms) gen = genesis.Default() gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} @@ -182,7 +199,7 @@ var _ = ginkgo.BeforeSuite(func() { gen.CustomAllocation = []*genesis.CustomAllocation{ { Address: sender, - Balance: 10_000_000, + Balance: 10_000_000_000_000_000, }, } gen.EmissionBalancer = genesis.EmissionBalancer{ @@ -197,7 +214,7 @@ var _ = ginkgo.BeforeSuite(func() { subnetID := ids.GenerateTestID() chainID := ids.GenerateTestID() - app := &appSender{} + app = &appSender{} for i := range instances { nodeID := ids.GenerateTestNodeID() sk, err := bls.NewSecretKey() @@ -218,6 +235,9 @@ var _ = ginkgo.BeforeSuite(func() { WarpSigner: warp.NewSigner(sk, networkID, chainID), ValidatorState: &validators.TestState{}, } + nodesFactories[i] = auth.NewBLSFactory(sk) + nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) + nodesPubKeys[i] = snowCtx.PublicKey toEngine := make(chan common.Message, 1) db := memdb.New() @@ -242,6 +262,8 @@ var _ = ginkgo.BeforeSuite(func() { hd, err = v.CreateHandlers(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) + emissions[i] = emission.GetEmission() + hjsonRPCServer := httptest.NewServer(hd[hrpc.JSONRPCEndpoint]) njsonRPCServer := httptest.NewServer(hd[nrpc.JSONRPCEndpoint]) webSocketServer := httptest.NewServer(hd[hrpc.WebSocketEndpoint]) @@ -287,6 +309,8 @@ var _ = ginkgo.BeforeSuite(func() { } blocks = []snowman.Block{} + setEmissionValidators() + app.instances = instances color.Blue("created %d VMs", vms) }) @@ -1549,6 +1573,442 @@ var _ = ginkgo.Describe("[Tx Processing]", func() { }) }) +var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { + ginkgo.FIt("Setup and get initial staked validators", func() { + height = 0 + withdraw0Priv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) + + delegatePriv, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) + delegateFactory = auth.NewED25519Factory(delegatePriv) + + validators, err := instances[3].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) + + ginkgo.FIt("Funding node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: nodesAddresses[3], + Asset: ids.Empty, + Value: 200_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) + + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) + }) + + ginkgo.FIt("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() + stakeStartBlock := currentBlockHeight + 2 + stakeEndBlock := currentBlockHeight + 100 + delegationFeeRate := 50 + + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartBlock: stakeStartBlock, + StakeEndBlock: stakeEndBlock, + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, + } + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[3].Sign(stakeInfoBytes) + gomega.Ω(err).Should(gomega.BeNil()) + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[3], + ) + gomega.Ω(err).Should(gomega.BeNil()) + + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + + // check if gossip/ new state happens + _, err = instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + + emissionInstance := emissions[3] + currentValidators := emissionInstance.GetAllValidators(context.TODO()) + gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + fmt.Println(stakedValidator) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + + validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] + gomega.Ω(exists).To(gomega.Equal(true)) + + // check when it becomes active ? + gomega.Ω(validator.IsActive).To(gomega.Equal(false)) + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + + validators, err := instances[4].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + + }) + + ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) + + ginkgo.FIt("Get validator staked amount after staking using node 0 cli", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) + + ginkgo.FIt("Get staked validators", func() { + validators, err := instances[4].ncli.StakedValidators(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) + }) + + ginkgo.FIt("Transfer NAI to delegate user", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) + + ginkgo.FIt("Delegate user stake to node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.DelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + fmt.Printf("delegate stake to node 3 %d", height) + + blk := blocks[height] + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + height++ + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) + + // TODO: GetUserStakeFromState is returning an empty value + // TODO: transactions are played twice because of Verify and Accept (block is already processed) + + /* + ginkgo.FIt("Get user stake before claim", func() { + for _, inst := range instances { + color.Blue("checking %q", inst.nodeID) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + + } + }) + + ginkgo.It("Claim delegation stake rewards from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) + + ginkgo.It("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) + + ginkgo.It("Undelegate user stake from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) + + ginkgo.It("Claim validator node 0 stake reward", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + }) + + ginkgo.It("Withdraw validator node 0 stake", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rwithdraw0, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + }) + + ginkgo.It("Get staked validators after staking withdraw ", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) + */ +}) + func expectBlk(i instance) func(bool) []*chain.Result { ctx := context.TODO() @@ -1652,3 +2112,33 @@ func (*appSender) SendCrossChainAppRequest(context.Context, ids.ID, uint32, []by func (*appSender) SendCrossChainAppResponse(context.Context, ids.ID, uint32, []byte) error { return nil } + +func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { + blk, err := vm.ParseBlock(context.Background(), block.Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk.Verify(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + err = vm.SetPreference(context.Background(), blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + err = blk.Accept(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) +} + +func setEmissionValidators() { + currentValidators := make([]*emission.Validator, 0, len(instances)) + for i, inst := range instances { + val := emission.Validator{ + NodeID: inst.nodeID, + PublicKey: bls.PublicKeyToBytes(nodesPubKeys[i]), + } + currentValidators = append(currentValidators, &val) + } + fmt.Println(len(currentValidators)) + for i := range instances { + fmt.Println(emissions[i]) + emissions[i].(*emission.Manual).CurrentValidators = currentValidators + } +} diff --git a/tests/integration/test_new_actions.go b/tests/integration/new_actions_test.go.separate similarity index 78% rename from tests/integration/test_new_actions.go rename to tests/integration/new_actions_test.go.separate index ae14336..7776eed 100644 --- a/tests/integration/test_new_actions.go +++ b/tests/integration/new_actions_test.go.separate @@ -7,13 +7,11 @@ import ( "context" "encoding/hex" "encoding/json" - "errors" "flag" "fmt" "net/http" "net/http/httptest" "os" - "testing" "time" "github.com/ava-labs/avalanchego/api/metrics" @@ -23,11 +21,9 @@ import ( "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/fatih/color" ginkgo "github.com/onsi/ginkgo/v2" @@ -49,11 +45,6 @@ import ( nrpc "github.com/nuklai/nuklaivm/rpc" ) -var ( - logFactory logging.Factory - log logging.Logger -) - func init() { logFactory = logging.NewFactory(logging.Config{ DisplayLevel: logging.Debug, @@ -65,17 +56,6 @@ func init() { log = l } -func TestIntegration(t *testing.T) { - gomega.RegisterFailHandler(ginkgo.Fail) - ginkgo.RunSpecs(t, "nuklaivm integration test suites") -} - -var ( - requestTimeout time.Duration - vms int - app *appSender -) - func init() { flag.DurationVar( &requestTimeout, @@ -92,42 +72,9 @@ func init() { } var ( - priv ed25519.PrivateKey - factory *auth.ED25519Factory - rsender codec.Address - sender string - - priv2 ed25519.PrivateKey - factory2 *auth.ED25519Factory - rsender2 codec.Address - sender2 string - - asset1 []byte - asset1Symbol []byte - asset1Decimals uint8 - asset1ID ids.ID - asset2 []byte - asset2Symbol []byte - asset2Decimals uint8 - asset2ID ids.ID - asset3 []byte - asset3Symbol []byte - asset3Decimals uint8 - asset3ID ids.ID - - // when used with embedded VMs - genesisBytes []byte - instances []instance - blocks []snowman.Block - - networkID uint32 - gen *genesis.Genesis - withdraw0 string - withdraw1 string delegate string rwithdraw0 codec.Address - rwithdraw1 codec.Address rdelegate codec.Address delegateFactory *auth.ED25519Factory nodesFactories []*auth.BLSFactory @@ -137,18 +84,6 @@ var ( height int ) -type instance struct { - chainID ids.ID - nodeID ids.NodeID - vm *vm.VM - toEngine chan common.Message - JSONRPCServer *httptest.Server - NuklaiJSONRPCServer *httptest.Server - WebSocketServer *httptest.Server - hcli *hrpc.JSONRPCClient // clients for embedded VMs - ncli *nrpc.JSONRPCClient -} - var _ = ginkgo.BeforeSuite(func() { log.Info("VMID", zap.Stringer("id", nconsts.ID)) gomega.Ω(vms).Should(gomega.BeNumerically(">", 1)) @@ -214,7 +149,6 @@ var _ = ginkgo.BeforeSuite(func() { subnetID := ids.GenerateTestID() chainID := ids.GenerateTestID() - app = &appSender{} for i := range instances { nodeID := ids.GenerateTestNodeID() sk, err := bls.NewSecretKey() @@ -332,11 +266,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - withdraw1Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw1 = auth.NewED25519Address(withdraw1Priv.PublicKey()) - withdraw1 = codec.MustAddressBech32(nconsts.HRP, rwithdraw1) - delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) @@ -765,110 +694,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { */ }) -func expectBlk(i instance) func(bool) []*chain.Result { - ctx := context.TODO() - - // manually signal ready - gomega.Ω(i.vm.Builder().Force(ctx)).To(gomega.BeNil()) - // manually ack ready sig as in engine - <-i.toEngine - - blk, err := i.vm.BuildBlock(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) - - gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = i.vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - return func(add bool) []*chain.Result { - gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - - if add { - blocks = append(blocks, blk) - } - - lastAccepted, err := i.vm.LastAccepted(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - return blk.(*chain.StatelessBlock).Results() - } -} - -// TODO: unify with expectBlk -func expectBlkWithContext(i instance) func(bool) []*chain.Result { - ctx := context.TODO() - - // manually signal ready - gomega.Ω(i.vm.Builder().Force(ctx)).To(gomega.BeNil()) - // manually ack ready sig as in engine - <-i.toEngine - - bctx := &block.Context{PChainHeight: 1} - blk, err := i.vm.BuildBlockWithContext(ctx, bctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) - cblk := blk.(block.WithVerifyContext) - - gomega.Ω(cblk.VerifyWithContext(ctx, bctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = i.vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - return func(add bool) []*chain.Result { - gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - - if add { - blocks = append(blocks, blk) - } - - lastAccepted, err := i.vm.LastAccepted(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - return blk.(*chain.StatelessBlock).Results() - } -} - -var _ common.AppSender = &appSender{} - -type appSender struct { - next int - instances []instance -} - -func (app *appSender) SendAppGossip(ctx context.Context, appGossipBytes []byte) error { - n := len(app.instances) - sender := app.instances[app.next].nodeID - app.next++ - app.next %= n - return app.instances[app.next].vm.AppGossip(ctx, sender, appGossipBytes) -} - -func (*appSender) SendAppRequest(context.Context, set.Set[ids.NodeID], uint32, []byte) error { - return nil -} - -func (*appSender) SendAppResponse(context.Context, ids.NodeID, uint32, []byte) error { - return nil -} - -func (*appSender) SendAppGossipSpecific(context.Context, set.Set[ids.NodeID], []byte) error { - return nil -} - -func (*appSender) SendCrossChainAppRequest(context.Context, ids.ID, uint32, []byte) error { - return nil -} - -func (*appSender) SendCrossChainAppResponse(context.Context, ids.ID, uint32, []byte) error { - return nil -} - func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { blk, err := vm.ParseBlock(context.Background(), block.Bytes()) gomega.Ω(err).Should(gomega.BeNil()) @@ -883,71 +708,6 @@ func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { gomega.Ω(err).Should(gomega.BeNil()) } -func ImportBlockToInstance2(vm *vm.VM, block snowman.Block) { - blk, err := vm.ParseBlock(context.Background(), block.Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - - // gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - // err = vm.SetPreference(context.Background(), blk.ID()) - // gomega.Ω(err).To(gomega.BeNil()) - - // sblk := blk.(*chain.StatelessBlock) - // sblkt := sblk.Timestamp().UnixMilli() - // tx := blk.(*chain.StatelessBlock).Txs[0] - // ok, err := sblk.IsRepeat(ctx, vm.Rules(sblkt).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), true) - // gomega.Ω(err).Should(gomega.BeNil()) - // gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - err = blk.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) -} - -func produceBlock(i *instance) (*chain.StatelessBlock, func()) { - ctx := context.TODO() - - blk, err := i.vm.BuildBlock(ctx) - if errors.Is(err, chain.ErrNoTxs) { - return nil, nil - } - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(blk).To(gomega.Not(gomega.BeNil())) - - gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = i.vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - return blk.(*chain.StatelessBlock), func() { - gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - - lastAccepted, err := i.vm.LastAccepted(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - } -} - -func addBlock(i *instance, blk *chain.StatelessBlock) func() { - ctx := context.TODO() - // start := time.Now() - tblk, err := i.vm.ParseBlock(ctx, blk.Bytes()) - // i.parse = append(i.parse, time.Since(start).Seconds()) - gomega.Ω(err).Should(gomega.BeNil()) - // start = time.Now() - gomega.Ω(tblk.Verify(ctx)).Should(gomega.BeNil()) - // i.verify = append(i.verify, time.Since(start).Seconds()) - // blk.MarkAccepted(context.Background()) - // err = i.vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - return func() { - // start = time.Now() - gomega.Ω(blk.Accept(ctx)).Should(gomega.BeNil()) - // i.accept = append(i.accept, time.Since(start).Seconds()) - } -} - func setEmissionValidators() { currentValidators := make([]*emission.Validator, 0, len(instances)) for i, inst := range instances { From 84d536df35c1626b2eed2aa773cec50629d6f184 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:27:24 +0100 Subject: [PATCH 63/78] remove println --- actions/register_validator_stake.go | 2 -- controller/controller.go | 9 --------- storage/storage.go | 20 +++++++++++++++++--- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/actions/register_validator_stake.go b/actions/register_validator_stake.go index 1184dcc..e011190 100644 --- a/actions/register_validator_stake.go +++ b/actions/register_validator_stake.go @@ -75,7 +75,6 @@ func (r *RegisterValidatorStake) Execute( // Get the emission instance emissionInstance := emission.GetEmission() - currentValidators := emissionInstance.GetAllValidators(ctx) var nodePublicKey *bls.PublicKey for _, validator := range currentValidators { @@ -90,7 +89,6 @@ func (r *RegisterValidatorStake) Execute( break } } - if !isValidatorOwner { return false, RegisterValidatorStakeComputeUnits, OutputUnauthorized, nil, nil } diff --git a/controller/controller.go b/controller/controller.go index cd6c25f..af41961 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -134,7 +134,6 @@ func (c *Controller) Initialize( return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err } - fmt.Println("-------------CONTROLLER/CONTROLLER.GO %b", c.config) if c.config.TestMode { c.inner.Logger().Info("running build and gossip in test mode") build = builder.NewManual(inner) @@ -191,9 +190,6 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er return err } } - fmt.Println("Controller Accepted") - fmt.Println(result.Success) - fmt.Println(tx.Action.GetTypeID()) totalFee += result.Fee if result.Success { switch action := tx.Action.(type) { @@ -219,8 +215,6 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er c.metrics.registerValidatorStake.Inc() case *actions.ClaimValidatorStakeRewards: rewardResult, err := actions.UnmarshalClaimRewardsResult(result.Output) - fmt.Println("reward result") - fmt.Println(rewardResult) if err != nil { // This should never happen return err @@ -240,14 +234,11 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er c.metrics.claimStakingRewards.Inc() c.metrics.withdrawValidatorStake.Inc() case *actions.DelegateUserStake: - fmt.Println("Controller accepted delegate user stake") // panic("hello") c.metrics.delegatorStakeAmount.Add(float64(action.StakedAmount)) c.metrics.delegateUserStake.Inc() case *actions.ClaimDelegationStakeRewards: rewardResult, err := actions.UnmarshalClaimRewardsResult(result.Output) - fmt.Println("reward result") - fmt.Println(rewardResult) if err != nil { // This should never happen return err diff --git a/storage/storage.go b/storage/storage.go index c567e7b..00491a4 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -565,6 +565,10 @@ func GetRegisterValidatorStakeFromState( error, ) { values, errs := f(ctx, [][]byte{RegisterValidatorStakeKey(nodeID)}) + fmt.Println("GetRegisterValidatorStakeFromState") + fmt.Println(nodeID) + fmt.Println(values) + fmt.Println(errs[0]) return innerGetRegisterValidatorStake(values[0], errs[0]) } @@ -645,7 +649,7 @@ func SetDelegateUserStake( copy(v[offset:], rewardAddress[:]) offset += codec.AddressLen copy(v[offset:], owner[:]) - + fmt.Println("SetDelegateUserStake") return mu.Insert(ctx, key, v) } @@ -662,6 +666,9 @@ func GetDelegateUserStake( error, ) { key := DelegateUserStakeKey(owner, nodeID) + fmt.Println("GetDelegateUserStake") + fmt.Println(codec.MustAddressBech32(nconsts.HRP, owner)) + fmt.Println(nodeID) v, err := im.GetValue(ctx, key) return innerGetDelegateUserStake(v, err) } @@ -680,6 +687,11 @@ func GetDelegateUserStakeFromState( error, ) { values, errs := f(ctx, [][]byte{DelegateUserStakeKey(owner, nodeID)}) + fmt.Println("GetDelegateUserStakeFromState") + fmt.Println(codec.MustAddressBech32(nconsts.HRP, owner)) + fmt.Println(nodeID) + fmt.Println(values) + fmt.Println(errs[0]) return innerGetDelegateUserStake(values[0], errs[0]) } @@ -692,12 +704,14 @@ func innerGetDelegateUserStake(v []byte, err error) ( error, ) { if errors.Is(err, database.ErrNotFound) { + fmt.Println("innerGetDelegateUserStake-0") return false, 0, 0, codec.Address{}, codec.Address{}, nil } + fmt.Println("innerGetDelegateUserStake-1") if err != nil { return false, 0, 0, codec.Address{}, codec.Address{}, nil } - + fmt.Println("innerGetDelegateUserStake-2") offset := 0 stakeStartBlock := binary.BigEndian.Uint64(v[offset : offset+hconsts.Uint64Len]) @@ -710,7 +724,7 @@ func innerGetDelegateUserStake(v []byte, err error) ( offset += codec.AddressLen var ownerAddress codec.Address copy(ownerAddress[:], v[offset:offset+codec.AddressLen]) - + fmt.Println("innerGetDelegateUserStake-3") return true, stakeStartBlock, stakedAmount, rewardAddress, ownerAddress, nil } From cc7220841995ebd24bc53b5ac7cc821235629e5f Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:34:16 +0100 Subject: [PATCH 64/78] fmt --- actions/register_validator_stake.go | 1 + controller/controller.go | 1 - storage/storage.go | 12 ------------ 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/actions/register_validator_stake.go b/actions/register_validator_stake.go index e011190..ba03335 100644 --- a/actions/register_validator_stake.go +++ b/actions/register_validator_stake.go @@ -92,6 +92,7 @@ func (r *RegisterValidatorStake) Execute( if !isValidatorOwner { return false, RegisterValidatorStakeComputeUnits, OutputUnauthorized, nil, nil } + // Unmarshal the stake info stakeInfo, err := UnmarshalValidatorStakeInfo(r.StakeInfo) if err != nil { diff --git a/controller/controller.go b/controller/controller.go index af41961..25e8b22 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -234,7 +234,6 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er c.metrics.claimStakingRewards.Inc() c.metrics.withdrawValidatorStake.Inc() case *actions.DelegateUserStake: - // panic("hello") c.metrics.delegatorStakeAmount.Add(float64(action.StakedAmount)) c.metrics.delegateUserStake.Inc() case *actions.ClaimDelegationStakeRewards: diff --git a/storage/storage.go b/storage/storage.go index 00491a4..9ab5598 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -666,9 +666,6 @@ func GetDelegateUserStake( error, ) { key := DelegateUserStakeKey(owner, nodeID) - fmt.Println("GetDelegateUserStake") - fmt.Println(codec.MustAddressBech32(nconsts.HRP, owner)) - fmt.Println(nodeID) v, err := im.GetValue(ctx, key) return innerGetDelegateUserStake(v, err) } @@ -687,11 +684,6 @@ func GetDelegateUserStakeFromState( error, ) { values, errs := f(ctx, [][]byte{DelegateUserStakeKey(owner, nodeID)}) - fmt.Println("GetDelegateUserStakeFromState") - fmt.Println(codec.MustAddressBech32(nconsts.HRP, owner)) - fmt.Println(nodeID) - fmt.Println(values) - fmt.Println(errs[0]) return innerGetDelegateUserStake(values[0], errs[0]) } @@ -704,14 +696,11 @@ func innerGetDelegateUserStake(v []byte, err error) ( error, ) { if errors.Is(err, database.ErrNotFound) { - fmt.Println("innerGetDelegateUserStake-0") return false, 0, 0, codec.Address{}, codec.Address{}, nil } - fmt.Println("innerGetDelegateUserStake-1") if err != nil { return false, 0, 0, codec.Address{}, codec.Address{}, nil } - fmt.Println("innerGetDelegateUserStake-2") offset := 0 stakeStartBlock := binary.BigEndian.Uint64(v[offset : offset+hconsts.Uint64Len]) @@ -724,7 +713,6 @@ func innerGetDelegateUserStake(v []byte, err error) ( offset += codec.AddressLen var ownerAddress codec.Address copy(ownerAddress[:], v[offset:offset+codec.AddressLen]) - fmt.Println("innerGetDelegateUserStake-3") return true, stakeStartBlock, stakedAmount, rewardAddress, ownerAddress, nil } From 6ac613b133b83ad91b9901f8f0033619349daace Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:46:24 +0100 Subject: [PATCH 65/78] space --- storage/storage.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/storage/storage.go b/storage/storage.go index 9ab5598..3542bce 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -565,10 +565,6 @@ func GetRegisterValidatorStakeFromState( error, ) { values, errs := f(ctx, [][]byte{RegisterValidatorStakeKey(nodeID)}) - fmt.Println("GetRegisterValidatorStakeFromState") - fmt.Println(nodeID) - fmt.Println(values) - fmt.Println(errs[0]) return innerGetRegisterValidatorStake(values[0], errs[0]) } @@ -649,7 +645,6 @@ func SetDelegateUserStake( copy(v[offset:], rewardAddress[:]) offset += codec.AddressLen copy(v[offset:], owner[:]) - fmt.Println("SetDelegateUserStake") return mu.Insert(ctx, key, v) } @@ -701,6 +696,7 @@ func innerGetDelegateUserStake(v []byte, err error) ( if err != nil { return false, 0, 0, codec.Address{}, codec.Address{}, nil } + offset := 0 stakeStartBlock := binary.BigEndian.Uint64(v[offset : offset+hconsts.Uint64Len]) @@ -713,6 +709,7 @@ func innerGetDelegateUserStake(v []byte, err error) ( offset += codec.AddressLen var ownerAddress codec.Address copy(ownerAddress[:], v[offset:offset+codec.AddressLen]) + return true, stakeStartBlock, stakedAmount, rewardAddress, ownerAddress, nil } From 5d5800d1b47b0948ea023542591e18030495b797 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:48:31 +0100 Subject: [PATCH 66/78] space --- storage/storage.go | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/storage.go b/storage/storage.go index 3542bce..c567e7b 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -645,6 +645,7 @@ func SetDelegateUserStake( copy(v[offset:], rewardAddress[:]) offset += codec.AddressLen copy(v[offset:], owner[:]) + return mu.Insert(ctx, key, v) } From 6065476966ee43327ef050dd2f69cea694032755 Mon Sep 17 00:00:00 2001 From: najla Date: Tue, 7 May 2024 17:56:59 +0100 Subject: [PATCH 67/78] println --- tests/e2e/e2e_test.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 41e47a2..028424a 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -395,8 +395,6 @@ var _ = ginkgo.BeforeSuite(func() { gomega.Expect(err).Should(gomega.BeNil()) validatorSignerKey, err := cmd.LoadPrivateKey("bls", fmt.Sprintf("%s/signer.key", destDir)) - fmt.Println("VALIDATOR SIGNER KEY") - fmt.Println(validatorSignerKey) gomega.Expect(err).Should(gomega.BeNil()) nodesAddresses[i] = validatorSignerKey.Address sk, err := bls.PrivateKeyFromBytes(validatorSignerKey.Bytes) @@ -1629,7 +1627,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }, nodesFactories[0], ) - fmt.Println(err) gomega.Ω(err).Should(gomega.BeNil()) balance, err := instancesA[0].ncli.Balance(context.Background(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), ids.Empty) @@ -1784,7 +1781,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("Claim delegation stake rewards from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Println(balanceBefore) // wait for blocks otherwise reward = 0 and error on UnpackUint64 while unmarshalling the data time.Sleep(1 * time.Minute) @@ -1824,7 +1820,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } balanceAfter, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) - fmt.Println(balanceAfter) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } @@ -1833,7 +1828,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("Undelegate user stake from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) - fmt.Println(balanceBefore) gomega.Ω(err).Should(gomega.BeNil()) parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1924,7 +1918,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("Claim node 0 stake reward", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), withdraw0, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - fmt.Println(balanceBefore) gomega.Ω(balanceBefore).Should(gomega.Equal(uint64(100_000_000_000))) parser, err := instancesA[0].ncli.Parser(context.Background()) @@ -1962,7 +1955,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } balanceAfter, err := inst.ncli.Balance(context.Background(), withdraw0, ids.Empty) - fmt.Println(balanceAfter) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } @@ -1972,10 +1964,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("Withdraw validator node 0 stake", func() { for { currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) - fmt.Println("CURRENT BLOCK HEIGHT") - fmt.Println(currentBlockHeight) - fmt.Println("STAKE END BLOCK") - fmt.Println(stakeEndBlock) if stakeEndBlock < currentBlockHeight { break } From 46c73dad3ea0dbf0d9c91a6d78619673c2185836 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 13:48:57 +0100 Subject: [PATCH 68/78] update manual --- emission/manual.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/emission/manual.go b/emission/manual.go index 819db71..c049ef4 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -260,10 +260,12 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add if !exists { return ErrValidatorNotFound } - // Check if the delegator was already staked ERROR HERE ? + + // Check if the delegator was already staked if _, exists := validator.delegatorsLastClaim[delegatorAddress]; exists { return ErrDelegatorAlreadyStaked } + // Update the validator's stake validator.DelegatedAmount += stakeAmount @@ -275,7 +277,7 @@ func (e *Manual) DelegateUserStake(nodeID ids.NodeID, delegatorAddress codec.Add } // Update the delegator's stake - validator.delegatorsLastClaim[delegatorAddress] = e.GetLastAcceptedBlockHeight() + validator.delegatorsLastClaim[delegatorAddress] = stakeStartBlock return nil } @@ -390,7 +392,7 @@ func (e *Manual) MintNewNAI() uint64 { // Distribute rewards based on stake proportion for _, validator := range e.validators { lastBlockHeight := e.GetLastAcceptedBlockHeight() - // Mark validator active based on if stakeStartTime has started + // Mark validator active based on if stakeStartBlock has started if lastBlockHeight > validator.stakeStartBlock { validator.IsActive = true e.TotalStaked += (validator.StakedAmount + validator.DelegatedAmount) @@ -398,7 +400,7 @@ func (e *Manual) MintNewNAI() uint64 { if !validator.IsActive { continue } - // Mark validator inactive based on if stakeEndTime has ended + // Mark validator inactive based on if stakeEndBlock has ended if lastBlockHeight > validator.stakeEndBlock { validator.IsActive = false e.TotalStaked -= (validator.StakedAmount + validator.DelegatedAmount) @@ -464,7 +466,7 @@ func (e *Manual) DistributeFees(fee uint64) { // Distribute fees based on stake proportion for _, validator := range e.validators { lastBlockHeight := e.GetLastAcceptedBlockHeight() - // Mark validator active based on if stakeStartTime has started + // Mark validator active based on if stakeStartBlock has started if lastBlockHeight > validator.stakeStartBlock { validator.IsActive = true e.TotalStaked += (validator.StakedAmount + validator.DelegatedAmount) @@ -472,7 +474,7 @@ func (e *Manual) DistributeFees(fee uint64) { if !validator.IsActive { continue } - // Mark validator inactive based on if stakeEndTime has ended + // Mark validator inactive based on if stakeEndBlock has ended if lastBlockHeight > validator.stakeEndBlock { validator.IsActive = false e.TotalStaked -= (validator.StakedAmount + validator.DelegatedAmount) From 56e5316e6cdacc24098e4c8ee5b024857ae653ab Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 14:16:24 +0100 Subject: [PATCH 69/78] integration tests pass in one file --- tests/integration/integration_test.go | 2872 +++++++++++++------------ 1 file changed, 1438 insertions(+), 1434 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index cae8471..1b43f74 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -349,1664 +349,1668 @@ var _ = ginkgo.Describe("[Network]", func() { }) }) -var _ = ginkgo.Describe("[Tx Processing]", func() { - ginkgo.It("get currently accepted block ID", func() { - for _, inst := range instances { - hcli := inst.hcli - _, _, _, err := hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - } - }) - - var transferTxRoot *chain.Transaction - ginkgo.It("Gossip TransferTx to a different node", func() { - ginkgo.By("issue TransferTx", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 100_000, // must be more than StateLockup - }, - factory, - ) - transferTxRoot = transferTx - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) - }) - - ginkgo.By("skip duplicate", func() { - _, err := instances[0].hcli.SubmitTx( - context.Background(), - transferTxRoot.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("send gossip from node 0 to 1", func() { - err := instances[0].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - }) - - ginkgo.By("skip invalid time", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: 0, - MaxFee: 1000, - }, - nil, - &actions.Transfer{ - To: rsender2, - Value: 110, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // 0 timestamp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { - _, err := instances[0].hcli.SubmitTx( - context.Background(), - transferTxRoot.Bytes(), - ) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - }) - - ginkgo.By("receive gossip in the node 1, and signal block build", func() { - gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - <-instances[1].toEngine - }) - - ginkgo.By("build block in the node 1", func() { - ctx := context.TODO() - blk, err := instances[1].vm.BuildBlock(ctx) - gomega.Ω(err).To(gomega.BeNil()) - - gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - - err = instances[1].vm.SetPreference(ctx, blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) - blocks = append(blocks, blk) - - lastAccepted, err := instances[1].vm.LastAccepted(ctx) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) - - results := blk.(*chain.StatelessBlock).Results() - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(results[0].Output).Should(gomega.BeNil()) - - // Unit explanation - // - // bandwidth: tx size - // compute: 5 for signature, 1 for base, 1 for transfer - // read: 2 keys reads, 1 had 0 chunks - // allocate: 1 key created - // write: 1 key modified, 1 key new - transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} - gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) - - // Fee explanation - // - // Multiply all unit consumption by 1 and sum - gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) - }) - - ginkgo.By("ensure balance is updated", func() { - balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance).To(gomega.Equal(uint64(9899703))) - balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) - }) - }) - - ginkgo.It("ensure multiple txs work ", func() { - ginkgo.By("transfer funds again", func() { - parser, err := instances[1].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 101, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept := expectBlk(instances[1]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) - gomega.Ω(err).To(gomega.BeNil()) - gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) - }) - }) - - ginkgo.It("Test processing block handling", func() { - var accept, accept2 func(bool) []*chain.Result - - ginkgo.By("create processing tip", func() { - parser, err := instances[1].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 200, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept = expectBlk(instances[1]) - - submit, _, _, err = instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 201, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - time.Sleep(2 * time.Second) // for replay test - accept2 = expectBlk(instances[1]) - }) - - ginkgo.By("clear processing tip", func() { - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - results = accept2(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - }) - }) - - ginkgo.It("ensure mempool works", func() { - ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { - parser, err := instances[1].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[1].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rsender2, - Value: 203, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - err = instances[1].vm.Gossiper().Force(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - - // mempool in 0 should be 1 (old amount), since gossip/submit failed - gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - }) - }) - - ginkgo.It("ensure unprocessed tip and replay protection works", func() { - ginkgo.By("import accepted blocks to instance 2", func() { - ctx := context.TODO() - - gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) - - n := instances[2] - blk1, err := n.vm.ParseBlock(ctx, blocks[0].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk1.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Parse tip - blk2, err := n.vm.ParseBlock(ctx, blocks[1].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - blk3, err := n.vm.ParseBlock(ctx, blocks[2].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - - // Verify tip - err = blk2.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk3.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Check if tx from old block would be considered a repeat on processing tip - tx := blk2.(*chain.StatelessBlock).Txs[0] - sblk3 := blk3.(*chain.StatelessBlock) - sblk3t := sblk3.Timestamp().UnixMilli() - ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - - // Accept tip - err = blk1.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk2.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk3.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Parse another - blk4, err := n.vm.ParseBlock(ctx, blocks[3].Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk4.Verify(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk4.Accept(ctx) - gomega.Ω(err).Should(gomega.BeNil()) - - // Check if tx from old block would be considered a repeat on accepted tip - time.Sleep(2 * time.Second) - gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) - }) - }) - - ginkgo.It("processes valid index transactions (w/block listening)", func() { - // Clear previous txs on instance 0 - accept := expectBlk(instances[0]) - accept(false) // don't care about results - - // Subscribe to blocks - hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) +var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { + ginkgo.It("Setup and get initial staked validators", func() { + height = 0 + withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) - - // Wait for message to be sent - time.Sleep(2 * pubsub.MaxMessageWait) + rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) + withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - // Fetch balances - balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) + rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) + delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) + delegateFactory = auth.NewED25519Factory(delegatePriv) - // Send tx - other, err := ed25519.GeneratePrivateKey() + validators, err := instances[3].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - transfer := &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 1, - } + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) - parser, err := instances[0].ncli.Parser(context.Background()) + ginkgo.It("Funding node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, - transfer, + &actions.Transfer{ + To: nodesAddresses[3], + Asset: ids.Empty, + Value: 200_000_000_000, + }, factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - gomega.Ω(err).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results := accept(false) + accept := expectBlk(instances[3]) + results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // Read item from connection - blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) + gomega.Ω(len(blocks)).Should(gomega.Equal(1)) + + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) - tx := blk.Txs[0].Action.(*actions.Transfer) - gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) - gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) - gomega.Ω(lresults).Should(gomega.Equal(results)) - gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) - - // Check balance modifications are correct - balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + + // check if gossip/ new state happens + balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) + gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) - // Close connection when done - gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) }) - ginkgo.It("processes valid index transactions (w/streaming verification)", func() { - // Create streaming client - hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + ginkgo.It("Register validator stake node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) + currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() + stakeStartBlock := currentBlockHeight + 2 + stakeEndBlock := currentBlockHeight + 100 + delegationFeeRate := 50 - // Create tx - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - transfer := &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 1, + stakeInfo := &actions.ValidatorStakeInfo{ + NodeID: instances[3].nodeID.Bytes(), + StakeStartBlock: stakeStartBlock, + StakeEndBlock: stakeEndBlock, + StakedAmount: 100_000_000_000, + DelegationFeeRate: uint64(delegationFeeRate), + RewardAddress: rwithdraw0, } - parser, err := instances[0].ncli.Parser(context.Background()) + + stakeInfoBytes, err := stakeInfo.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + signature, err := nodesFactories[3].Sign(stakeInfoBytes) gomega.Ω(err).Should(gomega.BeNil()) - _, tx, _, err := instances[0].hcli.GenerateTransaction( + signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) + signature.Marshal(signaturePacker) + authSignature := signaturePacker.Bytes() + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, - transfer, - factory, + &actions.RegisterValidatorStake{ + StakeInfo: stakeInfoBytes, + AuthSignature: authSignature, + }, + nodesFactories[3], ) gomega.Ω(err).Should(gomega.BeNil()) - // Submit tx and accept block - gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) - // Wait for message to be sent - time.Sleep(2 * pubsub.MaxMessageWait) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - for instances[0].vm.Mempool().Len(context.TODO()) == 0 { - // We need to wait for mempool to be populated because issuance will - // return as soon as bytes are on the channel. - hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") - time.Sleep(500 * time.Millisecond) - } - gomega.Ω(err).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) + accept := expectBlk(instances[3]) + results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // Read decision from connection - txID, dErr, result, err := hcli.ListenTx(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(txID).Should(gomega.Equal(tx.ID())) - gomega.Ω(dErr).Should(gomega.BeNil()) - gomega.Ω(result.Success).Should(gomega.BeTrue()) - gomega.Ω(result).Should(gomega.Equal(results[0])) - - // Close connection when done - gomega.Ω(hcli.Close()).Should(gomega.BeNil()) - }) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - ginkgo.It("transfer an asset with a memo", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - Memo: []byte("hello"), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeTrue()) - }) + blk := blocks[height] + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - ginkgo.It("transfer an asset with large memo", func() { - other, err := ed25519.GeneratePrivateKey() + _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.Transfer{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - Memo: make([]byte, 1000), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) - }) - ginkgo.It("mint an asset that doesn't exist", func() { - other, err := ed25519.GeneratePrivateKey() + // check if gossip/ new state happens + _, err = instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - assetID := ids.GenerateTestID() - parser, err := instances[0].ncli.Parser(context.Background()) + + emissionInstance := emissions[3] + currentValidators := emissionInstance.GetAllValidators(context.TODO()) + gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) + stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) + fmt.Println(stakedValidator) + gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) + + validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] + gomega.Ω(exists).To(gomega.Equal(true)) + + // check when it becomes active ? + gomega.Ω(validator.IsActive).To(gomega.Equal(false)) + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: assetID, - Value: 10, - }, - factory, - ) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("asset missing")) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) + validators, err := instances[4].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeFalse()) - }) - - ginkgo.It("create a new asset (no metadata)", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.CreateAsset{ - Symbol: []byte("s0"), - Decimals: 0, - Metadata: nil, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - }) - - ginkgo.It("create a new asset (no symbol)", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1001, - }, - nil, - &actions.CreateAsset{ - Symbol: nil, - Decimals: 0, - Metadata: []byte("m"), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) - }) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) - ginkgo.It("create asset with too long of metadata", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.CreateAsset{ - Symbol: []byte("s0"), - Decimals: 0, - Metadata: make([]byte, actions.MaxMetadataSize*2), - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // too large) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) }) - ginkgo.It("create a new asset (simple metadata)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset1Symbol, - Decimals: asset1Decimals, - Metadata: asset1, - }, - factory, - ) + ginkgo.It("Get validator staked amount after node 3 validator staking", func() { + _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) - asset1ID = tx.ID() - balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + ginkgo.It("Get validator staked amount after staking using node 0 cli", func() { + _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) + }) - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + ginkgo.It("Get staked validators", func() { + validators, err := instances[4].ncli.StakedValidators(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(0))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) + gomega.Ω(len(validators)).Should(gomega.Equal(1)) }) - ginkgo.It("mint a new asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) + ginkgo.It("Transfer NAI to delegate user", func() { + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset1ID, - Value: 15, + &actions.Transfer{ + To: rdelegate, + Asset: ids.Empty, + Value: 100_000_000_000, }, factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(15))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(15))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) + blk := blocks[height] + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - ginkgo.It("mint asset from wrong owner", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: asset1ID, - Value: 10, - }, - factory2, - ) + balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("wrong owner")) + gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(15))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - ginkgo.It("burn new asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) + ginkgo.It("Delegate user stake to node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( + submit, _, _, err := instances[3].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.BurnAsset{ - Asset: asset1ID, - Value: 5, + &actions.DelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + StakedAmount: 30_000_000_000, + RewardAddress: rdelegate, }, - factory2, + delegateFactory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) + fmt.Printf("delegate stake to node 3 %d", height) - ginkgo.It("burn missing asset", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.BurnAsset{ - Asset: asset1ID, - Value: 10, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("invalid balance")) + blk := blocks[height] + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + height++ - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) - - ginkgo.It("rejects empty mint", func() { - other, err := ed25519.GeneratePrivateKey() + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Asset: asset1ID, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // bad codec) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) }) - ginkgo.It("reject max mint", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset1ID, - Value: hconsts.MaxUint64, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)). - Should(gomega.ContainSubstring("overflow")) + // TODO: GetUserStakeFromState is returning an empty value + // TODO: transactions are played twice because of Verify and Accept (block is already processed) + /* + ginkgo.FIt("Get user stake before claim", func() { + for _, inst := range instances { + color.Blue("checking %q", inst.nodeID) + + // Ensure all blocks processed + for { + _, h, _, err := inst.hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + if h > 0 { + break + } + time.Sleep(1 * time.Second) + } + _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + } + }) - exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) - gomega.Ω(metadata).Should(gomega.Equal(asset1)) - gomega.Ω(supply).Should(gomega.Equal(uint64(10))) - gomega.Ω(owner).Should(gomega.Equal(sender)) - gomega.Ω(warp).Should(gomega.BeFalse()) - }) + ginkgo.It("Claim delegation stake rewards from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimDelegationStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + UserStakeAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + + // test same block is accepted + lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + }) - ginkgo.It("rejects mint of native token", func() { - other, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.MintAsset{ - To: auth.NewED25519Address(other.PublicKey()), - Value: 10, - }, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // bad codec) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) - }) + ginkgo.It("Get user stake after claim", func() { + _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + }) - ginkgo.It("mints another new asset (to self)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset2Symbol, - Decimals: asset2Decimals, - Metadata: asset2, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - asset2ID = tx.ID() + ginkgo.It("Undelegate user stake from node 3", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.UndelegateUserStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rdelegate, + }, + delegateFactory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ + }) + + ginkgo.It("Claim validator node 0 stake reward", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ClaimValidatorStakeRewards{ + NodeID: instances[3].nodeID.Bytes(), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - submit, _, _, err = instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender, - Asset: asset2ID, - Value: 10, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results = accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - }) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - ginkgo.It("mints another new asset (to self) on another account", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.CreateAsset{ - Symbol: asset3Symbol, - Decimals: asset3Decimals, - Metadata: asset3, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - asset3ID = tx.ID() + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - submit, _, _, err = instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.MintAsset{ - To: rsender2, - Asset: asset3ID, - Value: 10, - }, - factory2, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept = expectBlk(instances[0]) - results = accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + }) - balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(10))) - }) + ginkgo.It("Withdraw validator node 0 stake", func() { + parser, err := instances[3].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[3].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.WithdrawValidatorStake{ + NodeID: instances[3].nodeID.Bytes(), + RewardAddress: rwithdraw0, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - ginkgo.It("import warp message with nil when expected", func() { - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - nil, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // empty warp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) - }) + accept := expectBlk(instances[3]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - ginkgo.It("import warp message empty", func() { - wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // empty warp) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) - }) + gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - ginkgo.It("import with wrong payload", func() { - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // invalid object) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) - }) + blk := blocks[height] + fmt.Println(blk.ID()) + ImportBlockToInstance(instances[4].vm, blk) + ImportBlockToInstance(instances[0].vm, blk) + ImportBlockToInstance(instances[2].vm, blk) + ImportBlockToInstance(instances[1].vm, blk) + height++ - ginkgo.It("import with invalid payload", func() { - wt := &actions.WarpTransfer{} - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - tx := chain.NewTx( - &chain.Base{ - ChainID: instances[0].chainID, - Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), - MaxFee: 1000, - }, - wm, - &actions.ImportAsset{}, - ) - // Must do manual construction to avoid `tx.Sign` error (would fail with - // invalid object) - msg, err := tx.Digest() - gomega.Ω(err).To(gomega.BeNil()) - auth, err := factory.Sign(msg) - gomega.Ω(err).To(gomega.BeNil()) - tx.Auth = auth - p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth - gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) - gomega.Ω(p.Err()).To(gomega.BeNil()) - _, err = instances[0].hcli.SubmitTx( - context.Background(), - p.Bytes(), - ) - gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) - }) + }) - ginkgo.It("import with wrong destination", func() { - wt := &actions.WarpTransfer{ - To: rsender, - Symbol: []byte("s"), - Decimals: 2, - Asset: ids.GenerateTestID(), - Value: 100, - Return: false, - Reward: 100, - TxID: ids.GenerateTestID(), - DestinationChainID: ids.GenerateTestID(), - } - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) - gomega.Ω(err).Should(gomega.BeNil()) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - wm, - &actions.ImportAsset{}, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + ginkgo.It("Get staked validators after staking withdraw ", func() { + validators, err := instances[0].ncli.StakedValidators(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(validators)).Should(gomega.Equal(0)) + }) - // Build block with no context (should fail) - gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) - <-instances[0].toEngine - blk, err := instances[0].vm.BuildBlock(context.TODO()) - gomega.Ω(err).To(gomega.Not(gomega.BeNil())) - gomega.Ω(blk).To(gomega.BeNil()) - - // Wait for mempool to be size 1 (txs are restored async) - for { - if instances[0].vm.Mempool().Len(context.Background()) > 0 { - break + }) */ + + var _ = ginkgo.Describe("[Tx Processing]", func() { + ginkgo.It("get currently accepted block ID", func() { + fmt.Println("block-beginning") + fmt.Println(blocks) + for _, inst := range instances { + hcli := inst.hcli + _, _, _, err := hcli.Accepted(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) } - log.Info("waiting for txs to be restored") - time.Sleep(100 * time.Millisecond) - } + }) - // Build block with context - accept := expectBlkWithContext(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) - }) + var transferTxRoot *chain.Transaction + ginkgo.It("Gossip TransferTx to a different node", func() { + ginkgo.By("issue TransferTx", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, transferTx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 100_000, // must be more than StateLockup + }, + factory, + ) + transferTxRoot = transferTx + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + gomega.Ω(instances[0].vm.Mempool().Len(context.Background())).Should(gomega.Equal(1)) + }) + + ginkgo.By("skip duplicate", func() { + _, err := instances[0].hcli.SubmitTx( + context.Background(), + transferTxRoot.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("send gossip from node 0 to 1", func() { + err := instances[0].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + }) + + ginkgo.By("skip invalid time", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: 0, + MaxFee: 1000, + }, + nil, + &actions.Transfer{ + To: rsender2, + Value: 110, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // 0 timestamp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("skip duplicate (after gossip, which shouldn't clear)", func() { + _, err := instances[0].hcli.SubmitTx( + context.Background(), + transferTxRoot.Bytes(), + ) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + }) + + ginkgo.By("receive gossip in the node 1, and signal block build", func() { + gomega.Ω(instances[1].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + <-instances[1].toEngine + }) + + ginkgo.By("build block in the node 1", func() { + ctx := context.TODO() + blk, err := instances[1].vm.BuildBlock(ctx) + gomega.Ω(err).To(gomega.BeNil()) + + gomega.Ω(blk.Verify(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) + + err = instances[1].vm.SetPreference(ctx, blk.ID()) + gomega.Ω(err).To(gomega.BeNil()) + + gomega.Ω(blk.Accept(ctx)).To(gomega.BeNil()) + gomega.Ω(blk.Status()).To(gomega.Equal(choices.Accepted)) + blocks = append(blocks, blk) + + lastAccepted, err := instances[1].vm.LastAccepted(ctx) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(lastAccepted).To(gomega.Equal(blk.ID())) + + results := blk.(*chain.StatelessBlock).Results() + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + gomega.Ω(results[0].Output).Should(gomega.BeNil()) + + // Unit explanation + // + // bandwidth: tx size + // compute: 5 for signature, 1 for base, 1 for transfer + // read: 2 keys reads, 1 had 0 chunks + // allocate: 1 key created + // write: 1 key modified, 1 key new + transferTxConsumed := chain.Dimensions{227, 7, 12, 25, 26} + gomega.Ω(results[0].Consumed).Should(gomega.Equal(transferTxConsumed)) + + // Fee explanation + // + // Multiply all unit consumption by 1 and sum + gomega.Ω(results[0].Fee).Should(gomega.Equal(uint64(297))) + }) + + ginkgo.By("ensure balance is updated", func() { + balance, err := instances[1].ncli.Balance(context.Background(), sender, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance).To(gomega.Equal(uint64(9999699999899109))) + balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance2).To(gomega.Equal(uint64(100000))) + }) + }) - ginkgo.It("export native asset", func() { - dest := ids.GenerateTestID() - loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(loan).Should(gomega.Equal(uint64(0))) + ginkgo.It("ensure multiple txs work ", func() { + ginkgo.By("transfer funds again", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 101, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept := expectBlk(instances[1]) + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + + balance2, err := instances[1].ncli.Balance(context.Background(), sender2, ids.Empty) + gomega.Ω(err).To(gomega.BeNil()) + gomega.Ω(balance2).To(gomega.Equal(uint64(100101))) + }) + }) - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, tx, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ExportAsset{ - To: rsender, - Asset: ids.Empty, - Value: 100, - Return: false, - Reward: 10, - Destination: dest, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeTrue()) - wt := &actions.WarpTransfer{ - To: rsender, - Symbol: []byte(nconsts.Symbol), - Decimals: nconsts.Decimals, - Asset: ids.Empty, - Value: 100, - Return: false, - Reward: 10, - TxID: tx.ID(), - DestinationChainID: dest, - } - wtb, err := wt.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) + ginkgo.It("Test processing block handling", func() { + var accept, accept2 func(bool) []*chain.Result - loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(loan).Should(gomega.Equal(uint64(110))) - }) + ginkgo.By("create processing tip", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 200, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept = expectBlk(instances[1]) + + submit, _, _, err = instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 201, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + time.Sleep(2 * time.Second) // for replay test + accept2 = expectBlk(instances[1]) + }) + + ginkgo.By("clear processing tip", func() { + results := accept(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + results = accept2(true) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + }) + }) - ginkgo.It("export native asset (invalid return)", func() { - parser, err := instances[0].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[0].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ExportAsset{ - To: rsender, - Asset: ids.Empty, - Value: 100, - Return: true, - Reward: 10, - Destination: ids.GenerateTestID(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[0]) - results := accept(false) - gomega.Ω(results).Should(gomega.HaveLen(1)) - result := results[0] - gomega.Ω(result.Success).Should(gomega.BeFalse()) - gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) - }) -}) + ginkgo.It("ensure mempool works", func() { + ginkgo.By("fail Gossip TransferTx to a stale node when missing previous blocks", func() { + parser, err := instances[1].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[1].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: rsender2, + Value: 203, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) -var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.FIt("Setup and get initial staked validators", func() { - height = 0 - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) - withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) + err = instances[1].vm.Gossiper().Force(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) - delegateFactory = auth.NewED25519Factory(delegatePriv) + // mempool in 0 should be 1 (old amount), since gossip/submit failed + gomega.Ω(instances[0].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + }) + }) - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) + ginkgo.It("ensure unprocessed tip and replay protection works", func() { + ginkgo.By("import accepted blocks to instance 2", func() { + fmt.Println("blocks") + fmt.Println(blocks) + ctx := context.TODO() - ginkgo.FIt("Funding node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: nodesAddresses[3], - Asset: ids.Empty, - Value: 200_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + n := instances[2] + blk1, err := n.vm.ParseBlock(ctx, blocks[4].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk1.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(blocks)).Should(gomega.Equal(1)) + // Parse tip + blk2, err := n.vm.ParseBlock(ctx, blocks[5].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + blk3, err := n.vm.ParseBlock(ctx, blocks[6].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + // Verify tip + err = blk2.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk3.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) + // Check if tx from old block would be considered a repeat on processing tip + tx := blk2.(*chain.StatelessBlock).Txs[0] + sblk3 := blk3.(*chain.StatelessBlock) + sblk3t := sblk3.Timestamp().UnixMilli() + ok, err := sblk3.IsRepeat(ctx, sblk3t-n.vm.Rules(sblk3t).GetValidityWindow(), []*chain.Transaction{tx}, set.NewBits(), false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(ok.Len()).Should(gomega.Equal(1)) - // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) + // Accept tip + err = blk1.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk2.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk3.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) - balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) - }) + // Parse another + blk4, err := n.vm.ParseBlock(ctx, blocks[7].Bytes()) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk4.Verify(ctx) + gomega.Ω(err).Should(gomega.BeNil()) + err = blk4.Accept(ctx) + gomega.Ω(err).Should(gomega.BeNil()) - ginkgo.FIt("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() - stakeStartBlock := currentBlockHeight + 2 - stakeEndBlock := currentBlockHeight + 100 - delegationFeeRate := 50 + // Check if tx from old block would be considered a repeat on accepted tip + time.Sleep(2 * time.Second) + gomega.Ω(n.vm.IsRepeat(ctx, []*chain.Transaction{tx}, set.NewBits(), false).Len()).Should(gomega.Equal(1)) + }) + }) - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartBlock: stakeStartBlock, - StakeEndBlock: stakeEndBlock, - StakedAmount: 100_000_000_000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } + ginkgo.It("processes valid index transactions (w/block listening)", func() { + // Clear previous txs on instance 0 + accept := expectBlk(instances[0]) + accept(false) // don't care about results - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := nodesFactories[3].Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - nodesFactories[3], - ) - gomega.Ω(err).Should(gomega.BeNil()) + // Subscribe to blocks + hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(hcli.RegisterBlocks()).Should(gomega.BeNil()) - _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) + // Wait for message to be sent + time.Sleep(2 * pubsub.MaxMessageWait) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + // Fetch balances + balance, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + // Send tx + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + transfer := &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 1, + } - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + transfer, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - blk := blocks[height] - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - // check if gossip/ new state happens - _, err = instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - emissionInstance := emissions[3] - currentValidators := emissionInstance.GetAllValidators(context.TODO()) - gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) - stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - fmt.Println(stakedValidator) - gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - - validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] - gomega.Ω(exists).To(gomega.Equal(true)) - - // check when it becomes active ? - gomega.Ω(validator.IsActive).To(gomega.Equal(false)) - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + gomega.Ω(err).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - validators, err := instances[4].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) + // Read item from connection + blk, lresults, prices, err := hcli.ListenBlock(context.TODO(), parser) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(len(blk.Txs)).Should(gomega.Equal(1)) + tx := blk.Txs[0].Action.(*actions.Transfer) + gomega.Ω(tx.Asset).To(gomega.Equal(ids.Empty)) + gomega.Ω(tx.Value).To(gomega.Equal(uint64(1))) + gomega.Ω(lresults).Should(gomega.Equal(results)) + gomega.Ω(prices).Should(gomega.Equal(chain.Dimensions{1, 1, 1, 1, 1})) + + // Check balance modifications are correct + balancea, err := instances[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(balancea + lresults[0].Fee + 1)) - }) + // Close connection when done + gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + }) - ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) + ginkgo.It("processes valid index transactions (w/streaming verification)", func() { + // Create streaming client + hcli, err := hrpc.NewWebSocketClient(instances[0].WebSocketServer.URL, hrpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize) + gomega.Ω(err).Should(gomega.BeNil()) - ginkgo.FIt("Get validator staked amount after staking using node 0 cli", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) + // Create tx + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + transfer := &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 1, + } + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + _, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + transfer, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) - ginkgo.FIt("Get staked validators", func() { - validators, err := instances[4].ncli.StakedValidators(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) + // Submit tx and accept block + gomega.Ω(hcli.RegisterTx(tx)).Should(gomega.BeNil()) - ginkgo.FIt("Transfer NAI to delegate user", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rdelegate, - Asset: ids.Empty, - Value: 100_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + // Wait for message to be sent + time.Sleep(2 * pubsub.MaxMessageWait) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + for instances[0].vm.Mempool().Len(context.TODO()) == 0 { + // We need to wait for mempool to be populated because issuance will + // return as soon as bytes are on the channel. + hutils.Outf("{{yellow}}waiting for mempool to return non-zero txs{{/}}\n") + time.Sleep(500 * time.Millisecond) + } + gomega.Ω(err).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + // Read decision from connection + txID, dErr, result, err := hcli.ListenTx(context.TODO()) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(txID).Should(gomega.Equal(tx.ID())) + gomega.Ω(dErr).Should(gomega.BeNil()) + gomega.Ω(result.Success).Should(gomega.BeTrue()) + gomega.Ω(result).Should(gomega.Equal(results[0])) - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + // Close connection when done + gomega.Ω(hcli.Close()).Should(gomega.BeNil()) + }) - balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) + ginkgo.It("transfer an asset with a memo", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + Memo: []byte("hello"), + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeTrue()) + }) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) + ginkgo.It("transfer an asset with large memo", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.Transfer{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + Memo: make([]byte, 1000), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + }) - ginkgo.FIt("Delegate user stake to node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.DelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + ginkgo.It("mint an asset that doesn't exist", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + assetID := ids.GenerateTestID() + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: assetID, + Value: 10, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("asset missing")) - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + exists, _, _, _, _, _, _, err := instances[0].ncli.Asset(context.TODO(), assetID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeFalse()) + }) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + ginkgo.It("create a new asset (no metadata)", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.CreateAsset{ + Symbol: []byte("s0"), + Decimals: 0, + Metadata: nil, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + }) - fmt.Printf("delegate stake to node 3 %d", height) + ginkgo.It("create a new asset (no symbol)", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1001, + }, + nil, + &actions.CreateAsset{ + Symbol: nil, + Decimals: 0, + Metadata: []byte("m"), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Bytes field is not populated")) + }) - blk := blocks[height] - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - height++ + ginkgo.It("create asset with too long of metadata", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.CreateAsset{ + Symbol: []byte("s0"), + Decimals: 0, + Metadata: make([]byte, actions.MaxMetadataSize*2), + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // too large) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("size is larger than limit")) + }) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) + ginkgo.It("create a new asset (simple metadata)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset1Symbol, + Decimals: asset1Decimals, + Metadata: asset1, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - // TODO: GetUserStakeFromState is returning an empty value - // TODO: transactions are played twice because of Verify and Accept (block is already processed) + asset1ID = tx.ID() + balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - /* - ginkgo.FIt("Get user stake before claim", func() { - for _, inst := range instances { - color.Blue("checking %q", inst.nodeID) + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(0))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) - } - _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) + ginkgo.It("mint a new asset", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender2, + Asset: asset1ID, + Value: 15, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - } + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(15))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) }) - ginkgo.It("Claim delegation stake rewards from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + ginkgo.It("mint asset from wrong owner", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( + submit, _, _, err := instances[0].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.ClaimDelegationStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - UserStakeAddress: rdelegate, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: asset1ID, + Value: 10, }, - delegateFactory, + factory2, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("wrong owner")) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(15))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) - accept := expectBlk(instances[3]) - results := accept(true) + ginkgo.It("burn new asset", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.BurnAsset{ + Asset: asset1ID, + Value: 5, + }, + factory2, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) + ginkgo.It("burn missing asset", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.BurnAsset{ + Asset: asset1ID, + Value: 10, + }, + factory, + ) gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("invalid balance")) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) }) - ginkgo.It("Get user stake after claim", func() { - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) + ginkgo.It("rejects empty mint", func() { + other, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Asset: asset1ID, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // bad codec) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("Uint64 field is not populated")) }) - ginkgo.It("Undelegate user stake from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + ginkgo.It("reject max mint", func() { + parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( + submit, _, _, err := instances[0].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.UndelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rdelegate, + &actions.MintAsset{ + To: rsender2, + Asset: asset1ID, + Value: hconsts.MaxUint64, }, - delegateFactory, + factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)). + Should(gomega.ContainSubstring("overflow")) + + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + balance, err = instances[0].ncli.Balance(context.TODO(), sender, asset1ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(0))) + + exists, symbol, decimals, metadata, supply, owner, warp, err := instances[0].ncli.Asset(context.TODO(), asset1ID, false) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(exists).Should(gomega.BeTrue()) + gomega.Ω(symbol).Should(gomega.Equal(asset1Symbol)) + gomega.Ω(decimals).Should(gomega.Equal(asset1Decimals)) + gomega.Ω(metadata).Should(gomega.Equal(asset1)) + gomega.Ω(supply).Should(gomega.Equal(uint64(10))) + gomega.Ω(owner).Should(gomega.Equal(sender)) + gomega.Ω(warp).Should(gomega.BeFalse()) + }) + + ginkgo.It("rejects mint of native token", func() { + other, err := ed25519.GeneratePrivateKey() + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.MintAsset{ + To: auth.NewED25519Address(other.PublicKey()), + Value: 10, + }, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // bad codec) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("ID field is not populated")) + }) - accept := expectBlk(instances[3]) - results := accept(true) + ginkgo.It("mints another new asset (to self)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.CreateAsset{ + Symbol: asset2Symbol, + Decimals: asset2Decimals, + Metadata: asset2, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + asset2ID = tx.ID() - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + submit, _, _, err = instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender, + Asset: asset2ID, + Value: 10, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results = accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + balance, err := instances[0].ncli.Balance(context.TODO(), sender, asset2ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) }) - ginkgo.It("Claim validator node 0 stake reward", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + ginkgo.It("mints another new asset (to self) on another account", func() { + parser, err := instances[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( + submit, tx, _, err := instances[0].hcli.GenerateTransaction( context.Background(), parser, nil, - &actions.ClaimValidatorStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), + &actions.CreateAsset{ + Symbol: asset3Symbol, + Decimals: asset3Decimals, + Metadata: asset3, }, - factory, + factory2, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + asset3ID = tx.ID() - accept := expectBlk(instances[3]) - results := accept(true) + submit, _, _, err = instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.MintAsset{ + To: rsender2, + Asset: asset3ID, + Value: 10, + }, + factory2, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept = expectBlk(instances[0]) + results = accept(false) gomega.Ω(results).Should(gomega.HaveLen(1)) gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + balance, err := instances[0].ncli.Balance(context.TODO(), sender2, asset3ID) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(balance).Should(gomega.Equal(uint64(10))) + }) + + ginkgo.It("import warp message with nil when expected", func() { + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + nil, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // empty warp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("expected warp message")) + }) + + ginkgo.It("import warp message empty", func() { + wm, err := warp.NewMessage(&warp.UnsignedMessage{}, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // empty warp) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("empty warp payload")) + }) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + ginkgo.It("import with wrong payload", func() { + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, []byte("hello")) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // invalid object) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("insufficient length for input")) + }) - gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) + ginkgo.It("import with invalid payload", func() { + wt := &actions.WarpTransfer{} + wtb, err := wt.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + tx := chain.NewTx( + &chain.Base{ + ChainID: instances[0].chainID, + Timestamp: hutils.UnixRMilli(-1, 5*hconsts.MillisecondsPerSecond), + MaxFee: 1000, + }, + wm, + &actions.ImportAsset{}, + ) + // Must do manual construction to avoid `tx.Sign` error (would fail with + // invalid object) + msg, err := tx.Digest() + gomega.Ω(err).To(gomega.BeNil()) + auth, err := factory.Sign(msg) + gomega.Ω(err).To(gomega.BeNil()) + tx.Auth = auth + p := codec.NewWriter(0, hconsts.MaxInt) // test codec growth + gomega.Ω(tx.Marshal(p)).To(gomega.BeNil()) + gomega.Ω(p.Err()).To(gomega.BeNil()) + _, err = instances[0].hcli.SubmitTx( + context.Background(), + p.Bytes(), + ) + gomega.Ω(err.Error()).Should(gomega.ContainSubstring("field is not populated")) }) - ginkgo.It("Withdraw validator node 0 stake", func() { - parser, err := instances[3].ncli.Parser(context.Background()) + ginkgo.It("import with wrong destination", func() { + wt := &actions.WarpTransfer{ + To: rsender, + Symbol: []byte("s"), + Decimals: 2, + Asset: ids.GenerateTestID(), + Value: 100, + Return: false, + Reward: 100, + TxID: ids.GenerateTestID(), + DestinationChainID: ids.GenerateTestID(), + } + wtb, err := wt.Marshal() gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( + uwm, err := warp.NewUnsignedMessage(networkID, ids.Empty, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewMessage(uwm, &warp.BitSetSignature{}) + gomega.Ω(err).Should(gomega.BeNil()) + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( context.Background(), parser, - nil, - &actions.WithdrawValidatorStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rwithdraw0, - }, + wm, + &actions.ImportAsset{}, factory, ) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - accept := expectBlk(instances[3]) - results := accept(true) + // Build block with no context (should fail) + gomega.Ω(instances[0].vm.Builder().Force(context.TODO())).To(gomega.BeNil()) + <-instances[0].toEngine + blk, err := instances[0].vm.BuildBlock(context.TODO()) + gomega.Ω(err).To(gomega.Not(gomega.BeNil())) + gomega.Ω(blk).To(gomega.BeNil()) + + // Wait for mempool to be size 1 (txs are restored async) + for { + if instances[0].vm.Mempool().Len(context.Background()) > 0 { + break + } + log.Info("waiting for txs to be restored") + time.Sleep(100 * time.Millisecond) + } + + // Build block with context + accept := expectBlkWithContext(instances[0]) + results := accept(false) gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("warp verification failed")) + }) - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) + ginkgo.It("export native asset", func() { + dest := ids.GenerateTestID() + loan, err := instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(loan).Should(gomega.Equal(uint64(0))) - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, tx, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ExportAsset{ + To: rsender, + Asset: ids.Empty, + Value: 100, + Return: false, + Reward: 10, + Destination: dest, + }, + factory, + ) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeTrue()) + wt := &actions.WarpTransfer{ + To: rsender, + Symbol: []byte(nconsts.Symbol), + Decimals: nconsts.Decimals, + Asset: ids.Empty, + Value: 100, + Return: false, + Reward: 10, + TxID: tx.ID(), + DestinationChainID: dest, + } + wtb, err := wt.Marshal() + gomega.Ω(err).Should(gomega.BeNil()) + wm, err := warp.NewUnsignedMessage(networkID, instances[0].chainID, wtb) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(result.WarpMessage).Should(gomega.Equal(wm)) + loan, err = instances[0].ncli.Loan(context.TODO(), ids.Empty, dest) + gomega.Ω(err).Should(gomega.BeNil()) + gomega.Ω(loan).Should(gomega.Equal(uint64(110))) }) - ginkgo.It("Get staked validators after staking withdraw ", func() { - validators, err := instances[0].ncli.StakedValidators(context.Background()) + ginkgo.It("export native asset (invalid return)", func() { + parser, err := instances[0].ncli.Parser(context.Background()) + gomega.Ω(err).Should(gomega.BeNil()) + submit, _, _, err := instances[0].hcli.GenerateTransaction( + context.Background(), + parser, + nil, + &actions.ExportAsset{ + To: rsender, + Asset: ids.Empty, + Value: 100, + Return: true, + Reward: 10, + Destination: ids.GenerateTestID(), + }, + factory, + ) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) + gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) + accept := expectBlk(instances[0]) + results := accept(false) + gomega.Ω(results).Should(gomega.HaveLen(1)) + result := results[0] + gomega.Ω(result.Success).Should(gomega.BeFalse()) + gomega.Ω(string(result.Output)).Should(gomega.ContainSubstring("not warp asset")) }) - */ + }) }) func expectBlk(i instance) func(bool) []*chain.Result { From 7abfae9487fc0369a58723b7d9b542d452b61959 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 14:18:41 +0100 Subject: [PATCH 70/78] integration tests pass in one file --- tests/integration/integration_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 1b43f74..950b14f 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -481,7 +481,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { currentValidators := emissionInstance.GetAllValidators(context.TODO()) gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - fmt.Println(stakedValidator) gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] @@ -786,8 +785,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { var _ = ginkgo.Describe("[Tx Processing]", func() { ginkgo.It("get currently accepted block ID", func() { - fmt.Println("block-beginning") - fmt.Println(blocks) for _, inst := range instances { hcli := inst.hcli _, _, _, err := hcli.Accepted(context.Background()) @@ -1024,8 +1021,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("ensure unprocessed tip and replay protection works", func() { ginkgo.By("import accepted blocks to instance 2", func() { - fmt.Println("blocks") - fmt.Println(blocks) ctx := context.TODO() gomega.Ω(blocks[0].Height()).Should(gomega.Equal(uint64(1))) @@ -2140,9 +2135,7 @@ func setEmissionValidators() { } currentValidators = append(currentValidators, &val) } - fmt.Println(len(currentValidators)) for i := range instances { - fmt.Println(emissions[i]) emissions[i].(*emission.Manual).CurrentValidators = currentValidators } } From 9768e47e6e5eccd9e4ce453af4e66436b9bc78e4 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 14:20:55 +0100 Subject: [PATCH 71/78] remove old file --- .../integration/new_actions_test.go.separate | 725 ------------------ 1 file changed, 725 deletions(-) delete mode 100644 tests/integration/new_actions_test.go.separate diff --git a/tests/integration/new_actions_test.go.separate b/tests/integration/new_actions_test.go.separate deleted file mode 100644 index 7776eed..0000000 --- a/tests/integration/new_actions_test.go.separate +++ /dev/null @@ -1,725 +0,0 @@ -// Copyright (C) 2024, AllianceBlock. All rights reserved. -// See the file LICENSE for licensing terms. - -package integration_test - -import ( - "context" - "encoding/hex" - "encoding/json" - "flag" - "fmt" - "net/http" - "net/http/httptest" - "os" - "time" - - "github.com/ava-labs/avalanchego/api/metrics" - "github.com/ava-labs/avalanchego/database/memdb" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/snow/choices" - "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/common" - "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/crypto/bls" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/vms/platformvm/warp" - "github.com/fatih/color" - ginkgo "github.com/onsi/ginkgo/v2" - "github.com/onsi/gomega" - "go.uber.org/zap" - - "github.com/ava-labs/hypersdk/chain" - "github.com/ava-labs/hypersdk/codec" - "github.com/ava-labs/hypersdk/crypto/ed25519" - hrpc "github.com/ava-labs/hypersdk/rpc" - "github.com/ava-labs/hypersdk/vm" - - "github.com/nuklai/nuklaivm/actions" - "github.com/nuklai/nuklaivm/auth" - nconsts "github.com/nuklai/nuklaivm/consts" - "github.com/nuklai/nuklaivm/controller" - "github.com/nuklai/nuklaivm/emission" - "github.com/nuklai/nuklaivm/genesis" - nrpc "github.com/nuklai/nuklaivm/rpc" -) - -func init() { - logFactory = logging.NewFactory(logging.Config{ - DisplayLevel: logging.Debug, - }) - l, err := logFactory.Make("main") - if err != nil { - panic(err) - } - log = l -} - -func init() { - flag.DurationVar( - &requestTimeout, - "request-timeout", - 120*time.Second, - "timeout for transaction issuance and confirmation", - ) - flag.IntVar( - &vms, - "vms", - 5, - "number of VMs to create", - ) -} - -var ( - withdraw0 string - delegate string - rwithdraw0 codec.Address - rdelegate codec.Address - delegateFactory *auth.ED25519Factory - nodesFactories []*auth.BLSFactory - nodesAddresses []codec.Address - emissions []emission.Tracker - nodesPubKeys []*bls.PublicKey - height int -) - -var _ = ginkgo.BeforeSuite(func() { - log.Info("VMID", zap.Stringer("id", nconsts.ID)) - gomega.Ω(vms).Should(gomega.BeNumerically(">", 1)) - - var err error - priv, err = ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - factory = auth.NewED25519Factory(priv) - rsender = auth.NewED25519Address(priv.PublicKey()) - sender = codec.MustAddressBech32(nconsts.HRP, rsender) - log.Debug( - "generated key", - zap.String("addr", sender), - zap.String("pk", hex.EncodeToString(priv[:])), - ) - - priv2, err = ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - factory2 = auth.NewED25519Factory(priv2) - rsender2 = auth.NewED25519Address(priv2.PublicKey()) - sender2 = codec.MustAddressBech32(nconsts.HRP, rsender2) - log.Debug( - "generated key", - zap.String("addr", sender2), - zap.String("pk", hex.EncodeToString(priv2[:])), - ) - - asset1 = []byte("1") - asset1Symbol = []byte("s1") - asset1Decimals = uint8(1) - asset2 = []byte("2") - asset2Symbol = []byte("s2") - asset2Decimals = uint8(2) - asset3 = []byte("3") - asset3Symbol = []byte("s3") - asset3Decimals = uint8(3) - - // create embedded VMs - instances = make([]instance, vms) - nodesFactories = make([]*auth.BLSFactory, vms) - nodesAddresses = make([]codec.Address, vms) - emissions = make([]emission.Tracker, vms) - nodesPubKeys = make([]*bls.PublicKey, vms) - - gen = genesis.Default() - gen.MinUnitPrice = chain.Dimensions{1, 1, 1, 1, 1} - gen.MinBlockGap = 0 - gen.CustomAllocation = []*genesis.CustomAllocation{ - { - Address: sender, - Balance: 10_000_000_000_000_000, - }, - } - gen.EmissionBalancer = genesis.EmissionBalancer{ - TotalSupply: 10_000_000, - MaxSupply: 10_000_000_000, - EmissionAddress: sender, - } - genesisBytes, err = json.Marshal(gen) - gomega.Ω(err).Should(gomega.BeNil()) - - networkID = uint32(1) - subnetID := ids.GenerateTestID() - chainID := ids.GenerateTestID() - - for i := range instances { - nodeID := ids.GenerateTestNodeID() - sk, err := bls.NewSecretKey() - gomega.Ω(err).Should(gomega.BeNil()) - l, err := logFactory.Make(nodeID.String()) - gomega.Ω(err).Should(gomega.BeNil()) - dname, err := os.MkdirTemp("", fmt.Sprintf("%s-chainData", nodeID.String())) - gomega.Ω(err).Should(gomega.BeNil()) - snowCtx := &snow.Context{ - NetworkID: networkID, - SubnetID: subnetID, - ChainID: chainID, - NodeID: nodeID, - Log: l, - ChainDataDir: dname, - Metrics: metrics.NewOptionalGatherer(), - PublicKey: bls.PublicFromSecretKey(sk), - WarpSigner: warp.NewSigner(sk, networkID, chainID), - ValidatorState: &validators.TestState{}, - } - nodesFactories[i] = auth.NewBLSFactory(sk) - nodesAddresses[i] = auth.NewBLSAddress(snowCtx.PublicKey) - nodesPubKeys[i] = snowCtx.PublicKey - - toEngine := make(chan common.Message, 1) - db := memdb.New() - - v := controller.New() - err = v.Initialize( - context.TODO(), - snowCtx, - db, - genesisBytes, - nil, - []byte( - `{"parallelism":3, "testMode":true, "logLevel":"debug", "trackedPairs":["*"]}`, - ), - toEngine, - nil, - app, - ) - gomega.Ω(err).Should(gomega.BeNil()) - var hd map[string]http.Handler - hd, err = v.CreateHandlers(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - - emissions[i] = emission.GetEmission() - - hjsonRPCServer := httptest.NewServer(hd[hrpc.JSONRPCEndpoint]) - njsonRPCServer := httptest.NewServer(hd[nrpc.JSONRPCEndpoint]) - webSocketServer := httptest.NewServer(hd[hrpc.WebSocketEndpoint]) - instances[i] = instance{ - chainID: snowCtx.ChainID, - nodeID: snowCtx.NodeID, - vm: v, - toEngine: toEngine, - JSONRPCServer: hjsonRPCServer, - NuklaiJSONRPCServer: njsonRPCServer, - WebSocketServer: webSocketServer, - hcli: hrpc.NewJSONRPCClient(hjsonRPCServer.URL), - ncli: nrpc.NewJSONRPCClient(njsonRPCServer.URL, snowCtx.NetworkID, snowCtx.ChainID), - } - - // Force sync ready (to mimic bootstrapping from genesis) - v.ForceReady() - } - - // Verify genesis allocates loaded correctly (do here otherwise test may - // check during and it will be inaccurate) - for _, inst := range instances { - ncli := inst.ncli - g, err := ncli.Genesis(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - - csupply := uint64(0) - for _, alloc := range g.CustomAllocation { - balance, err := ncli.Balance(context.Background(), alloc.Address, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(alloc.Balance)) - csupply += alloc.Balance - } - exists, symbol, decimals, metadata, supply, owner, warp, err := ncli.Asset(context.Background(), ids.Empty, false) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(exists).Should(gomega.BeTrue()) - gomega.Ω(string(symbol)).Should(gomega.Equal(nconsts.Symbol)) - gomega.Ω(decimals).Should(gomega.Equal(uint8(nconsts.Decimals))) - gomega.Ω(string(metadata)).Should(gomega.Equal(nconsts.Name)) - gomega.Ω(supply).Should(gomega.Equal(csupply)) - gomega.Ω(owner).Should(gomega.Equal(codec.MustAddressBech32(nconsts.HRP, codec.EmptyAddress))) - gomega.Ω(warp).Should(gomega.BeFalse()) - } - blocks = []snowman.Block{} - - setEmissionValidators() - - app.instances = instances - color.Blue("created %d VMs", vms) -}) - -var _ = ginkgo.AfterSuite(func() { - for _, iv := range instances { - iv.JSONRPCServer.Close() - iv.NuklaiJSONRPCServer.Close() - iv.WebSocketServer.Close() - err := iv.vm.Shutdown(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - } -}) - -var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { - ginkgo.FIt("Setup and get initial staked validators", func() { - height = 0 - withdraw0Priv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rwithdraw0 = auth.NewED25519Address(withdraw0Priv.PublicKey()) - withdraw0 = codec.MustAddressBech32(nconsts.HRP, rwithdraw0) - - delegatePriv, err := ed25519.GeneratePrivateKey() - gomega.Ω(err).Should(gomega.BeNil()) - rdelegate = auth.NewED25519Address(delegatePriv.PublicKey()) - delegate = codec.MustAddressBech32(nconsts.HRP, rdelegate) - delegateFactory = auth.NewED25519Factory(delegatePriv) - - validators, err := instances[3].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) - - ginkgo.FIt("Funding node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: nodesAddresses[3], - Asset: ids.Empty, - Value: 200_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(1)) - - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - balance, err := instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(200_000_000_000))) - - // check if gossip/ new state happens - balanceOther, err := instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balanceOther).Should(gomega.Equal(uint64(200_000_000_000))) - - balance, err = instances[3].ncli.Balance(context.TODO(), sender, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) - }) - - ginkgo.FIt("Register validator stake node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - currentBlockHeight := instances[3].vm.LastAcceptedBlock().Height() - stakeStartBlock := currentBlockHeight + 2 - stakeEndBlock := currentBlockHeight + 100 - delegationFeeRate := 50 - - stakeInfo := &actions.ValidatorStakeInfo{ - NodeID: instances[3].nodeID.Bytes(), - StakeStartBlock: stakeStartBlock, - StakeEndBlock: stakeEndBlock, - StakedAmount: 100_000_000_000, - DelegationFeeRate: uint64(delegationFeeRate), - RewardAddress: rwithdraw0, - } - - stakeInfoBytes, err := stakeInfo.Marshal() - gomega.Ω(err).Should(gomega.BeNil()) - signature, err := nodesFactories[3].Sign(stakeInfoBytes) - gomega.Ω(err).Should(gomega.BeNil()) - signaturePacker := codec.NewWriter(signature.Size(), signature.Size()) - signature.Marshal(signaturePacker) - authSignature := signaturePacker.Bytes() - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.RegisterValidatorStake{ - StakeInfo: stakeInfoBytes, - AuthSignature: authSignature, - }, - nodesFactories[3], - ) - gomega.Ω(err).Should(gomega.BeNil()) - - _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - _, err = instances[3].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - // check if gossip/ new state happens - _, err = instances[4].ncli.Balance(context.TODO(), codec.MustAddressBech32(nconsts.HRP, nodesAddresses[3]), ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - - emissionInstance := emissions[3] - currentValidators := emissionInstance.GetAllValidators(context.TODO()) - gomega.Ω(len(currentValidators)).To(gomega.Equal(5)) - stakedValidator := emissionInstance.GetStakedValidator(instances[3].nodeID) - fmt.Println(stakedValidator) - gomega.Ω(len(stakedValidator)).To(gomega.Equal(1)) - - validator, exists := emissions[3].GetEmissionValidators()[instances[3].nodeID] - gomega.Ω(exists).To(gomega.Equal(true)) - - // check when it becomes active ? - gomega.Ω(validator.IsActive).To(gomega.Equal(false)) - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - - validators, err := instances[4].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - - }) - - ginkgo.FIt("Get validator staked amount after node 3 validator staking", func() { - _, _, stakedAmount, _, _, _, err := instances[3].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) - - ginkgo.FIt("Get validator staked amount after staking using node 0 cli", func() { - _, _, stakedAmount, _, _, _, err := instances[0].ncli.ValidatorStake(context.Background(), instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) - }) - - ginkgo.FIt("Get staked validators", func() { - validators, err := instances[4].ncli.StakedValidators(context.TODO()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) - - ginkgo.FIt("Transfer NAI to delegate user", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.Transfer{ - To: rdelegate, - Asset: ids.Empty, - Value: 100_000_000_000, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - balance, err := instances[0].ncli.Balance(context.TODO(), delegate, ids.Empty) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) - - ginkgo.FIt("Delegate user stake to node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.DelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - StakedAmount: 30_000_000_000, - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - fmt.Printf("delegate stake to node 3 %d", height) - - blk := blocks[height] - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - height++ - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) - - // TODO: GetUserStakeFromState is returning an empty value - // TODO: transactions are played twice because of Verify and Accept (block is already processed) - - /* - ginkgo.FIt("Get user stake before claim", func() { - for _, inst := range instances { - color.Blue("checking %q", inst.nodeID) - - // Ensure all blocks processed - for { - _, h, _, err := inst.hcli.Accepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - if h > 0 { - break - } - time.Sleep(1 * time.Second) - } - _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instances[3].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) - - } - }) - - ginkgo.It("Claim delegation stake rewards from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ClaimDelegationStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - UserStakeAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - // test same block is accepted - lastAcceptedBlock3, err := instances[3].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - lastAcceptedBlock4, err := instances[4].vm.LastAccepted(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(lastAcceptedBlock3).To(gomega.Equal(lastAcceptedBlock4)) - }) - - ginkgo.It("Get user stake after claim", func() { - _, stakedAmount, _, _, err := instances[3].ncli.UserStake(context.Background(), rdelegate, instances[0].nodeID) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(stakedAmount).Should(gomega.Equal(0)) - }) - - ginkgo.It("Undelegate user stake from node 3", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.UndelegateUserStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rdelegate, - }, - delegateFactory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - }) - - ginkgo.It("Claim validator node 0 stake reward", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.ClaimValidatorStakeRewards{ - NodeID: instances[3].nodeID.Bytes(), - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - gomega.Ω(instances[3].vm.Mempool().Len(context.TODO())).Should(gomega.Equal(1)) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - gomega.Ω(instances[3].ncli.Balance(context.Background(), withdraw0, ids.Empty)).Should(gomega.BeNumerically(">", 0)) - }) - - ginkgo.It("Withdraw validator node 0 stake", func() { - parser, err := instances[3].ncli.Parser(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - submit, _, _, err := instances[3].hcli.GenerateTransaction( - context.Background(), - parser, - nil, - &actions.WithdrawValidatorStake{ - NodeID: instances[3].nodeID.Bytes(), - RewardAddress: rwithdraw0, - }, - factory, - ) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) - - accept := expectBlk(instances[3]) - results := accept(true) - gomega.Ω(results).Should(gomega.HaveLen(1)) - gomega.Ω(results[0].Success).Should(gomega.BeTrue()) - - gomega.Ω(len(blocks)).Should(gomega.Equal(height + 1)) - - blk := blocks[height] - fmt.Println(blk.ID()) - ImportBlockToInstance(instances[4].vm, blk) - ImportBlockToInstance(instances[0].vm, blk) - ImportBlockToInstance(instances[2].vm, blk) - ImportBlockToInstance(instances[1].vm, blk) - height++ - - }) - - ginkgo.It("Get staked validators after staking withdraw ", func() { - validators, err := instances[0].ncli.StakedValidators(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(len(validators)).Should(gomega.Equal(0)) - }) - */ -}) - -func ImportBlockToInstance(vm *vm.VM, block snowman.Block) { - blk, err := vm.ParseBlock(context.Background(), block.Bytes()) - gomega.Ω(err).Should(gomega.BeNil()) - err = blk.Verify(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) - - gomega.Ω(blk.Status()).To(gomega.Equal(choices.Processing)) - err = vm.SetPreference(context.Background(), blk.ID()) - gomega.Ω(err).To(gomega.BeNil()) - - err = blk.Accept(context.Background()) - gomega.Ω(err).Should(gomega.BeNil()) -} - -func setEmissionValidators() { - currentValidators := make([]*emission.Validator, 0, len(instances)) - for i, inst := range instances { - val := emission.Validator{ - NodeID: inst.nodeID, - PublicKey: bls.PublicKeyToBytes(nodesPubKeys[i]), - } - currentValidators = append(currentValidators, &val) - } - fmt.Println(len(currentValidators)) - for i := range instances { - fmt.Println(emissions[i]) - emissions[i].(*emission.Manual).CurrentValidators = currentValidators - } -} From c66d1f472d0fb476b41fdee0204a377bbd5bc411 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 17:02:46 +0100 Subject: [PATCH 72/78] update --- tests/e2e/e2e_test.go | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 028424a..a364238 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -547,7 +547,7 @@ var _ = ginkgo.Describe("[Test]", func() { return } - ginkgo.It("transfer in a single node (raw)", func() { + ginkgo.XIt("transfer in a single node (raw)", func() { nativeBalance, err := instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(nativeBalance).Should(gomega.Equal(startAmount)) @@ -593,7 +593,8 @@ var _ = ginkgo.Describe("[Test]", func() { sendAmount, balance, ) - gomega.Ω(balance).Should(gomega.Equal(startAmount - fee - sendAmount)) + updatedAmount := startAmount - fee - sendAmount + gomega.Ω(balance).Should(gomega.Equal(updatedAmount)) hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) @@ -1532,10 +1533,12 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(0)) }) - ginkgo.It("Funding node 0", func() { + balanceBefore, err := instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) + gomega.Ω(err).Should(gomega.BeNil()) parser, err := instancesA[0].ncli.Parser(context.TODO()) gomega.Ω(err).Should(gomega.BeNil()) + amount := uint64(200_000_000_000) submit, tx, _, err := instancesA[0].hcli.GenerateTransaction( context.Background(), parser, @@ -1543,7 +1546,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { &actions.Transfer{ To: nodesAddresses[0], Asset: ids.Empty, - Value: 200_000_000_000, + Value: amount, }, factory, ) @@ -1553,7 +1556,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(submit(context.Background())).Should(gomega.BeNil()) hutils.Outf("{{yellow}}submitted transaction{{/}}\n") ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - success, _, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) + success, fee, err := instancesA[0].ncli.WaitForTransaction(ctx, tx.ID()) cancel() gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) @@ -1582,12 +1585,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { hutils.Outf("{{yellow}}fetched balance{{/}}\n") } - balance, err = instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) + balanceAfter, err := instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(balance).Should(gomega.Equal(uint64(852_999_799_999_970_300))) + gomega.Ω(balanceAfter).Should(gomega.Equal(balanceBefore - fee - amount)) hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) - ginkgo.It("Register validator stake node 0", func() { withdraw0Priv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) @@ -1641,7 +1643,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found register validator stake transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) @@ -1665,20 +1666,17 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { fmt.Printf("node 3 instances[4] %s balance after staking %d\n", codec.MustAddressBech32(nconsts.HRP, nodesAddresses[0]), balanceOther) } }) - ginkgo.It("Get validator staked amount after node 0 validator staking", func() { _, _, stakedAmount, _, _, _, err := instancesA[0].ncli.ValidatorStake(context.Background(), instancesA[0].nodeID) fmt.Printf("NODE 3 STAKED AMOUNT %d", stakedAmount) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(100_000_000_000))) }) - ginkgo.It("Get staked validators", func() { validators, err := instancesA[0].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(1)) }) - ginkgo.It("Transfer NAI to delegate user", func() { delegatePriv, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) @@ -1727,7 +1725,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.It("Delegate user stake to node 0", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1771,13 +1768,11 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.It("Get user stake before claim", func() { _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) }) - ginkgo.It("Claim delegation stake rewards from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -1825,7 +1820,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.It("Undelegate user stake from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -1853,7 +1847,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { for _, inst := range instancesA { color.Blue("checking %q", inst.uri) - // Ensure all blocks processed for { _, h, _, err := inst.hcli.Accepted(context.Background()) @@ -1870,7 +1863,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.It("Transfer NAI to node 0 withdraw address for fees", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1894,10 +1886,8 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) - // Ensure all blocks processed for { _, h, _, err := inst.hcli.Accepted(context.Background()) @@ -1914,7 +1904,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } }) - ginkgo.It("Claim node 0 stake reward", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), withdraw0, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) @@ -1958,9 +1947,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } - }) - ginkgo.It("Withdraw validator node 0 stake", func() { for { currentBlockHeight, _, _, _, _, _, _, _ := instancesA[0].ncli.EmissionInfo(context.Background()) @@ -2013,7 +2000,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(len(validators)).Should(gomega.Equal(0)) } }) - }) func awaitHealthy(cli runner_sdk.Client) { From a9e0362c676c3e4da1982a196cb53c1b6cd2aba5 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Wed, 8 May 2024 18:19:04 +0100 Subject: [PATCH 73/78] e2e tests should pass --- tests/e2e/e2e_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index a364238..35f1909 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -547,10 +547,10 @@ var _ = ginkgo.Describe("[Test]", func() { return } - ginkgo.XIt("transfer in a single node (raw)", func() { + ginkgo.It("transfer in a single node (raw)", func() { nativeBalance, err := instancesA[0].ncli.Balance(context.TODO(), sender, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - gomega.Ω(nativeBalance).Should(gomega.Equal(startAmount)) + gomega.Ω(nativeBalance).Should(gomega.BeNumerically("<=", startAmount)) other, err := ed25519.GeneratePrivateKey() gomega.Ω(err).Should(gomega.BeNil()) @@ -593,7 +593,7 @@ var _ = ginkgo.Describe("[Test]", func() { sendAmount, balance, ) - updatedAmount := startAmount - fee - sendAmount + updatedAmount := nativeBalance - fee - sendAmount gomega.Ω(balance).Should(gomega.Equal(updatedAmount)) hutils.Outf("{{yellow}}fetched balance{{/}}\n") }) From dc03de111a647c79f832b1b947d6425cecd384f3 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Thu, 9 May 2024 17:54:17 +0100 Subject: [PATCH 74/78] linter --- emission/manual.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emission/manual.go b/emission/manual.go index c049ef4..45dc0c0 100644 --- a/emission/manual.go +++ b/emission/manual.go @@ -513,7 +513,7 @@ func (e *Manual) GetStakedValidator(nodeID ids.NodeID) []*Validator { } // GetAllValidators fetches the current validators from the underlying VM -func (e *Manual) GetAllValidators(ctx context.Context) []*Validator { +func (e *Manual) GetAllValidators(_ context.Context) []*Validator { e.c.Logger().Info("fetching all staked and unstaked validators") for _, v := range e.CurrentValidators { From 93ae68ae356ef1ce703e7a9f7f3ee3db7be8cf1c Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Thu, 9 May 2024 18:18:15 +0100 Subject: [PATCH 75/78] linter e2e --- tests/e2e/e2e_test.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 35f1909..0e5b89a 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1705,7 +1705,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) @@ -1722,7 +1721,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { balance, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - } }) ginkgo.It("Delegate user stake to node 0", func() { @@ -1748,7 +1746,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found delegate user stake transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) @@ -1761,12 +1758,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } time.Sleep(1 * time.Second) } - _, stakedAmount, _, _, err := inst.ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(stakedAmount).Should(gomega.Equal(uint64(30_000_000_000))) } - }) ginkgo.It("Get user stake before claim", func() { _, stakedAmount, _, _, err := instancesA[0].ncli.UserStake(context.Background(), rdelegate, instancesA[0].nodeID) @@ -1776,8 +1771,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { ginkgo.It("Claim delegation stake rewards from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) - - // wait for blocks otherwise reward = 0 and error on UnpackUint64 while unmarshalling the data time.Sleep(1 * time.Minute) parser, err := instancesA[0].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -1800,7 +1793,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found claim delegation stake transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) @@ -1813,12 +1805,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } time.Sleep(2 * time.Second) } - balanceAfter, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } - }) ginkgo.It("Undelegate user stake from node 0", func() { balanceBefore, err := instancesA[0].ncli.Balance(context.Background(), delegate, ids.Empty) @@ -1844,7 +1834,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(success).Should(gomega.BeTrue()) hutils.Outf("{{yellow}}found undelegate user stake transaction{{/}}\n") - for _, inst := range instancesA { color.Blue("checking %q", inst.uri) // Ensure all blocks processed @@ -1856,12 +1845,10 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } time.Sleep(1 * time.Second) } - balanceAfter, err := inst.ncli.Balance(context.Background(), delegate, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balanceAfter).Should(gomega.BeNumerically(">", balanceBefore-fee)) } - }) ginkgo.It("Transfer NAI to node 0 withdraw address for fees", func() { parser, err := instancesA[0].ncli.Parser(context.Background()) @@ -1897,11 +1884,9 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { } time.Sleep(1 * time.Second) } - balance, err := inst.ncli.Balance(context.Background(), withdraw0, ids.Empty) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(100_000_000_000))) - } }) ginkgo.It("Claim node 0 stake reward", func() { From 1b21f33f18d411ea8cf4e07932a195710261be23 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Mon, 13 May 2024 10:12:21 +0100 Subject: [PATCH 76/78] rename file from manual to mock --- emission/{manual.go => mock.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename emission/{manual.go => mock.go} (100%) diff --git a/emission/manual.go b/emission/mock.go similarity index 100% rename from emission/manual.go rename to emission/mock.go From f7759410f282adb83300c1a04989ac4cec069554 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Mon, 13 May 2024 15:39:00 +0100 Subject: [PATCH 77/78] lint --- tests/integration/integration_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 950b14f..8f3158f 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -413,7 +413,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(balance).Should(gomega.Equal(uint64(9_999_799_999_999_703))) }) - ginkgo.It("Register validator stake node 3", func() { parser, err := instances[3].ncli.Parser(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) @@ -499,7 +498,6 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { validators, err := instances[4].ncli.StakedValidators(context.Background()) gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(len(validators)).Should(gomega.Equal(1)) - }) ginkgo.It("Get validator staked amount after node 3 validator staking", func() { From dd9bc0549e7ef814a3d636fa0741040595d45732 Mon Sep 17 00:00:00 2001 From: najlachamseddine Date: Mon, 13 May 2024 15:46:46 +0100 Subject: [PATCH 78/78] fix lint: golangci-lint run --fix --- tests/integration/integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 8f3158f..a3e614b 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -781,7 +781,7 @@ var _ = ginkgo.Describe("[Nuklai staking mechanism]", func() { }) */ - var _ = ginkgo.Describe("[Tx Processing]", func() { + _ = ginkgo.Describe("[Tx Processing]", func() { ginkgo.It("get currently accepted block ID", func() { for _, inst := range instances { hcli := inst.hcli