Merge pull request #3475 from fjl/rpc-hex-improvements

rpc: remove HexBytes, HexNumber
pull/3487/head
Péter Szilágyi 8 years ago committed by GitHub
commit 115364b0a9
  1. 32
      eth/api.go
  2. 20
      eth/bind.go
  3. 478
      internal/ethapi/api.go
  4. 2
      internal/jsre/jsre.go
  5. 6
      internal/jsre/pretty.go
  6. 5
      les/backend.go
  7. 13
      node/api.go
  8. 67
      rpc/json.go
  9. 115
      rpc/types.go
  10. 95
      rpc/types_test.go
  11. 17
      whisper/shhapi/api.go
  12. 4
      whisper/shhapi/api_test.go
  13. 70
      whisper/whisperv2/api.go

@ -31,6 +31,7 @@ import (
"github.com/ethereum/ethash" "github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -69,8 +70,8 @@ func (s *PublicEthereumAPI) Coinbase() (common.Address, error) {
} }
// Hashrate returns the POW hashrate // Hashrate returns the POW hashrate
func (s *PublicEthereumAPI) Hashrate() *rpc.HexNumber { func (s *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
return rpc.NewHexNumber(s.e.Miner().HashRate()) return hexutil.Uint64(s.e.Miner().HashRate())
} }
// PublicMinerAPI provides an API to control the miner. // PublicMinerAPI provides an API to control the miner.
@ -95,8 +96,8 @@ func (s *PublicMinerAPI) Mining() bool {
// SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was // SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was
// accepted. Note, this is not an indication if the provided work was valid! // accepted. Note, this is not an indication if the provided work was valid!
func (s *PublicMinerAPI) SubmitWork(nonce rpc.HexNumber, solution, digest common.Hash) bool { func (s *PublicMinerAPI) SubmitWork(nonce hexutil.Uint64, solution, digest common.Hash) bool {
return s.agent.SubmitWork(nonce.Uint64(), digest, solution) return s.agent.SubmitWork(uint64(nonce), digest, solution)
} }
// GetWork returns a work package for external miner. The work package consists of 3 strings // GetWork returns a work package for external miner. The work package consists of 3 strings
@ -119,8 +120,8 @@ func (s *PublicMinerAPI) GetWork() (work [3]string, err error) {
// SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined // SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined
// hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which // hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which
// must be unique between nodes. // must be unique between nodes.
func (s *PublicMinerAPI) SubmitHashrate(hashrate rpc.HexNumber, id common.Hash) bool { func (s *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool {
s.agent.SubmitHashrate(id, hashrate.Uint64()) s.agent.SubmitHashrate(id, uint64(hashrate))
return true return true
} }
@ -137,18 +138,15 @@ func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI {
// Start the miner with the given number of threads. If threads is nil the number of // Start the miner with the given number of threads. If threads is nil the number of
// workers started is equal to the number of logical CPU's that are usable by this process. // workers started is equal to the number of logical CPU's that are usable by this process.
func (s *PrivateMinerAPI) Start(threads *rpc.HexNumber) (bool, error) { func (s *PrivateMinerAPI) Start(threads *hexutil.Uint) (bool, error) {
s.e.StartAutoDAG() s.e.StartAutoDAG()
var err error
if threads == nil { if threads == nil {
threads = rpc.NewHexNumber(runtime.NumCPU()) err = s.e.StartMining(runtime.NumCPU())
} } else {
err = s.e.StartMining(int(*threads))
err := s.e.StartMining(threads.Int())
if err == nil {
return true, nil
} }
return false, err return err == nil, err
} }
// Stop the miner // Stop the miner
@ -166,8 +164,8 @@ func (s *PrivateMinerAPI) SetExtra(extra string) (bool, error) {
} }
// SetGasPrice sets the minimum accepted gas price for the miner. // SetGasPrice sets the minimum accepted gas price for the miner.
func (s *PrivateMinerAPI) SetGasPrice(gasPrice rpc.HexNumber) bool { func (s *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
s.e.Miner().SetGasPrice(gasPrice.BigInt()) s.e.Miner().SetGasPrice((*big.Int)(&gasPrice))
return true return true
} }

@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -83,16 +84,16 @@ func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs {
args := ethapi.CallArgs{ args := ethapi.CallArgs{
To: msg.To, To: msg.To,
From: msg.From, From: msg.From,
Data: common.ToHex(msg.Data), Data: msg.Data,
} }
if msg.Gas != nil { if msg.Gas != nil {
args.Gas = *rpc.NewHexNumber(msg.Gas) args.Gas = hexutil.Big(*msg.Gas)
} }
if msg.GasPrice != nil { if msg.GasPrice != nil {
args.GasPrice = *rpc.NewHexNumber(msg.GasPrice) args.GasPrice = hexutil.Big(*msg.GasPrice)
} }
if msg.Value != nil { if msg.Value != nil {
args.Value = *rpc.NewHexNumber(msg.Value) args.Value = hexutil.Big(*msg.Value)
} }
return args return args
} }
@ -106,9 +107,12 @@ func toBlockNumber(num *big.Int) rpc.BlockNumber {
// PendingAccountNonce implements bind.ContractTransactor retrieving the current // PendingAccountNonce implements bind.ContractTransactor retrieving the current
// pending nonce associated with an account. // pending nonce associated with an account.
func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { func (b *ContractBackend) PendingNonceAt(ctx context.Context, account common.Address) (nonce uint64, err error) {
out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber) out, err := b.txapi.GetTransactionCount(ctx, account, rpc.PendingBlockNumber)
return out.Uint64(), err if out != nil {
nonce = uint64(*out)
}
return nonce, err
} }
// SuggestGasPrice implements bind.ContractTransactor retrieving the currently // SuggestGasPrice implements bind.ContractTransactor retrieving the currently
@ -124,13 +128,13 @@ func (b *ContractBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error)
// should provide a basis for setting a reasonable default. // should provide a basis for setting a reasonable default.
func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) { func (b *ContractBackend) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (*big.Int, error) {
out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg)) out, err := b.bcapi.EstimateGas(ctx, toCallArgs(msg))
return out.BigInt(), err return out.ToInt(), err
} }
// SendTransaction implements bind.ContractTransactor injects the transaction // SendTransaction implements bind.ContractTransactor injects the transaction
// into the pending pool for execution. // into the pending pool for execution.
func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { func (b *ContractBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
raw, _ := rlp.EncodeToBytes(tx) raw, _ := rlp.EncodeToBytes(tx)
_, err := b.txapi.SendRawTransaction(ctx, common.ToHex(raw)) _, err := b.txapi.SendRawTransaction(ctx, raw)
return err return err
} }

