Different API update to support staking txs fetch and additional staking methods

pull/1909/head
flicker-harmony 5 years ago
parent 026f9feccf
commit 0f3a3deffc
  1. 38
      internal/hmyapi/blockchain.go
  2. 31
      internal/hmyapi/transactionpool.go
  3. 145
      internal/hmyapi/types.go
  4. 5
      staking/types/transaction.go

@ -541,10 +541,10 @@ func (s *PublicBlockChainAPI) GetValidatorInformation(ctx context.Context, addre
return rpcValidator, nil return rpcValidator, nil
} }
// GetDelegationsByDelegator returns information about a validator. // GetDelegationsByDelegator returns list of delegations for a delegator address.
func (s *PublicBlockChainAPI) GetDelegationsByDelegator(ctx context.Context, address string) ([]*RPCDelegation, error) { func (s *PublicBlockChainAPI) GetDelegationsByDelegator(ctx context.Context, address string) ([]*RPCDelegation, error) {
validatorAddress := internal_common.ParseAddr(address) delegatorAddress := internal_common.ParseAddr(address)
validators, delegations := s.b.GetDelegationsByDelegator(validatorAddress) validators, delegations := s.b.GetDelegationsByDelegator(delegatorAddress)
result := []*RPCDelegation{} result := []*RPCDelegation{}
for i := range delegations { for i := range delegations {
delegation := delegations[i] delegation := delegations[i]
@ -559,7 +559,7 @@ func (s *PublicBlockChainAPI) GetDelegationsByDelegator(ctx context.Context, add
} }
result = append(result, &RPCDelegation{ result = append(result, &RPCDelegation{
validators[i], validators[i],
validatorAddress, delegatorAddress,
delegation.Amount, delegation.Amount,
delegation.Reward, delegation.Reward,
undelegations, undelegations,
@ -593,3 +593,33 @@ func (s *PublicBlockChainAPI) GetDelegationsByValidator(ctx context.Context, add
} }
return result, nil return result, nil
} }
// GetDelegationByDelegatorAndValidator returns a delegation for delegator and validator.
func (s *PublicBlockChainAPI) GetDelegationByDelegatorAndValidator(ctx context.Context, address string, validator string) (*RPCDelegation, error) {
delegatorAddress := internal_common.ParseAddr(address)
validatorAddress := internal_common.ParseAddr(validator)
validators, delegations := s.b.GetDelegationsByDelegator(delegatorAddress)
for i := range delegations {
if validators[i] != validatorAddress {
continue
}
delegation := delegations[i]
undelegations := []RPCUndelegation{}
for j := range delegation.Undelegations {
undelegations = append(undelegations, RPCUndelegation{
delegation.Undelegations[j].Amount,
delegation.Undelegations[j].Epoch,
})
}
return &RPCDelegation{
validatorAddress,
delegatorAddress,
delegation.Amount,
delegation.Reward,
undelegations,
}, nil
}
return nil, nil
}

@ -109,17 +109,44 @@ func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context
// GetTransactionByHash returns the transaction for the given hash // GetTransactionByHash returns the transaction for the given hash
func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) *RPCTransaction { func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) *RPCTransaction {
// Try to return an already finalized transaction // Try to return an already finalized transaction
if tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash); tx != nil { tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash)
if tx != nil {
return newRPCTransaction(tx, blockHash, blockNumber, index) return newRPCTransaction(tx, blockHash, blockNumber, index)
} }
// No finalized transaction, try to retrieve it from the pool // No finalized transaction, try to retrieve it from the pool
if tx := s.b.GetPoolTransaction(hash); tx != nil { if tx = s.b.GetPoolTransaction(hash); tx != nil {
return newRPCPendingTransaction(tx) return newRPCPendingTransaction(tx)
} }
// Transaction unknown, return as such // Transaction unknown, return as such
return nil return nil
} }
// GetStakingTransactionByHash returns the transaction for the given hash
func (s *PublicTransactionPoolAPI) GetStakingTransactionByHash(ctx context.Context, hash common.Hash) *RPCStakingTransaction {
// Try to return an already finalized transaction
stx, blockHash, blockNumber, index := rawdb.ReadStakingTransaction(s.b.ChainDb(), hash)
if stx != nil {
return newRPCStakingTransaction(stx, blockHash, blockNumber, index)
}
return nil
}
// GetStakingTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCStakingTransaction {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCStakingTransactionFromBlockIndex(block, uint64(index))
}
return nil
}
// GetStakingTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (s *PublicTransactionPoolAPI) GetStakingTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCStakingTransaction {
if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
return newRPCStakingTransactionFromBlockIndex(block, uint64(index))
}
return nil
}
// GetTransactionCount returns the number of transactions the given address has sent for the given block number // GetTransactionCount returns the number of transactions the given address has sent for the given block number
func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr string, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) { func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr string, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) {
address := internal_common.ParseAddr(addr) address := internal_common.ParseAddr(addr)

@ -38,6 +38,23 @@ type RPCTransaction struct {
S *hexutil.Big `json:"s"` S *hexutil.Big `json:"s"`
} }
// RPCStakingTransaction represents a transaction that will serialize to the RPC representation of a staking transaction
type RPCStakingTransaction struct {
BlockHash common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From string `json:"from"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Nonce hexutil.Uint64 `json:"nonce"`
TransactionIndex hexutil.Uint `json:"transactionIndex"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
Type string `json:"type"`
Msg map[string]interface{} `json:"msg"`
}
// RPCCXReceipt represents a CXReceipt that will serialize to the RPC representation of a CXReceipt // RPCCXReceipt represents a CXReceipt that will serialize to the RPC representation of a CXReceipt
type RPCCXReceipt struct { type RPCCXReceipt struct {
BlockHash common.Hash `json:"blockHash"` BlockHash common.Hash `json:"blockHash"`
@ -186,7 +203,6 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
Gas: hexutil.Uint64(tx.Gas()), Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.GasPrice()), GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(), Hash: tx.Hash(),
Input: hexutil.Bytes(tx.Data()),
Nonce: hexutil.Uint64(tx.Nonce()), Nonce: hexutil.Uint64(tx.Nonce()),
Value: (*hexutil.Big)(tx.Value()), Value: (*hexutil.Big)(tx.Value()),
ShardID: tx.ShardID(), ShardID: tx.ShardID(),
@ -220,6 +236,96 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
return result return result
} }
// newRPCStakingTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
func newRPCStakingTransaction(tx *types2.StakingTransaction, blockHash common.Hash, blockNumber uint64, index uint64) *RPCStakingTransaction {
from, _ := tx.SenderAddress()
v, r, s := tx.RawSignatureValues()
stakingTxType := tx.StakingType().String()
message := tx.StakingMessage()
fields := make(map[string]interface{}, 0)
switch stakingTxType {
case "CreateValidator":
msg := message.(types2.CreateValidator)
fields = map[string]interface{}{
"validatorAddress": msg.ValidatorAddress,
"name": msg.Description.Name,
"commissionRate": (*hexutil.Big)(msg.CommissionRates.Rate.Int),
"maxCommissionRate": (*hexutil.Big)(msg.CommissionRates.MaxRate.Int),
"maxChangeRate": (*hexutil.Big)(msg.CommissionRates.MaxChangeRate.Int),
"minSelfDelegation": (*hexutil.Big)(msg.MinSelfDelegation),
"maxTotalDelegation": (*hexutil.Big)(msg.MaxTotalDelegation),
"amount": (*hexutil.Big)(msg.Amount),
"website": msg.Description.Website,
"identity": msg.Description.Identity,
"securityContact": msg.Description.SecurityContact,
"details": msg.Description.Details,
"slotPubKeys": msg.SlotPubKeys,
}
case "EditValidator":
msg := message.(types2.EditValidator)
fields = map[string]interface{}{
"validatorAddress": msg.ValidatorAddress,
"commisionRate": (*hexutil.Big)(msg.CommissionRate.Int),
"name": msg.Description.Name,
"minSelfDelegation": (*hexutil.Big)(msg.MinSelfDelegation),
"maxTotalDelegation": (*hexutil.Big)(msg.MaxTotalDelegation),
"website": msg.Description.Website,
"identity": msg.Description.Identity,
"securityContact": msg.Description.SecurityContact,
"details": msg.Description.Details,
"slotPubKeyToAdd": msg.SlotKeyToAdd,
"slotPubKeyToRemove": msg.SlotKeyToRemove,
}
case "CollectRewards":
msg := message.(types2.CollectRewards)
fields = map[string]interface{}{
"delegatorAddress": msg.DelegatorAddress,
}
case "Delegate":
msg := message.(types2.Delegate)
fields = map[string]interface{}{
"delegatorAddress": msg.DelegatorAddress,
"validatorAddress": msg.ValidatorAddress,
"amount": (*hexutil.Big)(msg.Amount),
}
case "Undelegate":
msg := message.(types2.Undelegate)
fields = map[string]interface{}{
"delegatorAddress": msg.DelegatorAddress,
"validatorAddress": msg.ValidatorAddress,
"amount": (*hexutil.Big)(msg.Amount),
}
}
result := &RPCStakingTransaction{
Gas: hexutil.Uint64(tx.Gas()),
GasPrice: (*hexutil.Big)(tx.Price()),
Hash: tx.Hash(),
Nonce: hexutil.Uint64(tx.Nonce()),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
Type: stakingTxType,
Msg: fields,
}
if blockHash != (common.Hash{}) {
result.BlockHash = blockHash
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
result.TransactionIndex = hexutil.Uint(index)
}
fromAddr, err := internal_common.AddressToBech32(from)
if err != nil {
return nil
}
result.From = fromAddr
return result
}
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation // newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
return newRPCTransaction(tx, common.Hash{}, 0, 0) return newRPCTransaction(tx, common.Hash{}, 0, 0)
@ -244,6 +350,7 @@ type RPCBlock struct {
TransactionsRoot common.Hash `json:"transactionsRoot"` TransactionsRoot common.Hash `json:"transactionsRoot"`
ReceiptsRoot common.Hash `json:"receiptsRoot"` ReceiptsRoot common.Hash `json:"receiptsRoot"`
Transactions []interface{} `json:"transactions"` Transactions []interface{} `json:"transactions"`
StakingTxs []interface{} `json:"stakingTxs`
Uncles []common.Hash `json:"uncles"` Uncles []common.Hash `json:"uncles"`
TotalDifficulty *big.Int `json:"totalDifficulty"` TotalDifficulty *big.Int `json:"totalDifficulty"`
Signers []string `json:"signers"` Signers []string `json:"signers"`
@ -282,6 +389,14 @@ func RPCMarshalBlock(b *types.Block, blockArgs BlockArgs) (map[string]interface{
return newRPCTransactionFromBlockHash(b, tx.Hash()), nil return newRPCTransactionFromBlockHash(b, tx.Hash()), nil
} }
} }
formatStakingTx := func(tx *types2.StakingTransaction) (interface{}, error) {
return tx.Hash(), nil
}
if blockArgs.FullTx {
formatStakingTx = func(tx *types2.StakingTransaction) (interface{}, error) {
return newRPCStakingTransactionFromBlockHash(b, tx.Hash()), nil
}
}
txs := b.Transactions() txs := b.Transactions()
transactions := make([]interface{}, len(txs)) transactions := make([]interface{}, len(txs))
var err error var err error
@ -291,6 +406,15 @@ func RPCMarshalBlock(b *types.Block, blockArgs BlockArgs) (map[string]interface{
} }
} }
fields["transactions"] = transactions fields["transactions"] = transactions
stakingTxs := b.StakingTransactions()
stakingTransactions := make([]interface{}, len(stakingTxs))
for i, tx := range stakingTxs {
if stakingTransactions[i], err = formatStakingTx(tx); err != nil {
return nil, err
}
}
fields["stakingTransactions"] = stakingTransactions
} }
uncles := b.Uncles() uncles := b.Uncles()
@ -324,6 +448,25 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransacti
return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index) return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index)
} }
// newRPCStakingTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
func newRPCStakingTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCStakingTransaction {
for idx, tx := range b.StakingTransactions() {
if tx.Hash() == hash {
return newRPCStakingTransactionFromBlockIndex(b, uint64(idx))
}
}
return nil
}
// newRPCStakingTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
func newRPCStakingTransactionFromBlockIndex(b *types.Block, index uint64) *RPCStakingTransaction {
txs := b.StakingTransactions()
if index >= uint64(len(txs)) {
return nil
}
return newRPCStakingTransaction(txs[index], b.Hash(), b.NumberU64(), index)
}
// CallArgs represents the arguments for a call. // CallArgs represents the arguments for a call.
type CallArgs struct { type CallArgs struct {
From *common.Address `json:"from"` From *common.Address `json:"from"`

@ -209,6 +209,11 @@ func RLPDecodeStakeMsg(payload []byte, d Directive) (interface{}, error) {
return ds, nil return ds, nil
} }
// RawSignatureValues return raw signature values.
func (tx *StakingTransaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) {
return tx.data.V, tx.data.R, tx.data.S
}
// StakingType returns the type of staking transaction // StakingType returns the type of staking transaction
func (tx *StakingTransaction) StakingType() Directive { func (tx *StakingTransaction) StakingType() Directive {
return tx.data.Directive return tx.data.Directive

Loading…
Cancel
Save