Skip to content

Commit

Permalink
[api] query staking data by eth_call (#3684)
Browse files Browse the repository at this point in the history
* add web3 stake buckets api

* complete web3 stake buckets apis

* complete web3 stake buckets apis test

* add comment for golint

* complete web3 stake candidate apis

* change total staking amount type to account meta

* add test for stake base

* refactor for code style

* refactor: move package

* refactor: move package

* refactor: rename method

* add edge tests

* change package name

* add candidates empty test

* refactor: extract duplication code

* refactor: Extract common struct
  • Loading branch information
ququzone committed Nov 30, 2022
1 parent 663c991 commit 56f93a0
Show file tree
Hide file tree
Showing 29 changed files with 2,204 additions and 43 deletions.
11 changes: 6 additions & 5 deletions action/protocol/rewarding/ethabi/availablebalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-proto/golang/protocol"
proto "github.com/iotexproject/iotex-proto/golang/protocol"

"github.com/iotexproject/iotex-core/action/protocol"
"github.com/iotexproject/iotex-core/action/protocol/abiutil"
)

Expand Down Expand Up @@ -35,14 +36,14 @@ func init() {

// AvailableBalanceStateContext context for AvailableBalance
type AvailableBalanceStateContext struct {
*baseStateContext
*protocol.BaseStateContext
}

func newAvailableBalanceStateContext() (*AvailableBalanceStateContext, error) {
return &AvailableBalanceStateContext{
&baseStateContext{
&Parameters{
MethodName: []byte(protocol.ReadAvailableBalanceMethodName),
&protocol.BaseStateContext{
Parameter: &protocol.Parameters{
MethodName: []byte(proto.ReadAvailableBalanceMethodName),
Arguments: nil,
},
},
Expand Down
2 changes: 1 addition & 1 deletion action/protocol/rewarding/ethabi/availablebalance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestAvailableBalanceEncodeToEth(t *testing.T) {

ctx, err := newAvailableBalanceStateContext()
r.Nil(err)
r.EqualValues("AvailableBalance", string(ctx.parameters.MethodName))
r.EqualValues("AvailableBalance", string(ctx.Parameters().MethodName))

amount := big.NewInt(10000)
resp := &iotexapi.ReadStateResponse{
Expand Down
26 changes: 2 additions & 24 deletions action/protocol/rewarding/ethabi/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/hex"
"errors"

"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-core/action/protocol"
)

var (
Expand All @@ -14,30 +14,8 @@ var (
errDecodeFailure = errors.New("decode data error")
)

type (
// Parameters state request parameters
Parameters struct {
MethodName []byte
Arguments [][]byte
}

// StateContext context for ReadState
StateContext interface {
Parameters() *Parameters
EncodeToEth(*iotexapi.ReadStateResponse) (string, error)
}

baseStateContext struct {
parameters *Parameters
}
)

func (r *baseStateContext) Parameters() *Parameters {
return r.parameters
}

// BuildReadStateRequest decode eth_call data to StateContext
func BuildReadStateRequest(data []byte) (StateContext, error) {
func BuildReadStateRequest(data []byte) (protocol.StateContext, error) {
if len(data) < 4 {
return nil, errInvalidCallData
}
Expand Down
11 changes: 6 additions & 5 deletions action/protocol/rewarding/ethabi/totalbalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-proto/golang/protocol"
proto "github.com/iotexproject/iotex-proto/golang/protocol"

"github.com/iotexproject/iotex-core/action/protocol"
"github.com/iotexproject/iotex-core/action/protocol/abiutil"
)

Expand Down Expand Up @@ -35,14 +36,14 @@ func init() {

// TotalBalanceStateContext context for TotalBalance
type TotalBalanceStateContext struct {
*baseStateContext
*protocol.BaseStateContext
}

func newTotalBalanceStateContext() (*TotalBalanceStateContext, error) {
return &TotalBalanceStateContext{
&baseStateContext{
&Parameters{
MethodName: []byte(protocol.ReadTotalBalanceMethodName),
&protocol.BaseStateContext{
Parameter: &protocol.Parameters{
MethodName: []byte(proto.ReadTotalBalanceMethodName),
Arguments: nil,
},
},
Expand Down
2 changes: 1 addition & 1 deletion action/protocol/rewarding/ethabi/totalbalance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestTotalBalanceEncodeToEth(t *testing.T) {

ctx, err := newTotalBalanceStateContext()
r.Nil(err)
r.EqualValues("TotalBalance", string(ctx.parameters.MethodName))
r.EqualValues("TotalBalance", string(ctx.Parameters().MethodName))

amount := big.NewInt(10000)
resp := &iotexapi.ReadStateResponse{
Expand Down
11 changes: 6 additions & 5 deletions action/protocol/rewarding/ethabi/unclaimedbalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-proto/golang/protocol"
proto "github.com/iotexproject/iotex-proto/golang/protocol"

"github.com/iotexproject/iotex-core/action/protocol"
"github.com/iotexproject/iotex-core/action/protocol/abiutil"
)

Expand Down Expand Up @@ -43,7 +44,7 @@ func init() {

// UnclaimedBalanceStateContext context for UnclaimedBalance
type UnclaimedBalanceStateContext struct {
*baseStateContext
*protocol.BaseStateContext
}

func newUnclaimedBalanceStateContext(data []byte) (*UnclaimedBalanceStateContext, error) {
Expand All @@ -62,9 +63,9 @@ func newUnclaimedBalanceStateContext(data []byte) (*UnclaimedBalanceStateContext
}

return &UnclaimedBalanceStateContext{
&baseStateContext{
&Parameters{
MethodName: []byte(protocol.ReadUnclaimedBalanceMethodName),
&protocol.BaseStateContext{
Parameter: &protocol.Parameters{
MethodName: []byte(proto.ReadUnclaimedBalanceMethodName),
Arguments: [][]byte{[]byte(accountAddress.String())},
},
},
Expand Down
4 changes: 2 additions & 2 deletions action/protocol/rewarding/ethabi/unclaimedbalance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ func TestNewUnclaimedBalanceStateContext(t *testing.T) {

ctx, err := newUnclaimedBalanceStateContext(data)
r.Nil(err)
r.EqualValues("io1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqps833xv", string(ctx.parameters.Arguments[0]))
r.EqualValues("UnclaimedBalance", string(ctx.parameters.MethodName))
r.EqualValues("io1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqps833xv", string(ctx.Parameters().Arguments[0]))
r.EqualValues("UnclaimedBalance", string(ctx.Parameters().MethodName))
}
143 changes: 143 additions & 0 deletions action/protocol/staking/ethabi/stake_base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package ethabi

import (
"encoding/hex"
"errors"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/iotexproject/iotex-proto/golang/iotextypes"

"github.com/iotexproject/iotex-core/action/protocol"
"github.com/iotexproject/iotex-core/pkg/util/addrutil"
)

var (
errInvalidCallData = errors.New("invalid call binary data")
errInvalidCallSig = errors.New("invalid call sig")
errConvertBigNumber = errors.New("convert big number error")
errDecodeFailure = errors.New("decode data error")
)

type (
// BucketEth struct for eth
BucketEth struct {
Index uint64
CandidateAddress common.Address
StakedAmount *big.Int
StakedDuration uint32
CreateTime int64
StakeStartTime int64
UnstakeStartTime int64
AutoStake bool
Owner common.Address
}

// CandidateEth struct for eth
CandidateEth struct {
OwnerAddress common.Address
OperatorAddress common.Address
RewardAddress common.Address
Name string
TotalWeightedVotes *big.Int
SelfStakeBucketIdx uint64
SelfStakingTokens *big.Int
}
)

func encodeVoteBucketListToEth(outputs abi.Arguments, buckets iotextypes.VoteBucketList) (string, error) {
args := make([]BucketEth, len(buckets.Buckets))
for i, bucket := range buckets.Buckets {
args[i] = BucketEth{}
args[i].Index = bucket.Index
addr, err := addrutil.IoAddrToEvmAddr(bucket.CandidateAddress)
if err != nil {
return "", err
}
args[i].CandidateAddress = addr
if amount, ok := new(big.Int).SetString(bucket.StakedAmount, 10); ok {
args[i].StakedAmount = amount
} else {
return "", errConvertBigNumber
}
args[i].StakedDuration = bucket.StakedDuration
args[i].CreateTime = bucket.CreateTime.Seconds
args[i].StakeStartTime = bucket.StakeStartTime.Seconds
args[i].UnstakeStartTime = bucket.UnstakeStartTime.Seconds
args[i].AutoStake = bucket.AutoStake
addr, err = addrutil.IoAddrToEvmAddr(bucket.Owner)
if err != nil {
return "", err
}
args[i].Owner = addr
}

data, err := outputs.Pack(args)
if err != nil {
return "", nil
}
return hex.EncodeToString(data), nil
}

func encodeCandidateToEth(candidate *iotextypes.CandidateV2) (*CandidateEth, error) {
result := &CandidateEth{}
addr, err := addrutil.IoAddrToEvmAddr(candidate.OwnerAddress)
if err != nil {
return nil, err
}
result.OwnerAddress = addr
addr, err = addrutil.IoAddrToEvmAddr(candidate.OperatorAddress)
if err != nil {
return nil, err
}
result.OperatorAddress = addr
addr, err = addrutil.IoAddrToEvmAddr(candidate.RewardAddress)
if err != nil {
return nil, err
}
result.RewardAddress = addr
result.Name = candidate.Name
if amount, ok := new(big.Int).SetString(candidate.TotalWeightedVotes, 10); ok {
result.TotalWeightedVotes = amount
} else {
return nil, errConvertBigNumber
}
result.SelfStakeBucketIdx = candidate.SelfStakeBucketIdx
if amount, ok := new(big.Int).SetString(candidate.SelfStakingTokens, 10); ok {
result.SelfStakingTokens = amount
} else {
return nil, errConvertBigNumber
}
return result, nil
}

// BuildReadStateRequest decode eth_call data to StateContext
func BuildReadStateRequest(data []byte) (protocol.StateContext, error) {
if len(data) < 4 {
return nil, errInvalidCallData
}

switch methodSig := hex.EncodeToString(data[:4]); methodSig {
case hex.EncodeToString(_bucketsMethod.ID):
return newBucketsStateContext(data[4:])
case hex.EncodeToString(_bucketsByCandidateMethod.ID):
return newBucketsByCandidateStateContext(data[4:])
case hex.EncodeToString(_bucketsByIndexesMethod.ID):
return newBucketsByIndexesStateContext(data[4:])
case hex.EncodeToString(_bucketsByVoterMethod.ID):
return newBucketsByVoterStateContext(data[4:])
case hex.EncodeToString(_bucketsCountMethod.ID):
return newBucketsCountStateContext()
case hex.EncodeToString(_candidatesMethod.ID):
return newCandidatesStateContext(data[4:])
case hex.EncodeToString(_candidateByNameMethod.ID):
return newCandidateByNameStateContext(data[4:])
case hex.EncodeToString(_candidateByAddressMethod.ID):
return newCandidateByAddressStateContext(data[4:])
case hex.EncodeToString(_totalStakingAmountMethod.ID):
return newTotalStakingAmountContext()
default:
return nil, errInvalidCallSig
}
}
Loading

0 comments on commit 56f93a0

Please sign in to comment.