From 955313eaa6d47c7862568b877d9fc63cf97bea98 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 19 May 2023 20:02:06 +0800 Subject: [PATCH 1/4] contractstaking bucket definition --- .../staking/contractstaking/bucket.go | 26 ++ .../staking/contractstaking/bucket_info.go | 69 +++++ .../staking/contractstaking/bucket_type.go | 58 ++++ .../contractstakingpb/contractstaking.pb.go | 293 ++++++++++++++++++ .../contractstakingpb/contractstaking.proto | 25 ++ 5 files changed, 471 insertions(+) create mode 100644 action/protocol/staking/contractstaking/bucket.go create mode 100644 action/protocol/staking/contractstaking/bucket_info.go create mode 100644 action/protocol/staking/contractstaking/bucket_type.go create mode 100644 action/protocol/staking/contractstaking/contractstakingpb/contractstaking.pb.go create mode 100644 action/protocol/staking/contractstaking/contractstakingpb/contractstaking.proto diff --git a/action/protocol/staking/contractstaking/bucket.go b/action/protocol/staking/contractstaking/bucket.go new file mode 100644 index 0000000000..75548071ae --- /dev/null +++ b/action/protocol/staking/contractstaking/bucket.go @@ -0,0 +1,26 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package contractstaking + +import ( + "math/big" + + "github.com/iotexproject/iotex-address/address" +) + +// Bucket defines the bucket struct for contract staking +type Bucket struct { + Index uint64 + Candidate address.Address + Owner address.Address + StakedAmount *big.Int + StakedDurationBlockNumber uint64 + CreateBlockHeight uint64 + StakeStartBlockHeight uint64 + UnstakeStartBlockHeight uint64 + AutoStake bool + ContractAddress string +} diff --git a/action/protocol/staking/contractstaking/bucket_info.go b/action/protocol/staking/contractstaking/bucket_info.go new file mode 100644 index 0000000000..ab23043c5f --- /dev/null +++ b/action/protocol/staking/contractstaking/bucket_info.go @@ -0,0 +1,69 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package contractstaking + +import ( + "github.com/iotexproject/iotex-address/address" + "google.golang.org/protobuf/proto" + + "github.com/iotexproject/iotex-core/action/protocol/staking/contractstaking/contractstakingpb" + "github.com/iotexproject/iotex-core/pkg/util/byteutil" +) + +type ( + // bucketInfo is the bucket information + bucketInfo struct { + TypeIndex uint64 + CreatedAt uint64 + UnlockedAt uint64 + UnstakedAt uint64 + Delegate address.Address // owner address of the delegate + Owner address.Address + } +) + +func (bi *bucketInfo) toProto() *contractstakingpb.BucketInfo { + pb := &contractstakingpb.BucketInfo{ + TypeIndex: bi.TypeIndex, + Delegate: bi.Delegate.String(), + CreatedAt: bi.CreatedAt, + Owner: bi.Owner.String(), + UnlockedAt: bi.UnlockedAt, + UnstakedAt: bi.UnstakedAt, + } + return pb +} + +// Serialize serializes the bucket info +func (bi *bucketInfo) Serialize() []byte { + return byteutil.Must(proto.Marshal(bi.toProto())) +} + +// Deserialize deserializes the bucket info +func (bi *bucketInfo) Deserialize(b []byte) error { + m := contractstakingpb.BucketInfo{} + if err := proto.Unmarshal(b, &m); err != nil { + return err + } + return bi.loadProto(&m) +} + +func (bi *bucketInfo) loadProto(p *contractstakingpb.BucketInfo) error { + var err error + bi.TypeIndex = p.TypeIndex + bi.CreatedAt = p.CreatedAt + bi.UnlockedAt = p.UnlockedAt + bi.UnstakedAt = p.UnstakedAt + bi.Delegate, err = address.FromString(p.Delegate) + if err != nil { + return err + } + bi.Owner, err = address.FromString(p.Owner) + if err != nil { + return err + } + return nil +} diff --git a/action/protocol/staking/contractstaking/bucket_type.go b/action/protocol/staking/contractstaking/bucket_type.go new file mode 100644 index 0000000000..f26fc5ee14 --- /dev/null +++ b/action/protocol/staking/contractstaking/bucket_type.go @@ -0,0 +1,58 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package contractstaking + +import ( + "math/big" + + "github.com/pkg/errors" + "google.golang.org/protobuf/proto" + + "github.com/iotexproject/iotex-core/action/protocol/staking/contractstaking/contractstakingpb" + "github.com/iotexproject/iotex-core/pkg/util/byteutil" +) + +type ( + // BucketType defines the type of contract staking bucket + BucketType struct { + Amount *big.Int + Duration uint64 // block numbers + ActivatedAt uint64 // block height + } +) + +func (bt *BucketType) toProto() *contractstakingpb.BucketType { + return &contractstakingpb.BucketType{ + Amount: bt.Amount.String(), + Duration: bt.Duration, + ActivatedAt: bt.ActivatedAt, + } +} + +func (bt *BucketType) loadProto(p *contractstakingpb.BucketType) error { + var ok bool + bt.Amount, ok = big.NewInt(0).SetString(p.Amount, 10) + if !ok { + return errors.New("failed to parse amount") + } + bt.Duration = p.Duration + bt.ActivatedAt = p.ActivatedAt + return nil +} + +// Serialize serializes the bucket type +func (bt *BucketType) Serialize() []byte { + return byteutil.Must(proto.Marshal(bt.toProto())) +} + +// Deserialize deserializes the bucket type +func (bt *BucketType) Deserialize(b []byte) error { + m := contractstakingpb.BucketType{} + if err := proto.Unmarshal(b, &m); err != nil { + return err + } + return bt.loadProto(&m) +} diff --git a/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.pb.go b/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.pb.go new file mode 100644 index 0000000000..506a53a29a --- /dev/null +++ b/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.pb.go @@ -0,0 +1,293 @@ +// Copyright (c) 2019 IoTeX +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +// To compile the proto, run: +// protoc --go_out=plugins=grpc:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.21.12 +// source: action/protocol/staking/contractstaking/contractstakingpb/contractstaking.proto + +package contractstakingpb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BucketType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Amount string `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount,omitempty"` + Duration uint64 `protobuf:"varint,2,opt,name=duration,proto3" json:"duration,omitempty"` + ActivatedAt uint64 `protobuf:"varint,3,opt,name=activatedAt,proto3" json:"activatedAt,omitempty"` +} + +func (x *BucketType) Reset() { + *x = BucketType{} + if protoimpl.UnsafeEnabled { + mi := &file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BucketType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BucketType) ProtoMessage() {} + +func (x *BucketType) ProtoReflect() protoreflect.Message { + mi := &file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BucketType.ProtoReflect.Descriptor instead. +func (*BucketType) Descriptor() ([]byte, []int) { + return file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescGZIP(), []int{0} +} + +func (x *BucketType) GetAmount() string { + if x != nil { + return x.Amount + } + return "" +} + +func (x *BucketType) GetDuration() uint64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *BucketType) GetActivatedAt() uint64 { + if x != nil { + return x.ActivatedAt + } + return 0 +} + +type BucketInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TypeIndex uint64 `protobuf:"varint,1,opt,name=typeIndex,proto3" json:"typeIndex,omitempty"` + CreatedAt uint64 `protobuf:"varint,2,opt,name=createdAt,proto3" json:"createdAt,omitempty"` + UnlockedAt uint64 `protobuf:"varint,3,opt,name=unlockedAt,proto3" json:"unlockedAt,omitempty"` + UnstakedAt uint64 `protobuf:"varint,4,opt,name=unstakedAt,proto3" json:"unstakedAt,omitempty"` + Delegate string `protobuf:"bytes,5,opt,name=delegate,proto3" json:"delegate,omitempty"` + Owner string `protobuf:"bytes,6,opt,name=owner,proto3" json:"owner,omitempty"` +} + +func (x *BucketInfo) Reset() { + *x = BucketInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BucketInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BucketInfo) ProtoMessage() {} + +func (x *BucketInfo) ProtoReflect() protoreflect.Message { + mi := &file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BucketInfo.ProtoReflect.Descriptor instead. +func (*BucketInfo) Descriptor() ([]byte, []int) { + return file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescGZIP(), []int{1} +} + +func (x *BucketInfo) GetTypeIndex() uint64 { + if x != nil { + return x.TypeIndex + } + return 0 +} + +func (x *BucketInfo) GetCreatedAt() uint64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +func (x *BucketInfo) GetUnlockedAt() uint64 { + if x != nil { + return x.UnlockedAt + } + return 0 +} + +func (x *BucketInfo) GetUnstakedAt() uint64 { + if x != nil { + return x.UnstakedAt + } + return 0 +} + +func (x *BucketInfo) GetDelegate() string { + if x != nil { + return x.Delegate + } + return "" +} + +func (x *BucketInfo) GetOwner() string { + if x != nil { + return x.Owner + } + return "" +} + +var File_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto protoreflect.FileDescriptor + +var file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDesc = []byte{ + 0x0a, 0x4f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x70, 0x62, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, 0x69, + 0x6e, 0x67, 0x70, 0x62, 0x22, 0x62, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x61, 0x63, 0x74, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0a, 0x42, 0x75, 0x63, + 0x6b, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x79, 0x70, 0x65, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x41, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x64, 0x41, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x6b, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6f, 0x74, 0x65, 0x78, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x2f, 0x69, 0x6f, 0x74, 0x65, 0x78, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x74, 0x61, 0x6b, + 0x69, 0x6e, 0x67, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescOnce sync.Once + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescData = file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDesc +) + +func file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescGZIP() []byte { + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescOnce.Do(func() { + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescData = protoimpl.X.CompressGZIP(file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescData) + }) + return file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDescData +} + +var file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_goTypes = []interface{}{ + (*BucketType)(nil), // 0: contractstakingpb.BucketType + (*BucketInfo)(nil), // 1: contractstakingpb.BucketInfo +} +var file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_init() +} +func file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_init() { + if File_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BucketType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BucketInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_goTypes, + DependencyIndexes: file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_depIdxs, + MessageInfos: file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_msgTypes, + }.Build() + File_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto = out.File + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_rawDesc = nil + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_goTypes = nil + file_action_protocol_staking_contractstaking_contractstakingpb_contractstaking_proto_depIdxs = nil +} diff --git a/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.proto b/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.proto new file mode 100644 index 0000000000..fa29ea5609 --- /dev/null +++ b/action/protocol/staking/contractstaking/contractstakingpb/contractstaking.proto @@ -0,0 +1,25 @@ +// Copyright (c) 2019 IoTeX +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +// To compile the proto, run: +// protoc --go_out=plugins=grpc:. *.proto +syntax = "proto3"; +package contractstakingpb; +option go_package = "github.com/iotexproject/iotex-core/action/protocol/staking/contractstaking/contractstakingpb"; + +message BucketType { + string amount = 1; + uint64 duration = 2; + uint64 activatedAt = 3; +} + +message BucketInfo { + uint64 typeIndex = 1; + uint64 createdAt = 2; + uint64 unlockedAt = 3; + uint64 unstakedAt = 4; + string delegate = 5; + string owner = 6; +} \ No newline at end of file From 37b2ea66776b077d0f74c281296e3102dfae3331 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 19 May 2023 20:52:03 +0800 Subject: [PATCH 2/4] indexer read --- .../staking/contractstaking/bucket.go | 19 ++ .../protocol/staking/contractstaking/cache.go | 188 ++++++++++++++++++ .../staking/contractstaking/indexer.go | 93 +++++++++ 3 files changed, 300 insertions(+) create mode 100644 action/protocol/staking/contractstaking/cache.go create mode 100644 action/protocol/staking/contractstaking/indexer.go diff --git a/action/protocol/staking/contractstaking/bucket.go b/action/protocol/staking/contractstaking/bucket.go index 75548071ae..0e34336acc 100644 --- a/action/protocol/staking/contractstaking/bucket.go +++ b/action/protocol/staking/contractstaking/bucket.go @@ -24,3 +24,22 @@ type Bucket struct { AutoStake bool ContractAddress string } + +func assembleBucket(token uint64, bi *bucketInfo, bt *BucketType) (*Bucket, error) { + vb := Bucket{ + Index: token, + StakedAmount: bt.Amount, + StakedDurationBlockNumber: bt.Duration, + CreateBlockHeight: bi.CreatedAt, + StakeStartBlockHeight: bi.CreatedAt, + UnstakeStartBlockHeight: bi.UnstakedAt, + AutoStake: bi.UnlockedAt == maxBlockNumber, + Candidate: bi.Delegate, + Owner: bi.Owner, + ContractAddress: StakingContractAddress, + } + if bi.UnlockedAt != maxBlockNumber { + vb.StakeStartBlockHeight = bi.UnlockedAt + } + return &vb, nil +} diff --git a/action/protocol/staking/contractstaking/cache.go b/action/protocol/staking/contractstaking/cache.go new file mode 100644 index 0000000000..b3e1de5348 --- /dev/null +++ b/action/protocol/staking/contractstaking/cache.go @@ -0,0 +1,188 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package contractstaking + +import ( + "math/big" + + "github.com/iotexproject/iotex-address/address" + "github.com/pkg/errors" +) + +type ( + contractStakingCache struct { + idBucketMap map[uint64]*bucketInfo // map[token]bucketInfo + candidateBucketMap map[string]map[uint64]bool // map[candidate]bucket + idBucketTypeMap map[uint64]*BucketType // map[token]BucketType + propertyBucketTypeMap map[int64]map[uint64]uint64 // map[amount][duration]index + height uint64 + totalBucketCount uint64 // total number of buckets including burned buckets + } +) + +var ( + // ErrBucketNotExist is the error when bucket does not exist + ErrBucketNotExist = errors.New("bucket does not exist") +) + +func newContractStakingCache() *contractStakingCache { + cache := &contractStakingCache{ + idBucketMap: make(map[uint64]*bucketInfo), + idBucketTypeMap: make(map[uint64]*BucketType), + propertyBucketTypeMap: make(map[int64]map[uint64]uint64), + candidateBucketMap: make(map[string]map[uint64]bool), + } + return cache +} + +func (s *contractStakingCache) GetHeight() uint64 { + return s.height +} + +func (s *contractStakingCache) GetCandidateVotes(candidate address.Address) *big.Int { + votes := big.NewInt(0) + m, ok := s.candidateBucketMap[candidate.String()] + if !ok { + return votes + } + for id, existed := range m { + if !existed { + continue + } + bi, ok := s.idBucketMap[id] + if !ok { + continue + } + if bi.UnstakedAt != maxBlockNumber { + continue + } + bt := s.mustGetBucketType(bi.TypeIndex) + votes.Add(votes, bt.Amount) + } + return votes +} + +func (s *contractStakingCache) GetBuckets() ([]*Bucket, error) { + vbs := []*Bucket{} + for id, bi := range s.getAllBucketInfo() { + bt := s.mustGetBucketType(bi.TypeIndex) + vb, err := assembleBucket(id, bi, bt) + if err != nil { + return nil, err + } + vbs = append(vbs, vb) + } + return vbs, nil +} + +func (s *contractStakingCache) GetBucket(id uint64) (*Bucket, error) { + return s.getBucket(id) +} + +func (s *contractStakingCache) GetBucketsByCandidate(candidate address.Address) ([]*Bucket, error) { + bucketMap := s.getBucketInfoByCandidate(candidate) + vbs := make([]*Bucket, 0, len(bucketMap)) + for id := range bucketMap { + vb, err := s.getBucket(id) + if err != nil { + return nil, err + } + vbs = append(vbs, vb) + } + return vbs, nil +} + +func (s *contractStakingCache) GetBucketsByIndices(indices []uint64) ([]*Bucket, error) { + vbs := make([]*Bucket, 0, len(indices)) + for _, id := range indices { + vb, err := s.getBucket(id) + if err != nil { + return nil, err + } + vbs = append(vbs, vb) + } + return vbs, nil +} + +func (s *contractStakingCache) GetTotalBucketCount() uint64 { + return s.totalBucketCount +} + +func (s *contractStakingCache) GetActiveBucketTypes() map[uint64]*BucketType { + m := make(map[uint64]*BucketType) + for k, v := range s.idBucketTypeMap { + if v.ActivatedAt != maxBlockNumber { + m[k] = v + } + } + return m +} + +func (s *contractStakingCache) getBucketTypeIndex(amount *big.Int, duration uint64) (uint64, bool) { + m, ok := s.propertyBucketTypeMap[amount.Int64()] + if !ok { + return 0, false + } + id, ok := m[duration] + return id, ok +} + +func (s *contractStakingCache) getBucketType(id uint64) (*BucketType, bool) { + bt, ok := s.idBucketTypeMap[id] + return bt, ok +} + +func (s *contractStakingCache) mustGetBucketType(id uint64) *BucketType { + bt, ok := s.idBucketTypeMap[id] + if !ok { + panic("bucket type not found") + } + return bt +} + +func (s *contractStakingCache) getBucketInfo(id uint64) (*bucketInfo, bool) { + bi, ok := s.idBucketMap[id] + return bi, ok +} + +func (s *contractStakingCache) mustGetBucketInfo(id uint64) *bucketInfo { + bt, ok := s.idBucketMap[id] + if !ok { + panic("bucket info not found") + } + return bt +} + +func (s *contractStakingCache) getBucket(id uint64) (*Bucket, error) { + bi, ok := s.getBucketInfo(id) + if !ok { + return nil, errors.Wrapf(ErrBucketNotExist, "id %d", id) + } + bt := s.mustGetBucketType(bi.TypeIndex) + return assembleBucket(id, bi, bt) +} + +func (s *contractStakingCache) getTotalBucketTypeCount() uint64 { + return uint64(len(s.idBucketTypeMap)) +} + +func (s *contractStakingCache) getAllBucketInfo() map[uint64]*bucketInfo { + m := make(map[uint64]*bucketInfo) + for k, v := range s.idBucketMap { + m[k] = v + } + return m +} + +func (s *contractStakingCache) getBucketInfoByCandidate(candidate address.Address) map[uint64]*bucketInfo { + m := make(map[uint64]*bucketInfo) + for k, v := range s.candidateBucketMap[candidate.String()] { + if v { + m[k] = s.idBucketMap[k] + } + } + return m +} diff --git a/action/protocol/staking/contractstaking/indexer.go b/action/protocol/staking/contractstaking/indexer.go new file mode 100644 index 0000000000..3a4c3164e4 --- /dev/null +++ b/action/protocol/staking/contractstaking/indexer.go @@ -0,0 +1,93 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package contractstaking + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common/math" + "github.com/iotexproject/iotex-address/address" + + "github.com/iotexproject/iotex-core/db" +) + +const ( + // StakingContractAddress is the address of system staking contract + // TODO (iip-13): replace with the real system staking contract address + StakingContractAddress = "io19ys8f4uhwms6lq6ulexr5fwht9gsjes8mvuugd" + + maxBlockNumber uint64 = math.MaxUint64 +) + +type ( + // Indexer is the contract staking indexer + // Main functions: + // 1. handle contract staking contract events when new block comes to generate index data + // 2. provide query interface for contract staking index data + // Generate index data flow: + // block comes -> new dirty cache -> handle contract events -> update dirty cache -> merge dirty to clean cache + // Main Object: + // kvstore: persistent storage, used to initialize index cache at startup + // cache: in-memory index for clean data, used to query index data + // dirty: the cache to update during event processing, will be merged to clean cache after all events are processed. If errors occur during event processing, dirty cache will be discarded. + Indexer struct { + kvstore db.KVStore // persistent storage + cache *contractStakingCache // in-memory index for clean data + } +) + +// NewContractStakingIndexer creates a new contract staking indexer +func NewContractStakingIndexer(kvStore db.KVStore) *Indexer { + return &Indexer{ + kvstore: kvStore, + cache: newContractStakingCache(), + } +} + +// Height returns the tip block height +func (s *Indexer) Height() (uint64, error) { + return s.cache.GetHeight(), nil +} + +// CandidateVotes returns the candidate votes +func (s *Indexer) CandidateVotes(candidate address.Address) *big.Int { + return s.cache.GetCandidateVotes(candidate) +} + +// Buckets returns the buckets +func (s *Indexer) Buckets() ([]*Bucket, error) { + return s.cache.GetBuckets() +} + +// Bucket returns the bucket +func (s *Indexer) Bucket(id uint64) (*Bucket, error) { + return s.cache.GetBucket(id) +} + +// BucketsByIndices returns the buckets by indices +func (s *Indexer) BucketsByIndices(indices []uint64) ([]*Bucket, error) { + return s.cache.GetBucketsByIndices(indices) +} + +// BucketsByCandidate returns the buckets by candidate +func (s *Indexer) BucketsByCandidate(candidate address.Address) ([]*Bucket, error) { + return s.cache.GetBucketsByCandidate(candidate) +} + +// TotalBucketCount returns the total bucket count including active and burnt buckets +func (s *Indexer) TotalBucketCount() uint64 { + return s.cache.GetTotalBucketCount() +} + +// BucketTypes returns the active bucket types +func (s *Indexer) BucketTypes() ([]*BucketType, error) { + btMap := s.cache.GetActiveBucketTypes() + bts := make([]*BucketType, 0, len(btMap)) + for _, bt := range btMap { + bts = append(bts, bt) + } + return bts, nil +} From 7a745bd0872c2352a4e3fc306f1e5cf317f7d209 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 22 May 2023 17:02:56 +0800 Subject: [PATCH 3/4] address comments --- .../staking/contractstaking/bucket.go | 2 +- .../staking/contractstaking/bucket_info.go | 39 ++++++++++--------- .../staking/contractstaking/bucket_type.go | 32 +++++++-------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/action/protocol/staking/contractstaking/bucket.go b/action/protocol/staking/contractstaking/bucket.go index 75548071ae..ba7866d0da 100644 --- a/action/protocol/staking/contractstaking/bucket.go +++ b/action/protocol/staking/contractstaking/bucket.go @@ -22,5 +22,5 @@ type Bucket struct { StakeStartBlockHeight uint64 UnstakeStartBlockHeight uint64 AutoStake bool - ContractAddress string + ContractAddress string // contract address for the bucket } diff --git a/action/protocol/staking/contractstaking/bucket_info.go b/action/protocol/staking/contractstaking/bucket_info.go index ab23043c5f..8683a66880 100644 --- a/action/protocol/staking/contractstaking/bucket_info.go +++ b/action/protocol/staking/contractstaking/bucket_info.go @@ -25,18 +25,6 @@ type ( } ) -func (bi *bucketInfo) toProto() *contractstakingpb.BucketInfo { - pb := &contractstakingpb.BucketInfo{ - TypeIndex: bi.TypeIndex, - Delegate: bi.Delegate.String(), - CreatedAt: bi.CreatedAt, - Owner: bi.Owner.String(), - UnlockedAt: bi.UnlockedAt, - UnstakedAt: bi.UnstakedAt, - } - return pb -} - // Serialize serializes the bucket info func (bi *bucketInfo) Serialize() []byte { return byteutil.Must(proto.Marshal(bi.toProto())) @@ -51,19 +39,32 @@ func (bi *bucketInfo) Deserialize(b []byte) error { return bi.loadProto(&m) } +func (bi *bucketInfo) toProto() *contractstakingpb.BucketInfo { + pb := &contractstakingpb.BucketInfo{ + TypeIndex: bi.TypeIndex, + Delegate: bi.Delegate.String(), + CreatedAt: bi.CreatedAt, + Owner: bi.Owner.String(), + UnlockedAt: bi.UnlockedAt, + UnstakedAt: bi.UnstakedAt, + } + return pb +} + func (bi *bucketInfo) loadProto(p *contractstakingpb.BucketInfo) error { - var err error - bi.TypeIndex = p.TypeIndex - bi.CreatedAt = p.CreatedAt - bi.UnlockedAt = p.UnlockedAt - bi.UnstakedAt = p.UnstakedAt - bi.Delegate, err = address.FromString(p.Delegate) + delegate, err := address.FromString(p.Delegate) if err != nil { return err } - bi.Owner, err = address.FromString(p.Owner) + owner, err := address.FromString(p.Owner) if err != nil { return err } + bi.TypeIndex = p.TypeIndex + bi.CreatedAt = p.CreatedAt + bi.UnlockedAt = p.UnlockedAt + bi.UnstakedAt = p.UnstakedAt + bi.Delegate = delegate + bi.Owner = owner return nil } diff --git a/action/protocol/staking/contractstaking/bucket_type.go b/action/protocol/staking/contractstaking/bucket_type.go index f26fc5ee14..98fca73346 100644 --- a/action/protocol/staking/contractstaking/bucket_type.go +++ b/action/protocol/staking/contractstaking/bucket_type.go @@ -24,6 +24,20 @@ type ( } ) +// Serialize serializes the bucket type +func (bt *BucketType) Serialize() []byte { + return byteutil.Must(proto.Marshal(bt.toProto())) +} + +// Deserialize deserializes the bucket type +func (bt *BucketType) Deserialize(b []byte) error { + m := contractstakingpb.BucketType{} + if err := proto.Unmarshal(b, &m); err != nil { + return err + } + return bt.loadProto(&m) +} + func (bt *BucketType) toProto() *contractstakingpb.BucketType { return &contractstakingpb.BucketType{ Amount: bt.Amount.String(), @@ -33,26 +47,12 @@ func (bt *BucketType) toProto() *contractstakingpb.BucketType { } func (bt *BucketType) loadProto(p *contractstakingpb.BucketType) error { - var ok bool - bt.Amount, ok = big.NewInt(0).SetString(p.Amount, 10) + amount, ok := big.NewInt(0).SetString(p.Amount, 10) if !ok { return errors.New("failed to parse amount") } + bt.Amount = amount bt.Duration = p.Duration bt.ActivatedAt = p.ActivatedAt return nil } - -// Serialize serializes the bucket type -func (bt *BucketType) Serialize() []byte { - return byteutil.Must(proto.Marshal(bt.toProto())) -} - -// Deserialize deserializes the bucket type -func (bt *BucketType) Deserialize(b []byte) error { - m := contractstakingpb.BucketType{} - if err := proto.Unmarshal(b, &m); err != nil { - return err - } - return bt.loadProto(&m) -} From 8c1f5a082b27f8c4c26208d55c43d70256466028 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 22 May 2023 17:37:49 +0800 Subject: [PATCH 4/4] address comments --- .../staking/contractstaking/bucket.go | 4 +- .../protocol/staking/contractstaking/cache.go | 54 +++++++++---------- .../staking/contractstaking/indexer.go | 35 +++++------- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/action/protocol/staking/contractstaking/bucket.go b/action/protocol/staking/contractstaking/bucket.go index b663c8dd92..f83edb4d4f 100644 --- a/action/protocol/staking/contractstaking/bucket.go +++ b/action/protocol/staking/contractstaking/bucket.go @@ -25,7 +25,7 @@ type Bucket struct { ContractAddress string // contract address for the bucket } -func assembleBucket(token uint64, bi *bucketInfo, bt *BucketType) (*Bucket, error) { +func assembleBucket(token uint64, bi *bucketInfo, bt *BucketType, contractAddr string) (*Bucket, error) { vb := Bucket{ Index: token, StakedAmount: bt.Amount, @@ -36,7 +36,7 @@ func assembleBucket(token uint64, bi *bucketInfo, bt *BucketType) (*Bucket, erro AutoStake: bi.UnlockedAt == maxBlockNumber, Candidate: bi.Delegate, Owner: bi.Owner, - ContractAddress: StakingContractAddress, + ContractAddress: contractAddr, } if bi.UnlockedAt != maxBlockNumber { vb.StakeStartBlockHeight = bi.UnlockedAt diff --git a/action/protocol/staking/contractstaking/cache.go b/action/protocol/staking/contractstaking/cache.go index b3e1de5348..43ed459b56 100644 --- a/action/protocol/staking/contractstaking/cache.go +++ b/action/protocol/staking/contractstaking/cache.go @@ -14,12 +14,13 @@ import ( type ( contractStakingCache struct { - idBucketMap map[uint64]*bucketInfo // map[token]bucketInfo + bucketInfoMap map[uint64]*bucketInfo // map[token]bucketInfo candidateBucketMap map[string]map[uint64]bool // map[candidate]bucket - idBucketTypeMap map[uint64]*BucketType // map[token]BucketType + bucketTypeMap map[uint64]*BucketType // map[bucketTypeId]BucketType propertyBucketTypeMap map[int64]map[uint64]uint64 // map[amount][duration]index height uint64 totalBucketCount uint64 // total number of buckets including burned buckets + contractAddress string // contract address for the bucket } ) @@ -28,21 +29,22 @@ var ( ErrBucketNotExist = errors.New("bucket does not exist") ) -func newContractStakingCache() *contractStakingCache { +func newContractStakingCache(contractAddr string) *contractStakingCache { cache := &contractStakingCache{ - idBucketMap: make(map[uint64]*bucketInfo), - idBucketTypeMap: make(map[uint64]*BucketType), + bucketInfoMap: make(map[uint64]*bucketInfo), + bucketTypeMap: make(map[uint64]*BucketType), propertyBucketTypeMap: make(map[int64]map[uint64]uint64), candidateBucketMap: make(map[string]map[uint64]bool), + contractAddress: contractAddr, } return cache } -func (s *contractStakingCache) GetHeight() uint64 { +func (s *contractStakingCache) Height() uint64 { return s.height } -func (s *contractStakingCache) GetCandidateVotes(candidate address.Address) *big.Int { +func (s *contractStakingCache) CandidateVotes(candidate address.Address) *big.Int { votes := big.NewInt(0) m, ok := s.candidateBucketMap[candidate.String()] if !ok { @@ -52,10 +54,8 @@ func (s *contractStakingCache) GetCandidateVotes(candidate address.Address) *big if !existed { continue } - bi, ok := s.idBucketMap[id] - if !ok { - continue - } + bi := s.mustGetBucketInfo(id) + // only count the bucket that is not unstaked if bi.UnstakedAt != maxBlockNumber { continue } @@ -65,11 +65,11 @@ func (s *contractStakingCache) GetCandidateVotes(candidate address.Address) *big return votes } -func (s *contractStakingCache) GetBuckets() ([]*Bucket, error) { +func (s *contractStakingCache) Buckets() ([]*Bucket, error) { vbs := []*Bucket{} for id, bi := range s.getAllBucketInfo() { bt := s.mustGetBucketType(bi.TypeIndex) - vb, err := assembleBucket(id, bi, bt) + vb, err := assembleBucket(id, bi, bt, s.contractAddress) if err != nil { return nil, err } @@ -78,11 +78,11 @@ func (s *contractStakingCache) GetBuckets() ([]*Bucket, error) { return vbs, nil } -func (s *contractStakingCache) GetBucket(id uint64) (*Bucket, error) { +func (s *contractStakingCache) Bucket(id uint64) (*Bucket, error) { return s.getBucket(id) } -func (s *contractStakingCache) GetBucketsByCandidate(candidate address.Address) ([]*Bucket, error) { +func (s *contractStakingCache) BucketsByCandidate(candidate address.Address) ([]*Bucket, error) { bucketMap := s.getBucketInfoByCandidate(candidate) vbs := make([]*Bucket, 0, len(bucketMap)) for id := range bucketMap { @@ -95,7 +95,7 @@ func (s *contractStakingCache) GetBucketsByCandidate(candidate address.Address) return vbs, nil } -func (s *contractStakingCache) GetBucketsByIndices(indices []uint64) ([]*Bucket, error) { +func (s *contractStakingCache) BucketsByIndices(indices []uint64) ([]*Bucket, error) { vbs := make([]*Bucket, 0, len(indices)) for _, id := range indices { vb, err := s.getBucket(id) @@ -107,13 +107,13 @@ func (s *contractStakingCache) GetBucketsByIndices(indices []uint64) ([]*Bucket, return vbs, nil } -func (s *contractStakingCache) GetTotalBucketCount() uint64 { +func (s *contractStakingCache) TotalBucketCount() uint64 { return s.totalBucketCount } -func (s *contractStakingCache) GetActiveBucketTypes() map[uint64]*BucketType { +func (s *contractStakingCache) ActiveBucketTypes() map[uint64]*BucketType { m := make(map[uint64]*BucketType) - for k, v := range s.idBucketTypeMap { + for k, v := range s.bucketTypeMap { if v.ActivatedAt != maxBlockNumber { m[k] = v } @@ -131,12 +131,12 @@ func (s *contractStakingCache) getBucketTypeIndex(amount *big.Int, duration uint } func (s *contractStakingCache) getBucketType(id uint64) (*BucketType, bool) { - bt, ok := s.idBucketTypeMap[id] + bt, ok := s.bucketTypeMap[id] return bt, ok } func (s *contractStakingCache) mustGetBucketType(id uint64) *BucketType { - bt, ok := s.idBucketTypeMap[id] + bt, ok := s.bucketTypeMap[id] if !ok { panic("bucket type not found") } @@ -144,12 +144,12 @@ func (s *contractStakingCache) mustGetBucketType(id uint64) *BucketType { } func (s *contractStakingCache) getBucketInfo(id uint64) (*bucketInfo, bool) { - bi, ok := s.idBucketMap[id] + bi, ok := s.bucketInfoMap[id] return bi, ok } func (s *contractStakingCache) mustGetBucketInfo(id uint64) *bucketInfo { - bt, ok := s.idBucketMap[id] + bt, ok := s.bucketInfoMap[id] if !ok { panic("bucket info not found") } @@ -162,16 +162,16 @@ func (s *contractStakingCache) getBucket(id uint64) (*Bucket, error) { return nil, errors.Wrapf(ErrBucketNotExist, "id %d", id) } bt := s.mustGetBucketType(bi.TypeIndex) - return assembleBucket(id, bi, bt) + return assembleBucket(id, bi, bt, s.contractAddress) } func (s *contractStakingCache) getTotalBucketTypeCount() uint64 { - return uint64(len(s.idBucketTypeMap)) + return uint64(len(s.bucketTypeMap)) } func (s *contractStakingCache) getAllBucketInfo() map[uint64]*bucketInfo { m := make(map[uint64]*bucketInfo) - for k, v := range s.idBucketMap { + for k, v := range s.bucketInfoMap { m[k] = v } return m @@ -181,7 +181,7 @@ func (s *contractStakingCache) getBucketInfoByCandidate(candidate address.Addres m := make(map[uint64]*bucketInfo) for k, v := range s.candidateBucketMap[candidate.String()] { if v { - m[k] = s.idBucketMap[k] + m[k] = s.bucketInfoMap[k] } } return m diff --git a/action/protocol/staking/contractstaking/indexer.go b/action/protocol/staking/contractstaking/indexer.go index 3a4c3164e4..876f99b178 100644 --- a/action/protocol/staking/contractstaking/indexer.go +++ b/action/protocol/staking/contractstaking/indexer.go @@ -15,10 +15,6 @@ import ( ) const ( - // StakingContractAddress is the address of system staking contract - // TODO (iip-13): replace with the real system staking contract address - StakingContractAddress = "io19ys8f4uhwms6lq6ulexr5fwht9gsjes8mvuugd" - maxBlockNumber uint64 = math.MaxUint64 ) @@ -27,64 +23,59 @@ type ( // Main functions: // 1. handle contract staking contract events when new block comes to generate index data // 2. provide query interface for contract staking index data - // Generate index data flow: - // block comes -> new dirty cache -> handle contract events -> update dirty cache -> merge dirty to clean cache - // Main Object: - // kvstore: persistent storage, used to initialize index cache at startup - // cache: in-memory index for clean data, used to query index data - // dirty: the cache to update during event processing, will be merged to clean cache after all events are processed. If errors occur during event processing, dirty cache will be discarded. Indexer struct { - kvstore db.KVStore // persistent storage - cache *contractStakingCache // in-memory index for clean data + kvstore db.KVStore // persistent storage, used to initialize index cache at startup + cache *contractStakingCache // in-memory index for clean data, used to query index data + contractAddress string // stake contract address } ) // NewContractStakingIndexer creates a new contract staking indexer -func NewContractStakingIndexer(kvStore db.KVStore) *Indexer { +func NewContractStakingIndexer(kvStore db.KVStore, contractAddr string) *Indexer { return &Indexer{ kvstore: kvStore, - cache: newContractStakingCache(), + cache: newContractStakingCache(contractAddr), } } // Height returns the tip block height func (s *Indexer) Height() (uint64, error) { - return s.cache.GetHeight(), nil + return s.cache.Height(), nil } // CandidateVotes returns the candidate votes func (s *Indexer) CandidateVotes(candidate address.Address) *big.Int { - return s.cache.GetCandidateVotes(candidate) + return s.cache.CandidateVotes(candidate) } // Buckets returns the buckets func (s *Indexer) Buckets() ([]*Bucket, error) { - return s.cache.GetBuckets() + return s.cache.Buckets() } // Bucket returns the bucket func (s *Indexer) Bucket(id uint64) (*Bucket, error) { - return s.cache.GetBucket(id) + return s.cache.Bucket(id) } // BucketsByIndices returns the buckets by indices func (s *Indexer) BucketsByIndices(indices []uint64) ([]*Bucket, error) { - return s.cache.GetBucketsByIndices(indices) + return s.cache.BucketsByIndices(indices) } // BucketsByCandidate returns the buckets by candidate func (s *Indexer) BucketsByCandidate(candidate address.Address) ([]*Bucket, error) { - return s.cache.GetBucketsByCandidate(candidate) + return s.cache.BucketsByCandidate(candidate) } // TotalBucketCount returns the total bucket count including active and burnt buckets func (s *Indexer) TotalBucketCount() uint64 { - return s.cache.GetTotalBucketCount() + return s.cache.TotalBucketCount() } // BucketTypes returns the active bucket types func (s *Indexer) BucketTypes() ([]*BucketType, error) { - btMap := s.cache.GetActiveBucketTypes() + btMap := s.cache.ActiveBucketTypes() bts := make([]*BucketType, 0, len(btMap)) for _, bt := range btMap { bts = append(bts, bt)