From f0324a12304ab9c1116dc871bf5a09b0f8e0856a Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 29 Mar 2021 15:49:46 +0300 Subject: [PATCH 1/4] scripts: add test for compare-dumps script --- scripts/compare-dumps.go | 2 +- scripts/compare-dumps_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 scripts/compare-dumps_test.go diff --git a/scripts/compare-dumps.go b/scripts/compare-dumps.go index d18897d29..73458c3c0 100644 --- a/scripts/compare-dumps.go +++ b/scripts/compare-dumps.go @@ -15,7 +15,7 @@ import ( "github.com/urfave/cli" ) -var ledgerContractID = -2 +var ledgerContractID = -4 type dump []blockDump diff --git a/scripts/compare-dumps_test.go b/scripts/compare-dumps_test.go new file mode 100644 index 000000000..85a50fc64 --- /dev/null +++ b/scripts/compare-dumps_test.go @@ -0,0 +1,13 @@ +package main + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/core/native" + "github.com/stretchr/testify/require" +) + +func TestCompatibility(t *testing.T) { + cs := native.NewContracts(false, map[string][]uint32{}) + require.Equal(t, cs.Ledger.ID, int32(ledgerContractID)) +} From 3d8d92717887cf25c608509b0a569c4482218c6d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 29 Mar 2021 16:00:10 +0300 Subject: [PATCH 2/4] core: check candidate is registered at the start of voiting C# node returns an error if the candidate is not registered. We have this check inside the ModifyAccountVotes, but (*NEO).vote doesn't panics and just return bool on stack, so we should match exactly the C#'s algorithm. --- pkg/core/native/native_neo.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index e1d5d3f50..295a9d8f7 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -726,6 +726,18 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public if err != nil { return err } + if pub != nil { + valKey := makeValidatorKey(pub) + valSi := ic.DAO.GetStorageItem(n.ID, valKey) + if valSi == nil { + return errors.New("unknown validator") + } + cd := new(candidate).FromBytes(valSi) + if !cd.Registered { + return errors.New("validator must be registered") + } + } + if (acc.VoteTo == nil) != (pub == nil) { val := &acc.Balance if pub == nil { @@ -765,8 +777,6 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *b if ok { return err } - } else if !cd.Registered { - return errors.New("validator must be registered") } n.validators.Store(keys.PublicKeys(nil)) return d.PutStorageItem(n.ID, key, cd.Bytes()) From c63528db44573953f827689447a3075877e1d8c6 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 29 Mar 2021 16:07:28 +0300 Subject: [PATCH 3/4] core: put voiting account to the storage during (*NEO).vote After getting account from the storage there are a lot of checks which may fail. But C# node uses Snapshot.GetAndChange, so the account state should be put in the storage even in case of vote failure. Affects dumps. --- pkg/core/native/native_neo.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 295a9d8f7..5338abf87 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -726,6 +726,11 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public if err != nil { return err } + // we should put it in storage anyway as it affects dumps + err = ic.DAO.PutStorageItem(n.ID, key, si) + if err != nil { + return err + } if pub != nil { valKey := makeValidatorKey(pub) valSi := ic.DAO.GetStorageItem(n.ID, valKey) From b7194ec60894294a13b283af08e4bb426ff09ee0 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 29 Mar 2021 17:06:37 +0300 Subject: [PATCH 4/4] core: put candidate account to the storage during (*NEO).vote C# node uses Snapshot.GetAndChange to get it from storage, so it's the same problem as with voting account. Affects dumps. --- pkg/core/native/native_neo.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 5338abf87..75b2a7a95 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -738,6 +738,11 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public return errors.New("unknown validator") } cd := new(candidate).FromBytes(valSi) + // we should put it in storage anyway as it affects dumps + err = ic.DAO.PutStorageItem(n.ID, valKey, valSi) + if err != nil { + return err + } if !cd.Registered { return errors.New("validator must be registered") }