@ -19,7 +19,6 @@ package ethapi
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"math/big" "math/big"
"strings" "strings"
@ -44,7 +43,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
) )
const defaultGas = uint64(90000) const defaultGas = 90000
// PublicEthereumAPI provides an API to access Ethereum related information. // PublicEthereumAPI provides an API to access Ethereum related information.
// It offers only methods that operate on public data that is freely available to anyone. // It offers only methods that operate on public data that is freely available to anyone.
@ -63,8 +62,8 @@ func (s *PublicEthereumAPI) GasPrice(ctx context.Context) (*big.Int, error) {
} }
// ProtocolVersion returns the current Ethereum protocol version this node supports // ProtocolVersion returns the current Ethereum protocol version this node supports
func (s *PublicEthereumAPI) ProtocolVersion() *rpc.HexNumber { func (s *PublicEthereumAPI) ProtocolVersion() hexutil.Uint {
return rpc.NewHexNumber(s.b.ProtocolVersion()) return hexutil.Uint(s.b.ProtocolVersion())
} }
// Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not
@ -83,11 +82,11 @@ func (s *PublicEthereumAPI) Syncing() (interface{}, error) {
} }
// Otherwise gather the block sync stats // Otherwise gather the block sync stats
return map[string]interface{}{ return map[string]interface{}{
"startingBlock": rpc.NewHexNumber(progress.StartingBlock), "startingBlock": hexutil.Uint64(progress.StartingBlock),
"currentBlock": rpc.NewHexNumber(progress.CurrentBlock), "currentBlock": hexutil.Uint64(progress.CurrentBlock),
"highestBlock": rpc.NewHexNumber(progress.HighestBlock), "highestBlock": hexutil.Uint64(progress.HighestBlock),
"pulledStates": rpc.NewHexNumber(progress.PulledStates), "pulledStates": hexutil.Uint64(progress.PulledStates),
"knownStates": rpc.NewHexNumber(progress.KnownStates), "knownStates": hexutil.Uint64(progress.KnownStates),
}, nil }, nil
} }
@ -129,11 +128,11 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac
} }
// Status returns the number of pending and queued transaction in the pool. // Status returns the number of pending and queued transaction in the pool.
func (s *PublicTxPoolAPI) Status() map[string]*rpc.HexNumber { func (s *PublicTxPoolAPI) Status() map[string]hexutil.Uint {
pending, queue := s.b.Stats() pending, queue := s.b.Stats()
return map[string]*rpc.HexNumber{ return map[string]hexutil.Uint{
"pending": rpc.NewHexNumber(pending), "pending": hexutil.Uint(pending),
"queued": rpc.NewHexNumber(queue), "queued": hexutil.Uint(queue),
} }
} }
@ -238,13 +237,14 @@ func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (commo
// UnlockAccount will unlock the account associated with the given address with // UnlockAccount will unlock the account associated with the given address with
// the given password for duration seconds. If duration is nil it will use a // the given password for duration seconds. If duration is nil it will use a
// default of 300 seconds. It returns an indication if the account was unlocked. // default of 300 seconds. It returns an indication if the account was unlocked.
func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *rpc.HexNumber) (bool, error) { func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *hexutil.Uint) (bool, error) {
var d time.Duration
if duration == nil { if duration == nil {
duration = rpc.NewHexNumber(300) d = 300 * time.Second
} else {
d = time.Duration(*duration) * time.Second
} }
a := accounts.Account{Address: addr} if err := s.am.TimedUnlock(accounts.Account{Address: addr}, password, d); err != nil {
d := time.Duration(duration.Int64()) * time.Second
if err := s.am.TimedUnlock(a, password, d); err != nil {
return false, err return false, err
} }
return true, nil return true, nil
@ -259,27 +259,10 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
// tries to sign it with the key associated with args.To. If the given passwd isn't // tries to sign it with the key associated with args.To. If the given passwd isn't
// able to decrypt the key it fails. // able to decrypt the key it fails.
func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) { func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
var err error if err := args.setDefaults(ctx, s.b); err != nil {
args, err = prepareSendTxArgs(ctx, args, s.b)
if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
tx := args.toTransaction()
if args.Nonce == nil {
nonce, err := s.b.GetPoolNonce(ctx, args.From)
if err != nil {
return common.Hash{}, err
}
args.Nonce = rpc.NewHexNumber(nonce)
}
var tx *types.Transaction
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
}
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number()) signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
signature, err := s.am.SignWithPassphrase(args.From, passwd, signer.Hash(tx).Bytes()) signature, err := s.am.SignWithPassphrase(args.From, passwd, signer.Hash(tx).Bytes())
if err != nil { if err != nil {
@ -399,15 +382,15 @@ func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash comm
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned. // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr) block, err := s.b.BlockByNumber(ctx, blockNr)
if block != nil { if block != nil {
uncles := block.Uncles() uncles := block.Uncles()
if index.Int() < 0 || index.Int() >= len(uncles) { if index >= hexutil.Uint(len(uncles)) {
glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr) glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index, blockNr)
return nil, nil return nil, nil
} }
block = types.NewBlockWithHeader(uncles[index.Int()]) block = types.NewBlockWithHeader(uncles[index])
return s.rpcOutputBlock(block, false, false) return s.rpcOutputBlock(block, false, false)
} }
return nil, err return nil, err
@ -415,32 +398,34 @@ func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context,
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned. // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
block, err := s.b.GetBlock(ctx, blockHash) block, err := s.b.GetBlock(ctx, blockHash)
if block != nil { if block != nil {
uncles := block.Uncles() uncles := block.Uncles()
if index.Int() < 0 || index.Int() >= len(uncles) { if index >= hexutil.Uint(len(uncles)) {
glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index.Int(), blockHash.Hex()) glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index, blockHash.Hex())
return nil, nil return nil, nil
} }
block = types.NewBlockWithHeader(uncles[index.Int()]) block = types.NewBlockWithHeader(uncles[index])
return s.rpcOutputBlock(block, false, false) return s.rpcOutputBlock(block, false, false)
} }
return nil, err return nil, err
} }
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number // GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *rpc.HexNumber { func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return rpc.NewHexNumber(len(block.Uncles())) n := hexutil.Uint(len(block.Uncles()))
return &n
} }
return nil return nil
} }
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *rpc.HexNumber { func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
return rpc.NewHexNumber(len(block.Uncles())) n := hexutil.Uint(len(block.Uncles()))
return &n
} }
return nil return nil
} }
@ -497,10 +482,10 @@ func (m callmsg) Data() []byte { return m.data }
type CallArgs struct { type CallArgs struct {
From common.Address `json:"from"` From common.Address `json:"from"`
To *common.Address `json:"to"` To *common.Address `json:"to"`
Gas rpc.HexNumber `json:"gas"` Gas hexutil.Big `json:"gas"`
GasPrice rpc.HexNumber `json:"gasPrice"` GasPrice hexutil.Big `json:"gasPrice"`
Value rpc.HexNumber `json:"value"` Value hexutil.Big `json:"value"`
Data string `json:"data"` Data hexutil.Bytes `json:"data"`
} }
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) { func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) {
@ -525,14 +510,14 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
} }
// Assemble the CALL invocation // Assemble the CALL invocation
gas, gasPrice := args.Gas.BigInt(), args.GasPrice.BigInt() gas, gasPrice := args.Gas.ToInt(), args.GasPrice.ToInt()
if gas.Cmp(common.Big0) == 0 { if gas.Cmp(common.Big0) == 0 {
gas = big.NewInt(50000000) gas = big.NewInt(50000000)
} }
if gasPrice.Cmp(common.Big0) == 0 { if gasPrice.Cmp(common.Big0) == 0 {
gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
} }
msg := types.NewMessage(addr, args.To, 0, args.Value.BigInt(), gas, gasPrice, common.FromHex(args.Data), false) msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false)
// Execute the call and return // Execute the call and return
vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header) vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header)
@ -558,9 +543,9 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr r
} }
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction. // EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*rpc.HexNumber, error) { func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*hexutil.Big, error) {
_, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber) _, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber)
return rpc.NewHexNumber(gas), err return (*hexutil.Big)(gas), err
} }
// ExecutionResult groups all structured logs emitted by the EVM // ExecutionResult groups all structured logs emitted by the EVM
@ -622,7 +607,7 @@ func FormatLogs(structLogs []vm.StructLog) []StructLogRes {
func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
head := b.Header() // copies the header once head := b.Header() // copies the header once
fields := map[string]interface{}{ fields := map[string]interface{}{
"number": rpc.NewHexNumber(head.Number), "number": (*hexutil.Big)(head.Number),
"hash": b.Hash(), "hash": b.Hash(),
"parentHash": head.ParentHash, "parentHash": head.ParentHash,
"nonce": head.Nonce, "nonce": head.Nonce,
@ -631,13 +616,13 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"logsBloom": head.Bloom, "logsBloom": head.Bloom,
"stateRoot": head.Root, "stateRoot": head.Root,
"miner": head.Coinbase, "miner": head.Coinbase,
"difficulty": rpc.NewHexNumber(head.Difficulty), "difficulty": (*hexutil.Big)(head.Difficulty),
"totalDifficulty": rpc.NewHexNumber(s.b.GetTd(b.Hash())), "totalDifficulty": (*hexutil.Big)(s.b.GetTd(b.Hash())),
"extraData": rpc.HexBytes(head.Extra), "extraData": hexutil.Bytes(head.Extra),
"size": rpc.NewHexNumber(b.Size().Int64()), "size": hexutil.Uint64(uint64(b.Size().Int64())),
"gasLimit": rpc.NewHexNumber(head.GasLimit), "gasLimit": (*hexutil.Big)(head.GasLimit),
"gasUsed": rpc.NewHexNumber(head.GasUsed), "gasUsed": (*hexutil.Big)(head.GasUsed),
"timestamp": rpc.NewHexNumber(head.Time), "timestamp": (*hexutil.Big)(head.Time),
"transactionsRoot": head.TxHash, "transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash, "receiptsRoot": head.ReceiptHash,
} }
@ -677,19 +662,19 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
type RPCTransaction struct { type RPCTransaction struct {
BlockHash common.Hash `json:"blockHash"` BlockHash common.Hash `json:"blockHash"`
BlockNumber *rpc.HexNumber `json:"blockNumber"` BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"` From common.Address `json:"from"`
Gas *rpc.HexNumber `json:"gas"` Gas *hexutil.Big `json:"gas"`
GasPrice *rpc.HexNumber `json:"gasPrice"` GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"` Hash common.Hash `json:"hash"`
Input rpc.HexBytes `json:"input"` Input hexutil.Bytes `json:"input"`
Nonce *rpc.HexNumber `json:"nonce"` Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"` To *common.Address `json:"to"`
TransactionIndex *rpc.HexNumber `json:"transactionIndex"` TransactionIndex hexutil.Uint `json:"transactionIndex"`
Value *rpc.HexNumber `json:"value"` Value *hexutil.Big `json:"value"`
V *rpc.HexNumber `json:"v"` V *hexutil.Big `json:"v"`
R *rpc.HexNumber `json:"r"` R *hexutil.Big `json:"r"`
S *rpc.HexNumber `json:"s"` S *hexutil.Big `json:"s"`
} }
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation // newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation
@ -699,25 +684,25 @@ func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction {
signer = types.NewEIP155Signer(tx.ChainId()) signer = types.NewEIP155Signer(tx.ChainId())
} }
from, _ := types.Sender(signer, tx) from, _ := types.Sender(signer, tx)
v, r, s := types.SignatureValues(signer, tx) v, r, s := tx.RawSignatureValues()
return &RPCTransaction{ return &RPCTransaction{
From: from, From: from,
Gas: rpc.NewHexNumber(tx.Gas()), Gas: (*hexutil.Big)(tx.Gas()),
GasPrice: rpc.NewHexNumber(tx.GasPrice()), GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(), Hash: tx.Hash(),
Input: rpc.HexBytes(tx.Data()), Input: hexutil.Bytes(tx.Data()),
Nonce: rpc.NewHexNumber(tx.Nonce()), Nonce: hexutil.Uint64(tx.Nonce()),
To: tx.To(), To: tx.To(),
Value: rpc.NewHexNumber(tx.Value()), Value: (*hexutil.Big)(tx.Value()),
V: rpc.NewHexNumber(v), V: (*hexutil.Big)(v),
R: rpc.NewHexNumber(r), R: (*hexutil.Big)(r),
S: rpc.NewHexNumber(s), S: (*hexutil.Big)(s),
} }
} }
// newRPCTransaction returns a transaction that will serialize to the RPC representation. // newRPCTransaction returns a transaction that will serialize to the RPC representation.
func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransaction, error) { func newRPCTransactionFromBlockIndex(b *types.Block, txIndex uint) (*RPCTransaction, error) {
if txIndex >= 0 && txIndex < len(b.Transactions()) { if txIndex < uint(len(b.Transactions())) {
tx := b.Transactions()[txIndex] tx := b.Transactions()[txIndex]
var signer types.Signer = types.FrontierSigner{} var signer types.Signer = types.FrontierSigner{}
if tx.Protected() { if tx.Protected() {
@ -727,19 +712,19 @@ func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransacti
v, r, s := tx.RawSignatureValues() v, r, s := tx.RawSignatureValues()
return &RPCTransaction{ return &RPCTransaction{
BlockHash: b.Hash(), BlockHash: b.Hash(),
BlockNumber: rpc.NewHexNumber(b.Number()), BlockNumber: (*hexutil.Big)(b.Number()),
From: from, From: from,
Gas: rpc.NewHexNumber(tx.Gas()), Gas: (*hexutil.Big)(tx.Gas()),
GasPrice: rpc.NewHexNumber(tx.GasPrice()), GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(), Hash: tx.Hash(),
Input: rpc.HexBytes(tx.Data()), Input: hexutil.Bytes(tx.Data()),
Nonce: rpc.NewHexNumber(tx.Nonce()), Nonce: hexutil.Uint64(tx.Nonce()),
To: tx.To(), To: tx.To(),
TransactionIndex: rpc.NewHexNumber(txIndex), TransactionIndex: hexutil.Uint(txIndex),
Value: rpc.NewHexNumber(tx.Value()), Value: (*hexutil.Big)(tx.Value()),
V: rpc.NewHexNumber(v), V: (*hexutil.Big)(v),
R: rpc.NewHexNumber(r), R: (*hexutil.Big)(r),
S: rpc.NewHexNumber(s), S: (*hexutil.Big)(s),
}, nil }, nil
} }
@ -747,8 +732,8 @@ func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransacti
} }
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index. // newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
func newRPCRawTransactionFromBlockIndex(b *types.Block, txIndex int) (rpc.HexBytes, error) { func newRPCRawTransactionFromBlockIndex(b *types.Block, txIndex uint) (hexutil.Bytes, error) {
if txIndex >= 0 && txIndex < len(b.Transactions()) { if txIndex < uint(len(b.Transactions())) {
tx := b.Transactions()[txIndex] tx := b.Transactions()[txIndex]
return rlp.EncodeToBytes(tx) return rlp.EncodeToBytes(tx)
} }
@ -760,7 +745,7 @@ func newRPCRawTransactionFromBlockIndex(b *types.Block, txIndex int) (rpc.HexByt
func newRPCTransaction(b *types.Block, txHash common.Hash) (*RPCTransaction, error) { func newRPCTransaction(b *types.Block, txHash common.Hash) (*RPCTransaction, error) {
for idx, tx := range b.Transactions() { for idx, tx := range b.Transactions() {
if tx.Hash() == txHash { if tx.Hash() == txHash {
return newRPCTransactionFromBlockIndex(b, idx) return newRPCTransactionFromBlockIndex(b, uint(idx))
} }
} }
@ -796,55 +781,57 @@ func getTransaction(chainDb ethdb.Database, b Backend, txHash common.Hash) (*typ
} }
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *rpc.HexNumber { func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return rpc.NewHexNumber(len(block.Transactions())) n := hexutil.Uint(len(block.Transactions()))
return &n
} }
return nil return nil
} }
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *rpc.HexNumber { func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
return rpc.NewHexNumber(len(block.Transactions())) n := hexutil.Uint(len(block.Transactions()))
return &n
} }
return nil return nil
} }
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index. // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (*RPCTransaction, error) { func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (*RPCTransaction, error) {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCTransactionFromBlockIndex(block, index.Int()) return newRPCTransactionFromBlockIndex(block, uint(index))
} }
return nil, nil return nil, nil
} }
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (*RPCTransaction, error) { func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (*RPCTransaction, error) {
if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
return newRPCTransactionFromBlockIndex(block, index.Int()) return newRPCTransactionFromBlockIndex(block, uint(index))
} }
return nil, nil return nil, nil
} }
// GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index. // GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (rpc.HexBytes, error) { func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (hexutil.Bytes, error) {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCRawTransactionFromBlockIndex(block, index.Int()) return newRPCRawTransactionFromBlockIndex(block, uint(index))
} }
return nil, nil return nil, nil
} }
// GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index. // GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (rpc.HexBytes, error) { func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (hexutil.Bytes, error) {
if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { if block, _ := s.b.GetBlock(ctx, blockHash); block != nil {
return newRPCRawTransactionFromBlockIndex(block, index.Int()) return newRPCRawTransactionFromBlockIndex(block, uint(index))
} }
return nil, nil return nil, 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, address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) { func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) {
state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil { if state == nil || err != nil {
return nil, err return nil, err
@ -853,7 +840,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, addr
if err != nil { if err != nil {
return nil, err return nil, err
} }
return rpc.NewHexNumber(nonce), nil return (*hexutil.Uint64)(&nonce), nil
} }
// getTransactionBlockData fetches the meta data for the given transaction from the chain database. This is useful to // getTransactionBlockData fetches the meta data for the given transaction from the chain database. This is useful to
@ -909,7 +896,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, txH
} }
// GetRawTransactionByHash returns the bytes of the transaction for the given hash. // GetRawTransactionByHash returns the bytes of the transaction for the given hash.
func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, txHash common.Hash) (rpc.HexBytes, error) { func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, txHash common.Hash) (hexutil.Bytes, error) {
var tx *types.Transaction var tx *types.Transaction
var err error var err error
@ -950,15 +937,15 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma
from, _ := types.Sender(signer, tx) from, _ := types.Sender(signer, tx)
fields := map[string]interface{}{ fields := map[string]interface{}{
"root": rpc.HexBytes(receipt.PostState), "root": hexutil.Bytes(receipt.PostState),
"blockHash": txBlock, "blockHash": txBlock,
"blockNumber": rpc.NewHexNumber(blockIndex), "blockNumber": hexutil.Uint64(blockIndex),
"transactionHash": txHash, "transactionHash": txHash,
"transactionIndex": rpc.NewHexNumber(index), "transactionIndex": hexutil.Uint64(index),
"from": from, "from": from,
"to": tx.To(), "to": tx.To(),
"gasUsed": rpc.NewHexNumber(receipt.GasUsed), "gasUsed": (*hexutil.Big)(receipt.GasUsed),
"cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed), "cumulativeGasUsed": (*hexutil.Big)(receipt.CumulativeGasUsed),
"contractAddress": nil, "contractAddress": nil,
"logs": receipt.Logs, "logs": receipt.Logs,
"logsBloom": receipt.Bloom, "logsBloom": receipt.Bloom,
@ -988,32 +975,46 @@ func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transacti
type SendTxArgs struct { type SendTxArgs struct {
From common.Address `json:"from"` From common.Address `json:"from"`
To *common.Address `json:"to"` To *common.Address `json:"to"`
Gas *rpc.HexNumber `json:"gas"` Gas *hexutil.Big `json:"gas"`
GasPrice *rpc.HexNumber `json:"gasPrice"` GasPrice *hexutil.Big `json:"gasPrice"`
Value *rpc.HexNumber `json:"value"` Value *hexutil.Big `json:"value"`
Data string `json:"data"` Data hexutil.Bytes `json:"data"`
Nonce *rpc.HexNumber `json:"nonce"` Nonce *hexutil.Uint64 `json:"nonce"`
} }
// prepareSendTxArgs is a helper function that fills in default values for unspecified tx fields. // prepareSendTxArgs is a helper function that fills in default values for unspecified tx fields.
func prepareSendTxArgs(ctx context.Context, args SendTxArgs, b Backend) (SendTxArgs, error) { func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
if args.Gas == nil { if args.Gas == nil {
args.Gas = rpc.NewHexNumber(defaultGas) args.Gas = (*hexutil.Big)(big.NewInt(defaultGas))
} }
if args.GasPrice == nil { if args.GasPrice == nil {
price, err := b.SuggestPrice(ctx) price, err := b.SuggestPrice(ctx)
if err != nil { if err != nil {
return args, err return err
} }
args.GasPrice = rpc.NewHexNumber(price) args.GasPrice = (*hexutil.Big)(price)
} }
if args.Value == nil { if args.Value == nil {
args.Value = rpc.NewHexNumber(0) args.Value = new(hexutil.Big)
}
if args.Nonce == nil {
nonce, err := b.GetPoolNonce(ctx, args.From)
if err != nil {
return err
}
args.Nonce = (*hexutil.Uint64)(&nonce)
}
return nil
}
func (args *SendTxArgs) toTransaction() *types.Transaction {
if args.To == nil {
return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), args.Data)
} }
return args, nil return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), args.Data)
} }
// submitTransaction is a helper function that submits tx to txPool and creates a log entry. // submitTransaction is a helper function that submits tx to txPool and logs a message.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, signature []byte) (common.Hash, error) { func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, signature []byte) (common.Hash, error) {
signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number()) signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
@ -1040,27 +1041,10 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, si
// SendTransaction creates a transaction for the given argument, sign it and submit it to the // SendTransaction creates a transaction for the given argument, sign it and submit it to the
// transaction pool. // transaction pool.
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) { func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
var err error if err := args.setDefaults(ctx, s.b); err != nil {
args, err = prepareSendTxArgs(ctx, args, s.b)
if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
tx := args.toTransaction()
if args.Nonce == nil {
nonce, err := s.b.GetPoolNonce(ctx, args.From)
if err != nil {
return common.Hash{}, err
}
args.Nonce = rpc.NewHexNumber(nonce)
}
var tx *types.Transaction
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
}
signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number()) signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
signature, err := s.b.AccountManager().SignEthereum(args.From, signer.Hash(tx).Bytes()) signature, err := s.b.AccountManager().SignEthereum(args.From, signer.Hash(tx).Bytes())
if err != nil { if err != nil {
@ -1072,9 +1056,9 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
// SendRawTransaction will add the signed transaction to the transaction pool. // SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce. // The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx string) (string, error) { func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (string, error) {
tx := new(types.Transaction) tx := new(types.Transaction)
if err := rlp.DecodeBytes(common.FromHex(encodedTx), tx); err != nil { if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return "", err return "", err
} }
@ -1107,153 +1091,28 @@ func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes)
return s.b.AccountManager().SignEthereum(addr, signHash(data)) return s.b.AccountManager().SignEthereum(addr, signHash(data))
} }
// SignTransactionArgs represents the arguments to sign a transaction.
type SignTransactionArgs struct {
From common.Address
To *common.Address
Nonce *rpc.HexNumber
Value *rpc.HexNumber
Gas *rpc.HexNumber
GasPrice *rpc.HexNumber
Data string
BlockNumber int64
}
// Tx is a helper object for argument and return values
type Tx struct {
tx *types.Transaction
To *common.Address `json:"to"`
From common.Address `json:"from"`
Nonce *rpc.HexNumber `json:"nonce"`
Value *rpc.HexNumber `json:"value"`
Data string `json:"data"`
GasLimit *rpc.HexNumber `json:"gas"`
GasPrice *rpc.HexNumber `json:"gasPrice"`
Hash common.Hash `json:"hash"`
}
// UnmarshalJSON parses JSON data into tx.
func (tx *Tx) UnmarshalJSON(b []byte) (err error) {
req := struct {
To *common.Address `json:"to"`
From common.Address `json:"from"`
Nonce *rpc.HexNumber `json:"nonce"`
Value *rpc.HexNumber `json:"value"`
Data string `json:"data"`
GasLimit *rpc.HexNumber `json:"gas"`
GasPrice *rpc.HexNumber `json:"gasPrice"`
Hash common.Hash `json:"hash"`
}{}
if err := json.Unmarshal(b, &req); err != nil {
return err
}
tx.To = req.To
tx.From = req.From
tx.Nonce = req.Nonce
tx.Value = req.Value
tx.Data = req.Data
tx.GasLimit = req.GasLimit
tx.GasPrice = req.GasPrice
tx.Hash = req.Hash
data := common.Hex2Bytes(tx.Data)
if tx.Nonce == nil {
return fmt.Errorf("need nonce")
}
if tx.Value == nil {
tx.Value = rpc.NewHexNumber(0)
}
if tx.GasLimit == nil {
tx.GasLimit = rpc.NewHexNumber(0)
}
if tx.GasPrice == nil {
tx.GasPrice = rpc.NewHexNumber(int64(50000000000))
}
if req.To == nil {
tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
} else {
tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data)
}
return nil
}
// SignTransactionResult represents a RLP encoded signed transaction. // SignTransactionResult represents a RLP encoded signed transaction.
type SignTransactionResult struct { type SignTransactionResult struct {
Raw string `json:"raw"` Raw hexutil.Bytes `json:"raw"`
Tx *Tx `json:"tx"` Tx *types.Transaction `json:"tx"`
}
func newTx(t *types.Transaction) *Tx {
var signer types.Signer = types.HomesteadSigner{}
if t.Protected() {
signer = types.NewEIP155Signer(t.ChainId())
}
from, _ := types.Sender(signer, t)
return &Tx{
tx: t,
To: t.To(),
From: from,
Value: rpc.NewHexNumber(t.Value()),
Nonce: rpc.NewHexNumber(t.Nonce()),
Data: "0x" + common.Bytes2Hex(t.Data()),
GasLimit: rpc.NewHexNumber(t.Gas()),
GasPrice: rpc.NewHexNumber(t.GasPrice()),
Hash: t.Hash(),
}
} }
// SignTransaction will sign the given transaction with the from account. // SignTransaction will sign the given transaction with the from account.
// The node needs to have the private key of the account corresponding with // The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked. // the given from address and it needs to be unlocked.
func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SignTransactionArgs) (*SignTransactionResult, error) { func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {
if args.Gas == nil { if err := args.setDefaults(ctx, s.b); err != nil {
args.Gas = rpc.NewHexNumber(defaultGas) return nil, err
}
if args.GasPrice == nil {
price, err := s.b.SuggestPrice(ctx)
if err != nil {
return nil, err
}
args.GasPrice = rpc.NewHexNumber(price)
}
if args.Value == nil {
args.Value = rpc.NewHexNumber(0)
}
if args.Nonce == nil {
nonce, err := s.b.GetPoolNonce(ctx, args.From)
if err != nil {
return nil, err
}
args.Nonce = rpc.NewHexNumber(nonce)
}
var tx *types.Transaction
if args.To == nil {
tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
} else {
tx = types.NewTransaction(args.Nonce.Uint64(), *args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data))
} }
tx, err := s.sign(args.From, args.toTransaction())
signedTx, err := s.sign(args.From, tx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
data, err := rlp.EncodeToBytes(tx)
data, err := rlp.EncodeToBytes(signedTx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &SignTransactionResult{data, tx}, nil
return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(signedTx)}, nil
} }
// PendingTransactions returns the transactions that are in the transaction pool and have a from address that is one of // PendingTransactions returns the transactions that are in the transaction pool and have a from address that is one of
@ -1278,9 +1137,16 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
return transactions, nil return transactions, nil
} }
// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the // Resend accepts an existing transaction and a new gas price and limit. It will remove
// pool and reinsert it with the new gas price and limit. // the given transaction from the pool and reinsert it with the new gas price and limit.
func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) { func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice, gasLimit *hexutil.Big) (common.Hash, error) {
if sendArgs.Nonce == nil {
return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec")
}
if err := sendArgs.setDefaults(ctx, s.b); err != nil {
return common.Hash{}, err
}
matchTx := sendArgs.toTransaction()
pending, err := s.b.GetPoolTransactions() pending, err := s.b.GetPoolTransactions()
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
@ -1291,37 +1157,29 @@ func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, tx Tx, gasPrice,
if p.Protected() { if p.Protected() {
signer = types.NewEIP155Signer(p.ChainId()) signer = types.NewEIP155Signer(p.ChainId())
} }
wantSigHash := signer.Hash(matchTx)
if pFrom, err := types.Sender(signer, p); err == nil && pFrom == tx.From && signer.Hash(p) == signer.Hash(tx.tx) { if pFrom, err := types.Sender(signer, p); err == nil && pFrom == sendArgs.From && signer.Hash(p) == wantSigHash {
if gasPrice == nil { // Match. Re-sign and send the transaction.
gasPrice = rpc.NewHexNumber(tx.tx.GasPrice()) if gasPrice != nil {
} sendArgs.GasPrice = gasPrice
if gasLimit == nil {
gasLimit = rpc.NewHexNumber(tx.tx.Gas())
} }
if gasLimit != nil {
var newTx *types.Transaction sendArgs.Gas = gasLimit
if tx.tx.To() == nil {
newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
} else {
newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasLimit.BigInt(), gasPrice.BigInt(), tx.tx.Data())
} }
signedTx, err := s.sign(sendArgs.From, sendArgs.toTransaction())
signedTx, err := s.sign(tx.From, newTx)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
s.b.RemoveTx(p.Hash())
s.b.RemoveTx(tx.Hash)
if err = s.b.SendTx(ctx, signedTx); err != nil { if err = s.b.SendTx(ctx, signedTx); err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
return signedTx.Hash(), nil return signedTx.Hash(), nil
} }
} }
return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash) return common.Hash{}, fmt.Errorf("Transaction %#x not found", matchTx.Hash())
} }
// PublicDebugAPI is the collection of Etheruem APIs exposed over the public // PublicDebugAPI is the collection of Etheruem APIs exposed over the public
@ -1418,8 +1276,8 @@ func (api *PrivateDebugAPI) ChaindbCompact() error {
} }
// SetHead rewinds the head of the blockchain to a previous block. // SetHead rewinds the head of the blockchain to a previous block.
func (api *PrivateDebugAPI) SetHead(number rpc.HexNumber) { func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) {
api.b.SetHead(uint64(number.Int64())) api.b.SetHead(uint64(number))
} }
// PublicNetAPI offers network related RPC methods // PublicNetAPI offers network related RPC methods
@ -1439,8 +1297,8 @@ func (s *PublicNetAPI) Listening() bool {
} }
// PeerCount returns the number of connected peers // PeerCount returns the number of connected peers
func (s *PublicNetAPI) PeerCount() *rpc.HexNumber { func (s *PublicNetAPI) PeerCount() hexutil.Uint {
return rpc.NewHexNumber(s.net.PeerCount()) return hexutil.Uint(s.net.PeerCount())
} }
// Version returns the current ethereum protocol version. // Version returns the current ethereum protocol version.

