From a7e2a90ce9bf87399e49a095666c01c8136b017c Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 22 Aug 2025 11:04:11 +0800 Subject: [PATCH 1/4] store staking --- action/protocol/staking/bucket_index.go | 22 ++++++ action/protocol/staking/bucket_pool.go | 23 +++++++ action/protocol/staking/candidate.go | 67 +++++++++++++++++++ .../staking/candidate_statemanager.go | 10 ++- .../protocol/staking/candidate_statereader.go | 3 +- action/protocol/staking/endorsement.go | 22 ++++++ .../staking/endorsement_statemanager.go | 2 +- action/protocol/staking/vote_bucket.go | 37 ++++++++++ 8 files changed, 181 insertions(+), 5 deletions(-) diff --git a/action/protocol/staking/bucket_index.go b/action/protocol/staking/bucket_index.go index 698abd6e9e..0867dccf9d 100644 --- a/action/protocol/staking/bucket_index.go +++ b/action/protocol/staking/bucket_index.go @@ -12,6 +12,9 @@ import ( "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) type ( @@ -19,6 +22,11 @@ type ( BucketIndices []uint64 ) +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterBucketIndices(_stakingNameSpace, &BucketIndices{})) +} + // Proto converts bucket indices to protobuf func (bis *BucketIndices) Proto() *stakingpb.BucketIndices { bucketIndicesPb := make([]uint64, 0, len(*bis)) @@ -51,6 +59,20 @@ func (bis *BucketIndices) Serialize() ([]byte, error) { return proto.Marshal(bis.Proto()) } +// Encode encodes bucket indices into generic value +func (bis *BucketIndices) Encode() (systemcontracts.GenericValue, error) { + data, err := bis.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize bucket indices") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes bucket indices from generic value +func (bis *BucketIndices) Decode(gv systemcontracts.GenericValue) error { + return bis.Deserialize(gv.PrimaryData) +} + func (bis *BucketIndices) addBucketIndex(index uint64) { *bis = append(*bis, index) } diff --git a/action/protocol/staking/bucket_pool.go b/action/protocol/staking/bucket_pool.go index c5d998edcb..84486744ac 100644 --- a/action/protocol/staking/bucket_pool.go +++ b/action/protocol/staking/bucket_pool.go @@ -9,11 +9,15 @@ import ( "math/big" "github.com/iotexproject/go-pkgs/hash" + "github.com/pkg/errors" "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // const @@ -49,6 +53,11 @@ type ( } ) +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterBucketPool(_stakingNameSpace, &totalAmount{})) +} + func (t *totalAmount) Serialize() ([]byte, error) { gen := stakingpb.TotalAmount{ Amount: t.amount.String(), @@ -91,6 +100,20 @@ func (t *totalAmount) SubBalance(amount *big.Int) error { return nil } +// Encode encodes total amount into generic value +func (t *totalAmount) Encode() (systemcontracts.GenericValue, error) { + data, err := t.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize total amount") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes total amount from generic value +func (t *totalAmount) Decode(gv systemcontracts.GenericValue) error { + return t.Deserialize(gv.PrimaryData) +} + // IsDirty returns true if the bucket pool is dirty func (bp *BucketPool) IsDirty() bool { return bp.dirty diff --git a/action/protocol/staking/candidate.go b/action/protocol/staking/candidate.go index 413821e49c..22484bbe7f 100644 --- a/action/protocol/staking/candidate.go +++ b/action/protocol/staking/candidate.go @@ -17,7 +17,10 @@ import ( "github.com/iotexproject/iotex-core/v2/action" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) type ( @@ -44,6 +47,12 @@ type ( } ) +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterCandidateMap(CandsMapNS, &CandidateList{})) + assertions.MustNoError(registry.RegisterCandidates(_candidateNameSpace, &Candidate{})) +} + // Clone returns a copy func (d *Candidate) Clone() *Candidate { return &Candidate{ @@ -194,6 +203,50 @@ func (d *Candidate) GetIdentifier() address.Address { return d.Identifier } +// Encode encodes candidate into generic value +func (d *Candidate) Encode() (systemcontracts.GenericValue, error) { + var ( + primaryData []byte + secondaryData []byte + err error + value systemcontracts.GenericValue + ) + if d.Votes.Sign() > 0 { + secondaryData, err = proto.Marshal(&stakingpb.Candidate{Votes: d.Votes.String()}) + if err != nil { + return value, errors.Wrap(err, "failed to marshal candidate votes") + } + } + clone := d.Clone() + clone.Votes = big.NewInt(0) + primaryData, err = clone.Serialize() + if err != nil { + return value, errors.Wrap(err, "failed to serialize candidate") + } + value.PrimaryData = primaryData + value.SecondaryData = secondaryData + return value, nil +} + +// Decode decodes candidate from generic value +func (d *Candidate) Decode(gv systemcontracts.GenericValue) error { + if err := d.Deserialize(gv.PrimaryData); err != nil { + return errors.Wrap(err, "failed to deserialize candidate") + } + if len(gv.SecondaryData) > 0 { + votes := &stakingpb.Candidate{} + if err := proto.Unmarshal(gv.SecondaryData, votes); err != nil { + return errors.Wrap(err, "failed to unmarshal candidate votes") + } + vote, ok := new(big.Int).SetString(votes.Votes, 10) + if !ok { + return errors.Wrapf(action.ErrInvalidAmount, "failed to parse candidate votes: %s", votes.Votes) + } + d.Votes = vote + } + return nil +} + func (d *Candidate) toProto() (*stakingpb.Candidate, error) { if d.Owner == nil || d.Operator == nil || d.Reward == nil || len(d.Name) == 0 || d.Votes == nil || d.SelfStake == nil { @@ -360,6 +413,20 @@ func (l *CandidateList) Deserialize(buf []byte) error { return nil } +// Encode encodes candidate list into generic value +func (l *CandidateList) Encode() (systemcontracts.GenericValue, error) { + data, err := l.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize candidate list") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes candidate list from generic value +func (l *CandidateList) Decode(gv systemcontracts.GenericValue) error { + return l.Deserialize(gv.PrimaryData) +} + func (l CandidateList) toStateCandidateList() (state.CandidateList, error) { list := make(state.CandidateList, 0, len(l)) for _, c := range l { diff --git a/action/protocol/staking/candidate_statemanager.go b/action/protocol/staking/candidate_statemanager.go index 580bc833e0..25fc43c58f 100644 --- a/action/protocol/staking/candidate_statemanager.go +++ b/action/protocol/staking/candidate_statemanager.go @@ -220,7 +220,9 @@ func (csm *candSM) putBucket(bucket *VoteBucket) (uint64, error) { func (csm *candSM) delBucket(index uint64) error { _, err := csm.DelState( protocol.NamespaceOption(_stakingNameSpace), - protocol.KeyOption(bucketKey(index))) + protocol.KeyOption(bucketKey(index)), + protocol.ObjectOption(&VoteBucket{}), + ) return err } @@ -295,7 +297,9 @@ func (csm *candSM) delBucketIndex(addr address.Address, prefix byte, index uint6 if len(bis) == 0 { _, err = csm.DelState( protocol.NamespaceOption(_stakingNameSpace), - protocol.KeyOption(key)) + protocol.KeyOption(key), + protocol.ObjectOption(&BucketIndices{}), + ) } else { _, err = csm.PutState( &bis, @@ -319,7 +323,7 @@ func (csm *candSM) putCandBucketIndex(addr address.Address, index uint64) error } func (csm *candSM) delCandidate(name address.Address) error { - _, err := csm.DelState(protocol.NamespaceOption(_candidateNameSpace), protocol.KeyOption(name.Bytes())) + _, err := csm.DelState(protocol.NamespaceOption(_candidateNameSpace), protocol.KeyOption(name.Bytes()), protocol.ObjectOption(&Candidate{})) return err } diff --git a/action/protocol/staking/candidate_statereader.go b/action/protocol/staking/candidate_statereader.go index d12d498ffe..fd6505b1bd 100644 --- a/action/protocol/staking/candidate_statereader.go +++ b/action/protocol/staking/candidate_statereader.go @@ -221,6 +221,7 @@ func (c *candSR) NativeBuckets() ([]*VoteBucket, uint64, error) { } return keys, nil }), + protocol.ObjectOption(&VoteBucket{}), ) if err != nil { return nil, height, err @@ -302,7 +303,7 @@ func (c *candSR) CandidateByAddress(name address.Address) (*Candidate, uint64, e } func (c *candSR) getAllCandidates() (CandidateList, uint64, error) { - height, iter, err := c.States(protocol.NamespaceOption(_candidateNameSpace)) + height, iter, err := c.States(protocol.NamespaceOption(_candidateNameSpace), protocol.ObjectOption(&Candidate{})) if err != nil { return nil, height, err } diff --git a/action/protocol/staking/endorsement.go b/action/protocol/staking/endorsement.go index 9ce2ba2a80..e3579715b4 100644 --- a/action/protocol/staking/endorsement.go +++ b/action/protocol/staking/endorsement.go @@ -7,6 +7,9 @@ import ( "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // EndorsementStatus @@ -34,6 +37,11 @@ type ( } ) +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterEndorsement(_stakingNameSpace, &Endorsement{})) +} + // String returns a human-readable string of the endorsement status func (s EndorsementStatus) String() string { switch s { @@ -84,6 +92,20 @@ func (e *Endorsement) Deserialize(buf []byte) error { return e.fromProto(pb) } +// Encode encodes endorsement into generic value +func (e *Endorsement) Encode() (systemcontracts.GenericValue, error) { + data, err := e.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize endorsement") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes endorsement from generic value +func (e *Endorsement) Decode(gv systemcontracts.GenericValue) error { + return e.Deserialize(gv.PrimaryData) +} + func (e *Endorsement) toProto() (*stakingpb.Endorsement, error) { return &stakingpb.Endorsement{ ExpireHeight: e.ExpireHeight, diff --git a/action/protocol/staking/endorsement_statemanager.go b/action/protocol/staking/endorsement_statemanager.go index b002512c8a..c273f8d3c1 100644 --- a/action/protocol/staking/endorsement_statemanager.go +++ b/action/protocol/staking/endorsement_statemanager.go @@ -36,7 +36,7 @@ func (esm *EndorsementStateManager) Put(bucketIndex uint64, endorse *Endorsement // Delete deletes the endorsement of a bucket func (esm *EndorsementStateManager) Delete(bucketIndex uint64) error { - _, err := esm.DelState(protocol.NamespaceOption(_stakingNameSpace), protocol.KeyOption(endorsementKey(bucketIndex))) + _, err := esm.DelState(protocol.NamespaceOption(_stakingNameSpace), protocol.KeyOption(endorsementKey(bucketIndex)), protocol.ObjectOption(&Endorsement{})) return err } diff --git a/action/protocol/staking/vote_bucket.go b/action/protocol/staking/vote_bucket.go index 6cdc4f9a99..c5d2c7d8be 100644 --- a/action/protocol/staking/vote_bucket.go +++ b/action/protocol/staking/vote_bucket.go @@ -19,7 +19,10 @@ import ( "github.com/iotexproject/iotex-core/v2/action" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) const ( @@ -53,6 +56,12 @@ type ( } ) +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterStakingBuckets(_stakingNameSpace, &VoteBucket{})) + assertions.MustNoError(registry.RegisterBucketPool(_stakingNameSpace, &totalBucketCount{})) +} + // NewVoteBucket creates a new vote bucket func NewVoteBucket(cand, owner address.Address, amount *big.Int, duration uint32, ctime time.Time, autoStake bool) *VoteBucket { return &VoteBucket{ @@ -77,6 +86,20 @@ func (vb *VoteBucket) Deserialize(buf []byte) error { return vb.fromProto(pb) } +// Encode encodes VoteBucket into generic value +func (vb *VoteBucket) Encode() (systemcontracts.GenericValue, error) { + data, err := vb.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize bucket") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes VoteBucket from generic value +func (vb *VoteBucket) Decode(gv systemcontracts.GenericValue) error { + return vb.Deserialize(gv.PrimaryData) +} + func (vb *VoteBucket) fromProto(pb *stakingpb.Bucket) error { vote, ok := new(big.Int).SetString(pb.GetStakedAmount(), 10) if !ok { @@ -213,6 +236,20 @@ func (tc *totalBucketCount) Count() uint64 { return tc.count } +// Encode encodes totalBucketCount into generic value +func (tc *totalBucketCount) Encode() (systemcontracts.GenericValue, error) { + data, err := tc.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize total bucket count") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes totalBucketCount from generic value +func (tc *totalBucketCount) Decode(gv systemcontracts.GenericValue) error { + return tc.Deserialize(gv.PrimaryData) +} + func bucketKey(index uint64) []byte { key := []byte{_bucket} return append(key, byteutil.Uint64ToBytesBigEndian(index)...) From bf4b160756da91f16ca2f54aeec113f3182acbd2 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 26 Sep 2025 11:57:06 +0800 Subject: [PATCH 2/4] fix namespace storage --- state/factory/erigonstore/registry.go | 2 +- systemcontracts/namespace_storage_wrapper.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go index ce50dc8f3f..f854cfd9ae 100644 --- a/state/factory/erigonstore/registry.go +++ b/state/factory/erigonstore/registry.go @@ -63,7 +63,7 @@ func (osr *ObjectStorageRegistry) ObjectStorage(ns string, obj any, backend *con ) case namespaceStorageContractType: contractAddr := systemContracts[contractIndex].Address - contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), backend, common.Address(systemContractCreatorAddr)) + contract, err := systemcontracts.NewNamespaceStorageContractWrapper(common.BytesToAddress(contractAddr.Bytes()[:]), backend, common.Address(systemContractCreatorAddr), ns) if err != nil { return nil, err } diff --git a/systemcontracts/namespace_storage_wrapper.go b/systemcontracts/namespace_storage_wrapper.go index 2b957cfd27..c994ced1cc 100644 --- a/systemcontracts/namespace_storage_wrapper.go +++ b/systemcontracts/namespace_storage_wrapper.go @@ -65,13 +65,13 @@ func (ns *NamespaceStorageContractWrapper) BatchPut(keys [][]byte, values []Name } // List retrieves all stored data in a namespace with pagination -func (ns *NamespaceStorageContractWrapper) List(offset, limit *big.Int) (*NamespaceListResult, error) { - return ns.contract.List(ns.ns, offset, limit) +func (ns *NamespaceStorageContractWrapper) List(offset, limit uint64) (*NamespaceListResult, error) { + return ns.contract.List(ns.ns, big.NewInt(int64(offset)), big.NewInt(int64(limit))) } // ListKeys retrieves all keys in a namespace with pagination -func (ns *NamespaceStorageContractWrapper) ListKeys(offset, limit *big.Int) (*NamespaceListKeysResult, error) { - return ns.contract.ListKeys(ns.ns, offset, limit) +func (ns *NamespaceStorageContractWrapper) ListKeys(offset, limit uint64) (*NamespaceListKeysResult, error) { + return ns.contract.ListKeys(ns.ns, big.NewInt(int64(offset)), big.NewInt(int64(limit))) } // Count returns the number of items in the namespace From a914eb6109f445a72563982d5dd6f007fc23d118 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 26 Sep 2025 16:51:30 +0800 Subject: [PATCH 3/4] refactor storage registry --- action/protocol/poll/blockmeta.go | 2 +- action/protocol/rewarding/admin.go | 6 +- action/protocol/rewarding/fund.go | 3 +- action/protocol/rewarding/reward.go | 6 +- action/protocol/staking/bucket_index.go | 2 +- action/protocol/staking/bucket_pool.go | 2 +- action/protocol/staking/candidate.go | 8 -- action/protocol/staking/endorsement.go | 2 +- action/protocol/staking/vote_bucket.go | 4 +- action/protocol/vote/probationlist.go | 2 +- action/protocol/vote/unproductivedelegate.go | 2 +- state/factory/erigonstore/registry.go | 125 +++++++------------ 12 files changed, 57 insertions(+), 107 deletions(-) diff --git a/action/protocol/poll/blockmeta.go b/action/protocol/poll/blockmeta.go index 13ae8fd2e4..e8cde1fcfb 100644 --- a/action/protocol/poll/blockmeta.go +++ b/action/protocol/poll/blockmeta.go @@ -27,7 +27,7 @@ type BlockMeta struct { } func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollBlockMeta(protocol.SystemNamespace, &BlockMeta{})) + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &BlockMeta{}, erigonstore.PollBlockMetaContractIndex)) } // NewBlockMeta constructs new blockmeta struct with given fieldss diff --git a/action/protocol/rewarding/admin.go b/action/protocol/rewarding/admin.go index f388f6c9ee..ce86f16ef1 100644 --- a/action/protocol/rewarding/admin.go +++ b/action/protocol/rewarding/admin.go @@ -36,10 +36,8 @@ type admin struct { func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &admin{})) - assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &exempt{})) - assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &admin{})) - assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &exempt{})) + assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &admin{}, erigonstore.RewardingContractV1Index)) + assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &exempt{}, erigonstore.RewardingContractV1Index)) } // Serialize serializes admin state into bytes diff --git a/action/protocol/rewarding/fund.go b/action/protocol/rewarding/fund.go index 95bbc49d0f..219b84c10a 100644 --- a/action/protocol/rewarding/fund.go +++ b/action/protocol/rewarding/fund.go @@ -34,8 +34,7 @@ type fund struct { func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &fund{})) - assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &fund{})) + assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &fund{}, erigonstore.RewardingContractV1Index)) } // Serialize serializes fund state into bytes diff --git a/action/protocol/rewarding/reward.go b/action/protocol/rewarding/reward.go index 76346217b3..3946a072ad 100644 --- a/action/protocol/rewarding/reward.go +++ b/action/protocol/rewarding/reward.go @@ -36,10 +36,8 @@ type rewardHistory struct{} func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &rewardHistory{})) - assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &rewardAccount{})) - assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &rewardHistory{})) - assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &rewardAccount{})) + assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &rewardHistory{}, erigonstore.RewardingContractV1Index)) + assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &rewardAccount{}, erigonstore.RewardingContractV1Index)) } // Serialize serializes reward history state into bytes diff --git a/action/protocol/staking/bucket_index.go b/action/protocol/staking/bucket_index.go index 0867dccf9d..03e7f31741 100644 --- a/action/protocol/staking/bucket_index.go +++ b/action/protocol/staking/bucket_index.go @@ -24,7 +24,7 @@ type ( func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterBucketIndices(_stakingNameSpace, &BucketIndices{})) + assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &BucketIndices{}, erigonstore.BucketIndicesContractIndex)) } // Proto converts bucket indices to protobuf diff --git a/action/protocol/staking/bucket_pool.go b/action/protocol/staking/bucket_pool.go index 84486744ac..b6802a63e9 100644 --- a/action/protocol/staking/bucket_pool.go +++ b/action/protocol/staking/bucket_pool.go @@ -55,7 +55,7 @@ type ( func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterBucketPool(_stakingNameSpace, &totalAmount{})) + assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &totalAmount{}, erigonstore.BucketPoolContractIndex)) } func (t *totalAmount) Serialize() ([]byte, error) { diff --git a/action/protocol/staking/candidate.go b/action/protocol/staking/candidate.go index 22484bbe7f..450ae2e83c 100644 --- a/action/protocol/staking/candidate.go +++ b/action/protocol/staking/candidate.go @@ -17,9 +17,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -47,12 +45,6 @@ type ( } ) -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterCandidateMap(CandsMapNS, &CandidateList{})) - assertions.MustNoError(registry.RegisterCandidates(_candidateNameSpace, &Candidate{})) -} - // Clone returns a copy func (d *Candidate) Clone() *Candidate { return &Candidate{ diff --git a/action/protocol/staking/endorsement.go b/action/protocol/staking/endorsement.go index e3579715b4..da2d141305 100644 --- a/action/protocol/staking/endorsement.go +++ b/action/protocol/staking/endorsement.go @@ -39,7 +39,7 @@ type ( func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterEndorsement(_stakingNameSpace, &Endorsement{})) + assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &Endorsement{}, erigonstore.EndorsementContractIndex)) } // String returns a human-readable string of the endorsement status diff --git a/action/protocol/staking/vote_bucket.go b/action/protocol/staking/vote_bucket.go index c5d2c7d8be..0e0120b843 100644 --- a/action/protocol/staking/vote_bucket.go +++ b/action/protocol/staking/vote_bucket.go @@ -58,8 +58,8 @@ type ( func init() { registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterStakingBuckets(_stakingNameSpace, &VoteBucket{})) - assertions.MustNoError(registry.RegisterBucketPool(_stakingNameSpace, &totalBucketCount{})) + assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &VoteBucket{}, erigonstore.StakingBucketsContractIndex)) + assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &totalBucketCount{}, erigonstore.BucketPoolContractIndex)) } // NewVoteBucket creates a new vote bucket diff --git a/action/protocol/vote/probationlist.go b/action/protocol/vote/probationlist.go index 8cd8029e0e..341433def6 100644 --- a/action/protocol/vote/probationlist.go +++ b/action/protocol/vote/probationlist.go @@ -26,7 +26,7 @@ type ProbationList struct { } func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollProbationList(protocol.SystemNamespace, &ProbationList{})) + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &ProbationList{}, erigonstore.PollProbationListContractIndex)) } // NewProbationList returns a new probation list diff --git a/action/protocol/vote/unproductivedelegate.go b/action/protocol/vote/unproductivedelegate.go index 7822b690b4..c4a0bf0987 100644 --- a/action/protocol/vote/unproductivedelegate.go +++ b/action/protocol/vote/unproductivedelegate.go @@ -26,7 +26,7 @@ type UnproductiveDelegate struct { } func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollUnproductiveDelegate(protocol.SystemNamespace, &UnproductiveDelegate{})) + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &UnproductiveDelegate{}, erigonstore.PollUnproductiveDelegateContractIndex)) } // NewUnproductiveDelegate creates new UnproductiveDelegate with probationperiod and cacheSize diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go index f854cfd9ae..4024e07369 100644 --- a/state/factory/erigonstore/registry.go +++ b/state/factory/erigonstore/registry.go @@ -25,12 +25,17 @@ var ( // ObjectStorageRegistry is a registry for object storage type ObjectStorageRegistry struct { contracts map[string]map[reflect.Type]int + fallback map[string]int } func init() { - assertions.MustNoError(storageRegistry.RegisterAccount(state.AccountKVNamespace, &state.Account{})) - assertions.MustNoError(storageRegistry.RegisterPollCandidateList(state.SystemNamespace, &state.CandidateList{})) - assertions.MustNoError(storageRegistry.RegisterPollLegacyCandidateList(state.AccountKVNamespace, &state.CandidateList{})) + assertions.MustNoError(storageRegistry.RegisterNamespace(state.RewardingNamespace, RewardingContractV2Index)) + assertions.MustNoError(storageRegistry.RegisterNamespace(state.CandidateNamespace, CandidatesContractIndex)) + assertions.MustNoError(storageRegistry.RegisterNamespace(state.CandsMapNamespace, CandidateMapContractIndex)) + + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.AccountKVNamespace, &state.Account{}, AccountIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &state.CandidateList{}, PollCandidateListContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.AccountKVNamespace, &state.CandidateList{}, PollLegacyCandidateListContractIndex)) } // GetObjectStorageRegistry returns the global object storage registry @@ -41,18 +46,15 @@ func GetObjectStorageRegistry() *ObjectStorageRegistry { func newObjectStorageRegistry() *ObjectStorageRegistry { return &ObjectStorageRegistry{ contracts: make(map[string]map[reflect.Type]int), + fallback: make(map[string]int), } } // ObjectStorage returns the object storage for the given namespace and object type func (osr *ObjectStorageRegistry) ObjectStorage(ns string, obj any, backend *contractBackend) (ObjectStorage, error) { - types, ok := osr.contracts[ns] - if !ok { - return nil, errors.Wrapf(ErrObjectStorageNotRegistered, "namespace: %s", ns) - } - contractIndex, ok := types[reflect.TypeOf(obj)] - if !ok { - return nil, errors.Wrapf(ErrObjectStorageNotRegistered, "namespace: %s, object: %T", ns, obj) + contractIndex, exist := osr.matchContractIndex(ns, obj) + if !exist { + return nil, errors.Wrapf(ErrObjectStorageNotRegistered, "namespace: %s, type: %T", ns, obj) } // TODO: cache storage switch systemContractTypes[contractIndex] { @@ -78,82 +80,30 @@ func (osr *ObjectStorageRegistry) ObjectStorage(ns string, obj any, backend *con } } -// RegisterAccount registers an account object storage -func (osr *ObjectStorageRegistry) RegisterAccount(ns string, obj any) error { - return osr.register(ns, obj, AccountIndex) -} - -// RegisterStakingBuckets registers a staking buckets object storage -func (osr *ObjectStorageRegistry) RegisterStakingBuckets(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, StakingBucketsContractIndex) -} - -// RegisterBucketPool registers a bucket pool object storage -func (osr *ObjectStorageRegistry) RegisterBucketPool(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, BucketPoolContractIndex) -} - -// RegisterBucketIndices registers a bucket indices object storage -func (osr *ObjectStorageRegistry) RegisterBucketIndices(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, BucketIndicesContractIndex) -} - -// RegisterEndorsement registers an endorsement object storage -func (osr *ObjectStorageRegistry) RegisterEndorsement(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, EndorsementContractIndex) -} - -// RegisterCandidateMap registers a candidate map object storage -func (osr *ObjectStorageRegistry) RegisterCandidateMap(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, CandidateMapContractIndex) -} - -// RegisterCandidates registers a candidates object storage -func (osr *ObjectStorageRegistry) RegisterCandidates(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, CandidatesContractIndex) -} - -// RegisterPollCandidateList registers a poll candidate list object storage -func (osr *ObjectStorageRegistry) RegisterPollCandidateList(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, PollCandidateListContractIndex) -} - -// RegisterPollLegacyCandidateList registers a poll legacy candidate list object storage -func (osr *ObjectStorageRegistry) RegisterPollLegacyCandidateList(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, PollLegacyCandidateListContractIndex) -} - -// RegisterPollProbationList registers a poll probation list object storage -func (osr *ObjectStorageRegistry) RegisterPollProbationList(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, PollProbationListContractIndex) -} - -// RegisterPollUnproductiveDelegate registers a poll unproductive delegate object storage -func (osr *ObjectStorageRegistry) RegisterPollUnproductiveDelegate(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, PollUnproductiveDelegateContractIndex) -} - -// RegisterPollBlockMeta registers a poll block meta object storage -func (osr *ObjectStorageRegistry) RegisterPollBlockMeta(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, PollBlockMetaContractIndex) -} - -// RegisterRewardingV1 registers a rewarding v1 object storage -func (osr *ObjectStorageRegistry) RegisterRewardingV1(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, RewardingContractV1Index) -} - -// RegisterRewardingV2 registers a rewarding v2 object storage -func (osr *ObjectStorageRegistry) RegisterRewardingV2(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, RewardingContractV2Index) +// RegisterObjectStorage registers a generic object storage +func (osr *ObjectStorageRegistry) RegisterObjectStorage(ns string, obj any, index int) error { + if index < AccountIndex || index >= SystemContractCount { + return errors.Errorf("invalid system contract index %d", index) + } + return osr.register(ns, obj, index) } -// RegisterStakingView registers a staking view object storage -func (osr *ObjectStorageRegistry) RegisterStakingView(ns string, obj systemcontracts.GenericValueContainer) error { - return osr.register(ns, obj, StakingViewContractIndex) +// RegisterNamespace registers a namespace object storage +func (osr *ObjectStorageRegistry) RegisterNamespace(ns string, index int) error { + if index < AccountIndex || index >= SystemContractCount { + return errors.Errorf("invalid system contract index %d", index) + } + return osr.register(ns, nil, index) } func (osr *ObjectStorageRegistry) register(ns string, obj any, index int) error { + if obj == nil { + if _, exists := osr.fallback[ns]; exists { + return errors.Wrapf(ErrObjectStorageAlreadyRegistered, "registered: %v", osr.fallback[ns]) + } + osr.fallback[ns] = index + return nil + } types, ok := osr.contracts[ns] if !ok { osr.contracts[ns] = make(map[reflect.Type]int) @@ -165,3 +115,16 @@ func (osr *ObjectStorageRegistry) register(ns string, obj any, index int) error types[reflect.TypeOf(obj)] = index return nil } + +func (osr *ObjectStorageRegistry) matchContractIndex(ns string, obj any) (int, bool) { + if obj == nil { + index, exist := osr.fallback[ns] + return index, exist + } + types, ok := osr.contracts[ns] + if !ok { + return 0, false + } + index, exist := types[reflect.TypeOf(obj)] + return index, exist +} From a70904b0bad3ba649bc8a65e915dd922075d7c85 Mon Sep 17 00:00:00 2001 From: zhi Date: Sun, 28 Sep 2025 12:04:20 +0800 Subject: [PATCH 4/4] update matchContractIndex and move registrations into erigonstore --- action/protocol/poll/blockmeta.go | 7 ----- action/protocol/rewarding/admin.go | 9 ------ action/protocol/rewarding/fund.go | 7 ----- action/protocol/rewarding/reward.go | 8 ----- action/protocol/staking/bucket_index.go | 7 ----- action/protocol/staking/bucket_pool.go | 7 ----- action/protocol/staking/endorsement.go | 7 ----- .../staking/staking_statereader_test.go | 4 +-- action/protocol/staking/vote_bucket.go | 8 ----- action/protocol/vote/probationlist.go | 7 ----- action/protocol/vote/unproductivedelegate.go | 7 ----- go.mod | 2 +- state/factory/erigonstore/registry.go | 30 +++++++++++++------ state/factory/workingsetstore_test.go | 4 +-- 14 files changed, 26 insertions(+), 88 deletions(-) diff --git a/action/protocol/poll/blockmeta.go b/action/protocol/poll/blockmeta.go index e8cde1fcfb..b32e90eb6d 100644 --- a/action/protocol/poll/blockmeta.go +++ b/action/protocol/poll/blockmeta.go @@ -12,10 +12,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" - "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/poll/blockmetapb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -26,10 +23,6 @@ type BlockMeta struct { MintTime time.Time } -func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &BlockMeta{}, erigonstore.PollBlockMetaContractIndex)) -} - // NewBlockMeta constructs new blockmeta struct with given fieldss func NewBlockMeta(height uint64, producer string, mintTime time.Time) *BlockMeta { return &BlockMeta{ diff --git a/action/protocol/rewarding/admin.go b/action/protocol/rewarding/admin.go index ce86f16ef1..1d67abb3ad 100644 --- a/action/protocol/rewarding/admin.go +++ b/action/protocol/rewarding/admin.go @@ -17,9 +17,6 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -34,12 +31,6 @@ type admin struct { productivityThreshold uint64 } -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &admin{}, erigonstore.RewardingContractV1Index)) - assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &exempt{}, erigonstore.RewardingContractV1Index)) -} - // Serialize serializes admin state into bytes func (a admin) Serialize() ([]byte, error) { gen := rewardingpb.Admin{ diff --git a/action/protocol/rewarding/fund.go b/action/protocol/rewarding/fund.go index 219b84c10a..2131d447fe 100644 --- a/action/protocol/rewarding/fund.go +++ b/action/protocol/rewarding/fund.go @@ -19,9 +19,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol" accountutil "github.com/iotexproject/iotex-core/v2/action/protocol/account/util" "github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -32,11 +30,6 @@ type fund struct { unclaimedBalance *big.Int } -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &fund{}, erigonstore.RewardingContractV1Index)) -} - // Serialize serializes fund state into bytes func (f fund) Serialize() ([]byte, error) { gen := rewardingpb.Fund{ diff --git a/action/protocol/rewarding/reward.go b/action/protocol/rewarding/reward.go index 3946a072ad..98ee8414ff 100644 --- a/action/protocol/rewarding/reward.go +++ b/action/protocol/rewarding/reward.go @@ -25,21 +25,13 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol/staking" "github.com/iotexproject/iotex-core/v2/pkg/enc" "github.com/iotexproject/iotex-core/v2/pkg/log" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // rewardHistory is the dummy struct to record a reward. Only key matters. type rewardHistory struct{} -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &rewardHistory{}, erigonstore.RewardingContractV1Index)) - assertions.MustNoError(registry.RegisterObjectStorage(state.AccountKVNamespace, &rewardAccount{}, erigonstore.RewardingContractV1Index)) -} - // Serialize serializes reward history state into bytes func (b rewardHistory) Serialize() ([]byte, error) { gen := rewardingpb.RewardHistory{} diff --git a/action/protocol/staking/bucket_index.go b/action/protocol/staking/bucket_index.go index 03e7f31741..4de0f37629 100644 --- a/action/protocol/staking/bucket_index.go +++ b/action/protocol/staking/bucket_index.go @@ -12,8 +12,6 @@ import ( "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -22,11 +20,6 @@ type ( BucketIndices []uint64 ) -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &BucketIndices{}, erigonstore.BucketIndicesContractIndex)) -} - // Proto converts bucket indices to protobuf func (bis *BucketIndices) Proto() *stakingpb.BucketIndices { bucketIndicesPb := make([]uint64, 0, len(*bis)) diff --git a/action/protocol/staking/bucket_pool.go b/action/protocol/staking/bucket_pool.go index b6802a63e9..7616c0456d 100644 --- a/action/protocol/staking/bucket_pool.go +++ b/action/protocol/staking/bucket_pool.go @@ -14,9 +14,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -53,11 +51,6 @@ type ( } ) -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &totalAmount{}, erigonstore.BucketPoolContractIndex)) -} - func (t *totalAmount) Serialize() ([]byte, error) { gen := stakingpb.TotalAmount{ Amount: t.amount.String(), diff --git a/action/protocol/staking/endorsement.go b/action/protocol/staking/endorsement.go index da2d141305..1b335a8088 100644 --- a/action/protocol/staking/endorsement.go +++ b/action/protocol/staking/endorsement.go @@ -7,8 +7,6 @@ import ( "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -37,11 +35,6 @@ type ( } ) -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &Endorsement{}, erigonstore.EndorsementContractIndex)) -} - // String returns a human-readable string of the endorsement status func (s EndorsementStatus) String() string { switch s { diff --git a/action/protocol/staking/staking_statereader_test.go b/action/protocol/staking/staking_statereader_test.go index e65654a904..162ec27605 100644 --- a/action/protocol/staking/staking_statereader_test.go +++ b/action/protocol/staking/staking_statereader_test.go @@ -165,7 +165,7 @@ func TestStakingStateReader(t *testing.T) { } t.Run("readStateBuckets", func(t *testing.T) { sf, _, stakeSR, ctx, r := prepare(t) - sf.EXPECT().States(gomock.Any(), gomock.Any()).DoAndReturn(func(arg0 ...protocol.StateOption) (uint64, state.Iterator, error) { + sf.EXPECT().States(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(arg0 ...protocol.StateOption) (uint64, state.Iterator, error) { iter, err := state.NewIterator(keys, states) r.NoError(err) return uint64(1), iter, nil @@ -195,7 +195,7 @@ func TestStakingStateReader(t *testing.T) { }) t.Run("readStateBucketsWithEndorsement", func(t *testing.T) { sf, _, stakeSR, ctx, r := prepare(t) - sf.EXPECT().States(gomock.Any(), gomock.Any()).DoAndReturn(func(arg0 ...protocol.StateOption) (uint64, state.Iterator, error) { + sf.EXPECT().States(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(arg0 ...protocol.StateOption) (uint64, state.Iterator, error) { iter, err := state.NewIterator(keys, states) r.NoError(err) return uint64(1), iter, nil diff --git a/action/protocol/staking/vote_bucket.go b/action/protocol/staking/vote_bucket.go index dc342b3b0e..c425146d1c 100644 --- a/action/protocol/staking/vote_bucket.go +++ b/action/protocol/staking/vote_bucket.go @@ -19,9 +19,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action" "github.com/iotexproject/iotex-core/v2/action/protocol/staking/stakingpb" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -52,12 +50,6 @@ type ( } ) -func init() { - registry := erigonstore.GetObjectStorageRegistry() - assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &VoteBucket{}, erigonstore.StakingBucketsContractIndex)) - assertions.MustNoError(registry.RegisterObjectStorage(_stakingNameSpace, &totalBucketCount{}, erigonstore.BucketPoolContractIndex)) -} - // NewVoteBucket creates a new vote bucket func NewVoteBucket(cand, owner address.Address, amount *big.Int, duration uint32, ctime time.Time, autoStake bool) *VoteBucket { return &VoteBucket{ diff --git a/action/protocol/vote/probationlist.go b/action/protocol/vote/probationlist.go index 341433def6..8d931e9c54 100644 --- a/action/protocol/vote/probationlist.go +++ b/action/protocol/vote/probationlist.go @@ -13,9 +13,6 @@ import ( "github.com/iotexproject/iotex-proto/golang/iotextypes" - "github.com/iotexproject/iotex-core/v2/action/protocol" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -25,10 +22,6 @@ type ProbationList struct { IntensityRate uint32 } -func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &ProbationList{}, erigonstore.PollProbationListContractIndex)) -} - // NewProbationList returns a new probation list func NewProbationList(intensity uint32) *ProbationList { return &ProbationList{ diff --git a/action/protocol/vote/unproductivedelegate.go b/action/protocol/vote/unproductivedelegate.go index c4a0bf0987..afe05612a0 100644 --- a/action/protocol/vote/unproductivedelegate.go +++ b/action/protocol/vote/unproductivedelegate.go @@ -11,10 +11,7 @@ import ( "github.com/pkg/errors" "google.golang.org/protobuf/proto" - "github.com/iotexproject/iotex-core/v2/action/protocol" updpb "github.com/iotexproject/iotex-core/v2/action/protocol/vote/unproductivedelegatepb" - "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" - "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -25,10 +22,6 @@ type UnproductiveDelegate struct { cacheSize uint64 } -func init() { - assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterObjectStorage(protocol.SystemNamespace, &UnproductiveDelegate{}, erigonstore.PollUnproductiveDelegateContractIndex)) -} - // NewUnproductiveDelegate creates new UnproductiveDelegate with probationperiod and cacheSize func NewUnproductiveDelegate(probationPeriod uint64, cacheSize uint64) (*UnproductiveDelegate, error) { if probationPeriod > cacheSize { diff --git a/go.mod b/go.mod index e096d2e99a..aa23e34054 100644 --- a/go.mod +++ b/go.mod @@ -241,7 +241,7 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/gogo/protobuf v1.3.2 + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gopacket v1.1.19 // indirect diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go index 4024e07369..b7df0b71c1 100644 --- a/state/factory/erigonstore/registry.go +++ b/state/factory/erigonstore/registry.go @@ -6,6 +6,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/iotexproject/iotex-core/v2/action/protocol/poll" + "github.com/iotexproject/iotex-core/v2/action/protocol/staking" + "github.com/iotexproject/iotex-core/v2/action/protocol/vote" "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/systemcontracts" @@ -29,13 +32,21 @@ type ObjectStorageRegistry struct { } func init() { + assertions.MustNoError(storageRegistry.RegisterNamespace(state.AccountKVNamespace, RewardingContractV1Index)) assertions.MustNoError(storageRegistry.RegisterNamespace(state.RewardingNamespace, RewardingContractV2Index)) assertions.MustNoError(storageRegistry.RegisterNamespace(state.CandidateNamespace, CandidatesContractIndex)) assertions.MustNoError(storageRegistry.RegisterNamespace(state.CandsMapNamespace, CandidateMapContractIndex)) + assertions.MustNoError(storageRegistry.RegisterNamespace(state.StakingNamespace, BucketPoolContractIndex)) assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.AccountKVNamespace, &state.Account{}, AccountIndex)) - assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &state.CandidateList{}, PollCandidateListContractIndex)) assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.AccountKVNamespace, &state.CandidateList{}, PollLegacyCandidateListContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &state.CandidateList{}, PollCandidateListContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &vote.UnproductiveDelegate{}, PollUnproductiveDelegateContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &vote.ProbationList{}, PollProbationListContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.SystemNamespace, &poll.BlockMeta{}, PollBlockMetaContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.StakingNamespace, &staking.VoteBucket{}, StakingBucketsContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.StakingNamespace, &staking.Endorsement{}, EndorsementContractIndex)) + assertions.MustNoError(storageRegistry.RegisterObjectStorage(state.StakingNamespace, &staking.BucketIndices{}, BucketIndicesContractIndex)) } // GetObjectStorageRegistry returns the global object storage registry @@ -117,14 +128,15 @@ func (osr *ObjectStorageRegistry) register(ns string, obj any, index int) error } func (osr *ObjectStorageRegistry) matchContractIndex(ns string, obj any) (int, bool) { - if obj == nil { - index, exist := osr.fallback[ns] - return index, exist - } - types, ok := osr.contracts[ns] - if !ok { - return 0, false + if obj != nil { + types, ok := osr.contracts[ns] + if ok { + index, exist := types[reflect.TypeOf(obj)] + if exist { + return index, true + } + } } - index, exist := types[reflect.TypeOf(obj)] + index, exist := osr.fallback[ns] return index, exist } diff --git a/state/factory/workingsetstore_test.go b/state/factory/workingsetstore_test.go index de104e6e5b..098cea7884 100644 --- a/state/factory/workingsetstore_test.go +++ b/state/factory/workingsetstore_test.go @@ -52,7 +52,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { var value valueBytes err := store.GetObject(namespace, key1, &value) require.Error(err) - require.NoError(store.DeleteObject(namespace, key1, &value)) + require.NoError(store.DeleteObject(namespace, key1, nil)) require.NoError(store.PutObject(namespace, key1, &value1)) var valueInStore valueBytes err = store.GetObject(namespace, key1, &valueInStore) @@ -88,7 +88,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { require.Equal("e1f83be0a44ae601061724990036b8a40edbf81cffc639657c9bb2c5d384defa", hex.EncodeToString(h[:])) }) sn3 := store.Snapshot() - require.NoError(store.DeleteObject(namespace, key1, &valueInStore)) + require.NoError(store.DeleteObject(namespace, key1, nil)) err = store.GetObject(namespace, key1, &valueInStore) require.Error(err) iter, err = store.States(namespace, &valueInStore, [][]byte{key1, key2, key3})