diff options
author | Wei-Ning Huang <w@dexon.org> | 2019-03-21 16:54:37 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@dexon.org> | 2019-04-09 21:32:58 +0800 |
commit | c58d86e0651d9aa7acb5d66da43ec7a3d6678126 (patch) | |
tree | 2179ec0e1c1fb6a52c5397855a9720a479e6c388 | |
parent | 53e91f6c8d2a1b00727b2670ee1f658269b6fb7a (diff) | |
download | dexon-c58d86e0651d9aa7acb5d66da43ec7a3d6678126.tar.gz dexon-c58d86e0651d9aa7acb5d66da43ec7a3d6678126.tar.zst dexon-c58d86e0651d9aa7acb5d66da43ec7a3d6678126.zip |
dex: skip duplicate vote to reduce gas used (#293)
-rw-r--r-- | dex/recovery.go | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/dex/recovery.go b/dex/recovery.go index 0e5c60e1a..4c3da7d5a 100644 --- a/dex/recovery.go +++ b/dex/recovery.go @@ -20,6 +20,7 @@ package dex import ( "crypto/ecdsa" "encoding/hex" + "errors" "fmt" "math/big" "strconv" @@ -29,6 +30,7 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core/types" "github.com/dexon-foundation/dexon/crypto" + "github.com/dexon-foundation/dexon/log" "github.com/dexon-foundation/dexon/params" "github.com/dexon-foundation/dexon/rlp" "github.com/onrik/ethrpc" @@ -296,6 +298,8 @@ const recoveryABI = ` ] ` +var errAlreadyVoted = errors.New("already voted for recovery") + var abiObject abi.ABI func init() { @@ -328,6 +332,23 @@ func NewRecovery(config *params.RecoveryConfig, networkRPC string, } } +func (r *Recovery) callRPC(data []byte, tag string) ([]byte, error) { + res, err := r.client.EthCall(ethrpc.T{ + From: r.nodeAddress.String(), + To: r.contract.String(), + Data: "0x" + hex.EncodeToString(data), + }, tag) + if err != nil { + return nil, err + } + + resBytes, err := hex.DecodeString(res[2:]) + if err != nil { + return nil, err + } + return resBytes, nil +} + func (r *Recovery) genVoteForSkipBlockTx(height uint64) (*types.Transaction, error) { netVersion, err := r.client.NetVersion() if err != nil { @@ -339,21 +360,33 @@ func (r *Recovery) genVoteForSkipBlockTx(height uint64) (*types.Transaction, err return nil, err } - data, err := abiObject.Pack("depositValue") + data, err := abiObject.Pack("voted", big.NewInt(int64(height)), r.nodeAddress) if err != nil { return nil, err } - res, err := r.client.EthCall(ethrpc.T{ - From: r.nodeAddress.String(), - To: r.contract.String(), - Data: "0x" + hex.EncodeToString(data), - }, "latest") + resBytes, err := r.callRPC(data, "latest") if err != nil { return nil, err } - resBytes, err := hex.DecodeString(res[2:]) + var voted bool + err = abiObject.Unpack(&voted, "voted", resBytes) + if err != nil { + return nil, err + } + + if voted { + log.Info("Already voted for skip block", "height", height) + return nil, errAlreadyVoted + } + + data, err = abiObject.Pack("depositValue") + if err != nil { + return nil, err + } + + resBytes, err = r.callRPC(data, "latest") if err != nil { return nil, err } @@ -397,6 +430,9 @@ func (r *Recovery) genVoteForSkipBlockTx(height uint64) (*types.Transaction, err func (r *Recovery) ProposeSkipBlock(height uint64) error { tx, err := r.genVoteForSkipBlockTx(height) + if err == errAlreadyVoted { + return nil + } if err != nil { return err } @@ -422,16 +458,7 @@ func (r *Recovery) Votes(height uint64) (uint64, error) { snapshotHeight := bn - numConfirmation - res, err := r.client.EthCall(ethrpc.T{ - From: r.nodeAddress.String(), - To: r.contract.String(), - Data: "0x" + hex.EncodeToString(data), - }, fmt.Sprintf("0x%x", snapshotHeight)) - if err != nil { - return 0, err - } - - resBytes, err := hex.DecodeString(res[2:]) + resBytes, err := r.callRPC(data, fmt.Sprintf("0x%x", snapshotHeight)) if err != nil { return 0, err } @@ -456,16 +483,7 @@ func (r *Recovery) Votes(height uint64) (uint64, error) { return 0, err } - res, err = r.client.EthCall(ethrpc.T{ - From: r.nodeAddress.String(), - To: r.contract.String(), - Data: "0x" + hex.EncodeToString(data), - }, fmt.Sprintf("0x%x", snapshotHeight)) - if err != nil { - return 0, err - } - - resBytes, err := hex.DecodeString(res[2:]) + resBytes, err := r.callRPC(data, fmt.Sprintf("0x%x", snapshotHeight)) if err != nil { return 0, err } |