@ -71,7 +71,7 @@ func New(assetPath string, output io.Writer) *JSRE {
} }
go re.runEventLoop() go re.runEventLoop()
re.Set("loadScript", re.loadScript) re.Set("loadScript", re.loadScript)
re.Set("inspect", prettyPrintJS) re.Set("inspect", re.prettyPrintJS)
return re return re
} }

@ -73,10 +73,10 @@ func jsErrorString(err error) string {
return err.Error() return err.Error()
} }
func prettyPrintJS(call otto.FunctionCall, w io.Writer) otto.Value { func (re *JSRE) prettyPrintJS(call otto.FunctionCall) otto.Value {
for _, v := range call.ArgumentList { for _, v := range call.ArgumentList {
prettyPrint(call.Otto, v, w) prettyPrint(call.Otto, v, re.output)
fmt.Fprintln(w) fmt.Fprintln(re.output)
} }
return otto.UndefinedValue() return otto.UndefinedValue()
} }

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler" "github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -135,8 +136,8 @@ func (s *LightDummyAPI) Coinbase() (common.Address, error) {
} }
// Hashrate returns the POW hashrate // Hashrate returns the POW hashrate
func (s *LightDummyAPI) Hashrate() *rpc.HexNumber { func (s *LightDummyAPI) Hashrate() hexutil.Uint {
return rpc.NewHexNumber(0) return 0
} }
// Mining returns an indication if this node is currently mining. // Mining returns an indication if this node is currently mining.

@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/rpc"
"github.com/rcrowley/go-metrics" "github.com/rcrowley/go-metrics"
) )
@ -75,7 +74,7 @@ func (api *PrivateAdminAPI) RemovePeer(url string) (bool, error) {
} }
// StartRPC starts the HTTP RPC API server. // StartRPC starts the HTTP RPC API server.
func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) { func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis *string) (bool, error) {
api.node.lock.Lock() api.node.lock.Lock()
defer api.node.lock.Unlock() defer api.node.lock.Unlock()
@ -91,7 +90,7 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st
host = &h host = &h
} }
if port == nil { if port == nil {
port = rpc.NewHexNumber(api.node.config.HTTPPort) port = &api.node.config.HTTPPort
} }
if cors == nil { if cors == nil {
cors = &api.node.config.HTTPCors cors = &api.node.config.HTTPCors
@ -105,7 +104,7 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *st
} }
} }
if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *cors); err != nil { if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, port), api.node.rpcAPIs, modules, *cors); err != nil {
return false, err return false, err
} }
return true, nil return true, nil
@ -124,7 +123,7 @@ func (api *PrivateAdminAPI) StopRPC() (bool, error) {
} }
// StartWS starts the websocket RPC API server. // StartWS starts the websocket RPC API server.
func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOrigins *string, apis *string) (bool, error) { func (api *PrivateAdminAPI) StartWS(host *string, port *int, allowedOrigins *string, apis *string) (bool, error) {
api.node.lock.Lock() api.node.lock.Lock()
defer api.node.lock.Unlock() defer api.node.lock.Unlock()
@ -140,7 +139,7 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr
host = &h host = &h
} }
if port == nil { if port == nil {
port = rpc.NewHexNumber(api.node.config.WSPort) port = &api.node.config.WSPort
} }
if allowedOrigins == nil { if allowedOrigins == nil {
allowedOrigins = &api.node.config.WSOrigins allowedOrigins = &api.node.config.WSOrigins
@ -154,7 +153,7 @@ func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOr
} }
} }
if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *allowedOrigins); err != nil { if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, *allowedOrigins); err != nil {
return false, err return false, err
} }
return true, nil return true, nil

@ -17,6 +17,7 @@
package rpc package rpc
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -256,8 +257,8 @@ func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error)
return requests, true, nil return requests, true, nil
} }
// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given types. It returns the parsed // ParseRequestArguments tries to parse the given params (json.RawMessage) with the given
// values or an error when the parsing failed. // types. It returns the parsed values or an error when the parsing failed.
func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) { func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) {
if args, ok := params.(json.RawMessage); !ok { if args, ok := params.(json.RawMessage); !ok {
return nil, &invalidParamsError{"Invalid params supplied"} return nil, &invalidParamsError{"Invalid params supplied"}
@ -266,42 +267,42 @@ func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interf
} }
} }
// parsePositionalArguments tries to parse the given args to an array of values with the given types. // parsePositionalArguments tries to parse the given args to an array of values with the
// It returns the parsed values or an error when the args could not be parsed. Missing optional arguments // given types. It returns the parsed values or an error when the args could not be
// are returned as reflect.Zero values. // parsed. Missing optional arguments are returned as reflect.Zero values.
func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, Error) { func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, Error) {
params := make([]interface{}, 0, len(callbackArgs)) // Read beginning of the args array.
for _, t := range callbackArgs { dec := json.NewDecoder(bytes.NewReader(rawArgs))
params = append(params, reflect.New(t).Interface()) if tok, _ := dec.Token(); tok != json.Delim('[') {
return nil, &invalidParamsError{"non-array args"}
} }
// Read args.
if err := json.Unmarshal(args, &params); err != nil { args := make([]reflect.Value, 0, len(types))
return nil, &invalidParamsError{err.Error()} for i := 0; dec.More(); i++ {
} if i >= len(types) {
return nil, &invalidParamsError{fmt.Sprintf("too many arguments, want at most %d", len(types))}
if len(params) > len(callbackArgs) { }
return nil, &invalidParamsError{fmt.Sprintf("too many params, want %d got %d", len(callbackArgs), len(params))} argval := reflect.New(types[i])
if err := dec.Decode(argval.Interface()); err != nil {
return nil, &invalidParamsError{fmt.Sprintf("invalid argument %d: %v", i, err)}
}
if argval.IsNil() && types[i].Kind() != reflect.Ptr {
return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
}
args = append(args, argval.Elem())
} }
// Read end of args array.
// assume missing params are null values if _, err := dec.Token(); err != nil {
for i := len(params); i < len(callbackArgs); i++ { return nil, &invalidParamsError{err.Error()}
params = append(params, nil)
} }
// Set any missing args to nil.
argValues := make([]reflect.Value, len(params)) for i := len(args); i < len(types); i++ {
for i, p := range params { if types[i].Kind() != reflect.Ptr {
// verify that JSON null values are only supplied for optional arguments (ptr types) return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
if p == nil && callbackArgs[i].Kind() != reflect.Ptr {
return nil, &invalidParamsError{fmt.Sprintf("invalid or missing value for params[%d]", i)}
}
if p == nil {
argValues[i] = reflect.Zero(callbackArgs[i])
} else { // deref pointers values creates previously with reflect.New
argValues[i] = reflect.ValueOf(p).Elem()
} }
args = append(args, reflect.Zero(types[i]))
} }
return args, nil
return argValues, nil
} }
// CreateResponse will create a JSON-RPC success response with the given id and reply as result. // CreateResponse will create a JSON-RPC success response with the given id and reply as result.

@ -17,8 +17,6 @@
package rpc package rpc
import ( import (
"bytes"
"encoding/hex"
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
@ -123,91 +121,6 @@ type ServerCodec interface {
Closed() <-chan interface{} Closed() <-chan interface{}
} }
// HexNumber serializes a number to hex format using the "%#x" format
type HexNumber big.Int
// NewHexNumber creates a new hex number instance which will serialize the given val with `%#x` on marshal.
func NewHexNumber(val interface{}) *HexNumber {
if val == nil {
return nil // note, this doesn't catch nil pointers, only passing nil directly!
}
if v, ok := val.(*big.Int); ok {
if v != nil {
return (*HexNumber)(new(big.Int).Set(v))
}
return nil
}
rval := reflect.ValueOf(val)
var unsigned uint64
utype := reflect.TypeOf(unsigned)
if t := rval.Type(); t.ConvertibleTo(utype) {
hn := new(big.Int).SetUint64(rval.Convert(utype).Uint())
return (*HexNumber)(hn)
}
var signed int64
stype := reflect.TypeOf(signed)
if t := rval.Type(); t.ConvertibleTo(stype) {
hn := new(big.Int).SetInt64(rval.Convert(stype).Int())
return (*HexNumber)(hn)
}
return nil
}
func (h *HexNumber) UnmarshalJSON(input []byte) error {
length := len(input)
if length >= 2 && input[0] == '"' && input[length-1] == '"' {
input = input[1 : length-1]
}
hn := (*big.Int)(h)
if _, ok := hn.SetString(string(input), 0); ok {
return nil
}
return fmt.Errorf("Unable to parse number")
}
// MarshalJSON serialize the hex number instance to a hex representation.
func (h *HexNumber) MarshalJSON() ([]byte, error) {
if h != nil {
hn := (*big.Int)(h)
if hn.BitLen() == 0 {
return []byte(`"0x0"`), nil
}
return []byte(fmt.Sprintf(`"0x%x"`, hn)), nil
}
return nil, nil
}
func (h *HexNumber) Int() int {
hn := (*big.Int)(h)
return int(hn.Int64())
}
func (h *HexNumber) Int64() int64 {
hn := (*big.Int)(h)
return hn.Int64()
}
func (h *HexNumber) Uint() uint {
hn := (*big.Int)(h)
return uint(hn.Uint64())
}
func (h *HexNumber) Uint64() uint64 {
hn := (*big.Int)(h)
return hn.Uint64()
}
func (h *HexNumber) BigInt() *big.Int {
return (*big.Int)(h)
}
var ( var (
pendingBlockNumber = big.NewInt(-2) pendingBlockNumber = big.NewInt(-2)
latestBlockNumber = big.NewInt(-1) latestBlockNumber = big.NewInt(-1)
@ -274,31 +187,3 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
func (bn BlockNumber) Int64() int64 { func (bn BlockNumber) Int64() int64 {
return (int64)(bn) return (int64)(bn)
} }
// HexBytes JSON-encodes as hex with 0x prefix.
type HexBytes []byte
func (b HexBytes) MarshalJSON() ([]byte, error) {
result := make([]byte, len(b)*2+4)
copy(result, `"0x`)
hex.Encode(result[3:], b)
result[len(result)-1] = '"'
return result, nil
}
func (b *HexBytes) UnmarshalJSON(input []byte) error {
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
input = input[1 : len(input)-1]
}
if !bytes.HasPrefix(input, []byte("0x")) {
return fmt.Errorf("missing 0x prefix for hex byte array")
}
input = input[2:]
if len(input) == 0 {
*b = nil
return nil
}
*b = make([]byte, len(input)/2)
_, err := hex.Decode(*b, input)
return err
}

@ -1,95 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rpc
import (
"bytes"
"encoding/json"
"math/big"
"testing"
)
func TestNewHexNumber(t *testing.T) {
tests := []interface{}{big.NewInt(123), int64(123), uint64(123), int8(123), uint8(123)}
for i, v := range tests {
hn := NewHexNumber(v)
if hn == nil {
t.Fatalf("Unable to create hex number instance for tests[%d]", i)
}
if hn.Int64() != 123 {
t.Fatalf("expected %d, got %d on value tests[%d]", 123, hn.Int64(), i)
}
}
failures := []interface{}{"", nil, []byte{1, 2, 3, 4}}
for i, v := range failures {
hn := NewHexNumber(v)
if hn != nil {
t.Fatalf("Creating a nex number instance of %T should fail (failures[%d])", failures[i], i)
}
}
}
func TestHexNumberUnmarshalJSON(t *testing.T) {
tests := []string{`"0x4d2"`, "1234", `"1234"`}
for i, v := range tests {
var hn HexNumber
if err := json.Unmarshal([]byte(v), &hn); err != nil {
t.Fatalf("Test %d failed - %s", i, err)
}
if hn.Int64() != 1234 {
t.Fatalf("Expected %d, got %d for test[%d]", 1234, hn.Int64(), i)
}
}
}
func TestHexNumberMarshalJSON(t *testing.T) {
hn := NewHexNumber(1234567890)
got, err := json.Marshal(hn)
if err != nil {
t.Fatalf("Unable to marshal hex number - %s", err)
}
exp := []byte(`"0x499602d2"`)
if bytes.Compare(exp, got) != 0 {
t.Fatalf("Invalid json.Marshal, expected '%s', got '%s'", exp, got)
}
}
var hexBytesTests = []struct{ in, out []byte }{
{in: []byte(`"0x"`), out: []byte{}},
{in: []byte(`"0x00"`), out: []byte{0}},
{in: []byte(`"0x01ff"`), out: []byte{0x01, 0xFF}},
}
func TestHexBytes(t *testing.T) {
for i, test := range hexBytesTests {
var dec HexBytes
if err := json.Unmarshal(test.in, &dec); err != nil {
t.Fatalf("test %d: can't decode: %v", i, err)
}
enc, _ := json.Marshal(HexBytes(test.out))
if !bytes.Equal(dec, test.out) {
t.Errorf("test %d: wrong decoded value 0x%x", i, dec)
}
if !bytes.Equal(enc, test.in) {
t.Errorf("test %d: wrong encoded value %#q", i, enc)
}
}
}

@ -23,6 +23,7 @@ import (
mathrand "math/rand" mathrand "math/rand"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -72,16 +73,16 @@ func (api *PublicWhisperAPI) Stop() error {
} }
// Version returns the Whisper version this node offers. // Version returns the Whisper version this node offers.
func (api *PublicWhisperAPI) Version() (*rpc.HexNumber, error) { func (api *PublicWhisperAPI) Version() (hexutil.Uint, error) {
if api.whisper == nil { if api.whisper == nil {
return rpc.NewHexNumber(0), whisperOffLineErr return 0, whisperOffLineErr
} }
return rpc.NewHexNumber(api.whisper.Version()), nil return hexutil.Uint(api.whisper.Version()), nil
} }
// MarkPeerTrusted marks specific peer trusted, which will allow it // MarkPeerTrusted marks specific peer trusted, which will allow it
// to send historic (expired) messages. // to send historic (expired) messages.
func (api *PublicWhisperAPI) MarkPeerTrusted(peerID rpc.HexBytes) error { func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error {
if api.whisper == nil { if api.whisper == nil {
return whisperOffLineErr return whisperOffLineErr
} }
@ -92,7 +93,7 @@ func (api *PublicWhisperAPI) MarkPeerTrusted(peerID rpc.HexBytes) error {
// data contains parameters (time frame, payment details, etc.), required // data contains parameters (time frame, payment details, etc.), required
// by the remote email-like server. Whisper is not aware about the data format, // by the remote email-like server. Whisper is not aware about the data format,
// it will just forward the raw data to the server. // it will just forward the raw data to the server.
func (api *PublicWhisperAPI) RequestHistoricMessages(peerID rpc.HexBytes, data rpc.HexBytes) error { func (api *PublicWhisperAPI) RequestHistoricMessages(peerID hexutil.Bytes, data hexutil.Bytes) error {
if api.whisper == nil { if api.whisper == nil {
return whisperOffLineErr return whisperOffLineErr
} }
@ -388,12 +389,12 @@ type PostArgs struct {
To string `json:"to"` To string `json:"to"`
KeyName string `json:"keyname"` KeyName string `json:"keyname"`
Topic whisperv5.TopicType `json:"topic"` Topic whisperv5.TopicType `json:"topic"`
Padding rpc.HexBytes `json:"padding"` Padding hexutil.Bytes `json:"padding"`
Payload rpc.HexBytes `json:"payload"` Payload hexutil.Bytes `json:"payload"`
WorkTime uint32 `json:"worktime"` WorkTime uint32 `json:"worktime"`
PoW float64 `json:"pow"` PoW float64 `json:"pow"`
FilterID uint32 `json:"filterID"` FilterID uint32 `json:"filterID"`
PeerID rpc.HexBytes `json:"peerID"` PeerID hexutil.Bytes `json:"peerID"`
} }
type WhisperFilterArgs struct { type WhisperFilterArgs struct {

@ -39,8 +39,8 @@ func TestBasic(t *testing.T) {
t.Fatalf("failed generateFilter: %s.", err) t.Fatalf("failed generateFilter: %s.", err)
} }
if ver.Uint64() != whisperv5.ProtocolVersion { if uint64(ver) != whisperv5.ProtocolVersion {
t.Fatalf("wrong version: %d.", ver.Uint64()) t.Fatalf("wrong version: %d.", ver)
} }
mail := api.GetFilterChanges(1) mail := api.GetFilterChanges(1)

@ -23,8 +23,8 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
) )
// PublicWhisperAPI provides the whisper RPC service. // PublicWhisperAPI provides the whisper RPC service.
@ -32,7 +32,7 @@ type PublicWhisperAPI struct {
w *Whisper w *Whisper
messagesMu sync.RWMutex messagesMu sync.RWMutex
messages map[int]*whisperFilter messages map[hexutil.Uint]*whisperFilter
} }
type whisperOfflineError struct{} type whisperOfflineError struct{}
@ -46,15 +46,15 @@ var whisperOffLineErr = new(whisperOfflineError)
// NewPublicWhisperAPI create a new RPC whisper service. // NewPublicWhisperAPI create a new RPC whisper service.
func NewPublicWhisperAPI(w *Whisper) *PublicWhisperAPI { func NewPublicWhisperAPI(w *Whisper) *PublicWhisperAPI {
return &PublicWhisperAPI{w: w, messages: make(map[int]*whisperFilter)} return &PublicWhisperAPI{w: w, messages: make(map[hexutil.Uint]*whisperFilter)}
} }
// Version returns the Whisper version this node offers. // Version returns the Whisper version this node offers.
func (s *PublicWhisperAPI) Version() (*rpc.HexNumber, error) { func (s *PublicWhisperAPI) Version() (hexutil.Uint, error) {
if s.w == nil { if s.w == nil {
return rpc.NewHexNumber(0), whisperOffLineErr return 0, whisperOffLineErr
} }
return rpc.NewHexNumber(s.w.Version()), nil return hexutil.Uint(s.w.Version()), nil
} }
// HasIdentity checks if the the whisper node is configured with the private key // HasIdentity checks if the the whisper node is configured with the private key
@ -84,12 +84,12 @@ type NewFilterArgs struct {
} }
// NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages. // NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages.
func (s *PublicWhisperAPI) NewFilter(args NewFilterArgs) (*rpc.HexNumber, error) { func (s *PublicWhisperAPI) NewFilter(args NewFilterArgs) (hexutil.Uint, error) {
if s.w == nil { if s.w == nil {
return nil, whisperOffLineErr return 0, whisperOffLineErr
} }
var id int var id hexutil.Uint
filter := Filter{ filter := Filter{
To: crypto.ToECDSAPub(common.FromHex(args.To)), To: crypto.ToECDSAPub(common.FromHex(args.To)),
From: crypto.ToECDSAPub(common.FromHex(args.From)), From: crypto.ToECDSAPub(common.FromHex(args.From)),
@ -103,23 +103,22 @@ func (s *PublicWhisperAPI) NewFilter(args NewFilterArgs) (*rpc.HexNumber, error)
} }
}, },
} }
id = hexutil.Uint(s.w.Watch(filter))
id = s.w.Watch(filter)
s.messagesMu.Lock() s.messagesMu.Lock()
s.messages[id] = newWhisperFilter(id, s.w) s.messages[id] = newWhisperFilter(id, s.w)
s.messagesMu.Unlock() s.messagesMu.Unlock()
return rpc.NewHexNumber(id), nil return id, nil
} }
// GetFilterChanges retrieves all the new messages matched by a filter since the last retrieval. // GetFilterChanges retrieves all the new messages matched by a filter since the last retrieval.
func (s *PublicWhisperAPI) GetFilterChanges(filterId rpc.HexNumber) []WhisperMessage { func (s *PublicWhisperAPI) GetFilterChanges(filterId hexutil.Uint) []WhisperMessage {
s.messagesMu.RLock() s.messagesMu.RLock()
defer s.messagesMu.RUnlock() defer s.messagesMu.RUnlock()
if s.messages[filterId.Int()] != nil { if s.messages[filterId] != nil {
if changes := s.messages[filterId.Int()].retrieve(); changes != nil { if changes := s.messages[filterId].retrieve(); changes != nil {
return changes return changes
} }
} }
@ -127,26 +126,26 @@ func (s *PublicWhisperAPI) GetFilterChanges(filterId rpc.HexNumber) []WhisperMes
} }
// UninstallFilter disables and removes an existing filter. // UninstallFilter disables and removes an existing filter.
func (s *PublicWhisperAPI) UninstallFilter(filterId rpc.HexNumber) bool { func (s *PublicWhisperAPI) UninstallFilter(filterId hexutil.Uint) bool {
s.messagesMu.Lock() s.messagesMu.Lock()
defer s.messagesMu.Unlock() defer s.messagesMu.Unlock()
if _, ok := s.messages[filterId.Int()]; ok { if _, ok := s.messages[filterId]; ok {
delete(s.messages, filterId.Int()) delete(s.messages, filterId)
return true return true
} }
return false return false
} }
// GetMessages retrieves all the known messages that match a specific filter. // GetMessages retrieves all the known messages that match a specific filter.
func (s *PublicWhisperAPI) GetMessages(filterId rpc.HexNumber) []WhisperMessage { func (s *PublicWhisperAPI) GetMessages(filterId hexutil.Uint) []WhisperMessage {
// Retrieve all the cached messages matching a specific, existing filter // Retrieve all the cached messages matching a specific, existing filter
s.messagesMu.RLock() s.messagesMu.RLock()
defer s.messagesMu.RUnlock() defer s.messagesMu.RUnlock()
var messages []*Message var messages []*Message
if s.messages[filterId.Int()] != nil { if s.messages[filterId] != nil {
messages = s.messages[filterId.Int()].messages() messages = s.messages[filterId].messages()
} }
return returnWhisperMessages(messages) return returnWhisperMessages(messages)
@ -217,12 +216,12 @@ type WhisperMessage struct {
func (args *PostArgs) UnmarshalJSON(data []byte) (err error) { func (args *PostArgs) UnmarshalJSON(data []byte) (err error) {
var obj struct { var obj struct {
From string `json:"from"` From string `json:"from"`
To string `json:"to"` To string `json:"to"`
Topics []string `json:"topics"` Topics []string `json:"topics"`
Payload string `json:"payload"` Payload string `json:"payload"`
Priority rpc.HexNumber `json:"priority"` Priority hexutil.Uint64 `json:"priority"`
TTL rpc.HexNumber `json:"ttl"` TTL hexutil.Uint64 `json:"ttl"`
} }
if err := json.Unmarshal(data, &obj); err != nil { if err := json.Unmarshal(data, &obj); err != nil {
@ -232,8 +231,8 @@ func (args *PostArgs) UnmarshalJSON(data []byte) (err error) {
args.From = obj.From args.From = obj.From
args.To = obj.To args.To = obj.To
args.Payload = obj.Payload args.Payload = obj.Payload
args.Priority = obj.Priority.Int64() args.Priority = int64(obj.Priority) // TODO(gluk256): handle overflow
args.TTL = obj.TTL.Int64() args.TTL = int64(obj.TTL) // ... here too ...
// decode topic strings // decode topic strings
args.Topics = make([][]byte, len(obj.Topics)) args.Topics = make([][]byte, len(obj.Topics))
@ -328,8 +327,8 @@ func (args *NewFilterArgs) UnmarshalJSON(b []byte) (err error) {
// whisperFilter is the message cache matching a specific filter, accumulating // whisperFilter is the message cache matching a specific filter, accumulating
// inbound messages until the are requested by the client. // inbound messages until the are requested by the client.
type whisperFilter struct { type whisperFilter struct {
id int // Filter identifier for old message retrieval id hexutil.Uint // Filter identifier for old message retrieval
ref *Whisper // Whisper reference for old message retrieval ref *Whisper // Whisper reference for old message retrieval
cache []WhisperMessage // Cache of messages not yet polled cache []WhisperMessage // Cache of messages not yet polled
skip map[common.Hash]struct{} // List of retrieved messages to avoid duplication skip map[common.Hash]struct{} // List of retrieved messages to avoid duplication
@ -348,7 +347,7 @@ func (w *whisperFilter) messages() []*Message {
w.update = time.Now() w.update = time.Now()
w.skip = make(map[common.Hash]struct{}) w.skip = make(map[common.Hash]struct{})
messages := w.ref.Messages(w.id) messages := w.ref.Messages(int(w.id))
for _, message := range messages { for _, message := range messages {
w.skip[message.Hash] = struct{}{} w.skip[message.Hash] = struct{}{}
} }
@ -388,11 +387,10 @@ func (w *whisperFilter) activity() time.Time {
} }
// newWhisperFilter creates a new serialized, poll based whisper topic filter. // newWhisperFilter creates a new serialized, poll based whisper topic filter.
func newWhisperFilter(id int, ref *Whisper) *whisperFilter { func newWhisperFilter(id hexutil.Uint, ref *Whisper) *whisperFilter {
return &whisperFilter{ return &whisperFilter{
id: id, id: id,
ref: ref, ref: ref,
update: time.Now(), update: time.Now(),
skip: make(map[common.Hash]struct{}), skip: make(map[common.Hash]struct{}),
} }

Loading…
Cancel
Save