// Status returns the number of pending and queued transaction in the pool. func (s *PublicTxPoolAPI) Status() map[string]*rpc.HexNumber { pending, queue := s.e.TxPool().Stats() return map[string]*rpc.HexNumber{ "pending": rpc.NewHexNumber(pending), "queued": rpc.NewHexNumber(queue), } }
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(blockNr rpc.BlockNumber) *rpc.HexNumber { if blockNr == rpc.PendingBlockNumber { return rpc.NewHexNumber(0) } if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { return rpc.NewHexNumber(len(block.Uncles())) } return nil }
// Syncing returns false in case the node is currently not synching with the network. It can be up to date or has not // yet received the latest block headers from its pears. In case it is synchronizing an object with 3 properties is // returned: // - startingBlock: block number this node started to synchronise from // - currentBlock: block number this node is currently importing // - highestBlock: block number of the highest block header this node has received from peers func (s *PublicEthereumAPI) Syncing() (interface{}, error) { origin, current, height := s.e.Downloader().Progress() if current < height { return map[string]interface{}{ "startingBlock": rpc.NewHexNumber(origin), "currentBlock": rpc.NewHexNumber(current), "highestBlock": rpc.NewHexNumber(height), }, nil } return false, nil }
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(blockNr rpc.BlockNumber) *rpc.HexNumber { if blockNr == rpc.PendingBlockNumber { return rpc.NewHexNumber(0) } if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { return rpc.NewHexNumber(len(block.Transactions())) } return nil }
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 } contractCreation := (req.To == (common.Address{})) 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(defaultGasPrice) } if contractCreation { tx.tx = types.NewContractCreation(tx.Nonce.Uint64(), tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data) } else { if tx.To == nil { return fmt.Errorf("need to address") } tx.tx = types.NewTransaction(tx.Nonce.Uint64(), *tx.To, tx.Value.BigInt(), tx.GasLimit.BigInt(), tx.GasPrice.BigInt(), data) } return nil }
func newTx(t *types.Transaction) *Tx { from, _ := t.From() 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(), } }
// newRPCPendingTransaction returns a pending transaction that will serialize to the RPC representation func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { from, _ := tx.From() return &RPCTransaction{ From: from, Gas: rpc.NewHexNumber(tx.Gas()), GasPrice: rpc.NewHexNumber(tx.GasPrice()), Hash: tx.Hash(), Input: fmt.Sprintf("0x%x", tx.Data()), Nonce: rpc.NewHexNumber(tx.Nonce()), To: tx.To(), Value: rpc.NewHexNumber(tx.Value()), } }
// GetTransactionReceipt returns the transaction receipt for the given transaction hash. func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (map[string]interface{}, error) { receipt := core.GetReceipt(s.chainDb, txHash) if receipt == nil { glog.V(logger.Debug).Infof("receipt not found for transaction %s", txHash.Hex()) return nil, nil } tx, _, err := getTransaction(s.chainDb, s.txPool, txHash) if err != nil { glog.V(logger.Debug).Infof("%v\n", err) return nil, nil } txBlock, blockIndex, index, err := getTransactionBlockData(s.chainDb, txHash) if err != nil { glog.V(logger.Debug).Infof("%v\n", err) return nil, nil } from, err := tx.From() if err != nil { glog.V(logger.Debug).Infof("%v\n", err) return nil, nil } fields := map[string]interface{}{ "blockHash": txBlock, "blockNumber": rpc.NewHexNumber(blockIndex), "transactionHash": txHash, "transactionIndex": rpc.NewHexNumber(index), "from": from, "to": tx.To(), "gasUsed": rpc.NewHexNumber(receipt.GasUsed), "cumulativeGasUsed": rpc.NewHexNumber(receipt.CumulativeGasUsed), "contractAddress": nil, "logs": receipt.Logs, } if receipt.Logs == nil { fields["logs"] = []vm.Logs{} } // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation if bytes.Compare(receipt.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 { fields["contractAddress"] = receipt.ContractAddress } return fields, nil }
// NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages. func (s *PublicWhisperAPI) NewFilter(args *NewFilterArgs) (*rpc.HexNumber, error) { if s.w == nil { return nil, whisperOffLineErr } var id int filter := Filter{ To: crypto.ToECDSAPub(common.FromHex(args.To)), From: crypto.ToECDSAPub(common.FromHex(args.From)), Topics: NewFilterTopics(args.Topics...), Fn: func(message *Message) { wmsg := NewWhisperMessage(message) s.messagesMu.RLock() // Only read lock to the filter pool defer s.messagesMu.RUnlock() if s.messages[id] != nil { s.messages[id].insert(wmsg) } }, } id = s.w.Watch(filter) s.messagesMu.Lock() s.messages[id] = newWhisperFilter(id, s.w) s.messagesMu.Unlock() return rpc.NewHexNumber(id), nil }
// SendTransaction will create a transaction for the given transaction argument, sign it and submit it to the // transaction pool. func (s *PublicTransactionPoolAPI) SendTransaction(args SendTxArgs) (common.Hash, error) { if args.Gas == nil { args.Gas = rpc.NewHexNumber(defaultGas) } if args.GasPrice == nil { args.GasPrice = rpc.NewHexNumber(defaultGasPrice) } if args.Value == nil { args.Value = rpc.NewHexNumber(0) } s.txMu.Lock() defer s.txMu.Unlock() if args.Nonce == nil { args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From)) } var tx *types.Transaction contractCreation := (args.To == common.Address{}) if contractCreation { 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)) } signedTx, err := s.sign(args.From, tx) if err != nil { return common.Hash{}, err } s.txPool.SetLocal(signedTx) if err := s.txPool.Add(signedTx); err != nil { return common.Hash{}, nil } if contractCreation { addr := crypto.CreateAddress(args.From, args.Nonce.Uint64()) glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex()) } else { glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex()) } return signedTx.Hash(), nil }
// GetTransactionCount returns the number of transactions the given address has sent for the given block number func (s *PublicTransactionPoolAPI) GetTransactionCount(address common.Address, blockNr rpc.BlockNumber) (*rpc.HexNumber, error) { block := blockByNumber(s.miner, s.bc, blockNr) if block == nil { return nil, nil } state, err := state.New(block.Root(), s.chainDb) if err != nil { return nil, err } return rpc.NewHexNumber(state.GetNonce(address)), nil }
// newRPCTransaction returns a transaction that will serialize to the RPC representation. func newRPCTransactionFromBlockIndex(b *types.Block, txIndex int) (*RPCTransaction, error) { if txIndex >= 0 && txIndex < len(b.Transactions()) { tx := b.Transactions()[txIndex] from, err := tx.From() if err != nil { return nil, err } return &RPCTransaction{ BlockHash: b.Hash(), BlockNumber: rpc.NewHexNumber(b.Number()), From: from, Gas: rpc.NewHexNumber(tx.Gas()), GasPrice: rpc.NewHexNumber(tx.GasPrice()), Hash: tx.Hash(), Input: fmt.Sprintf("0x%x", tx.Data()), Nonce: rpc.NewHexNumber(tx.Nonce()), To: tx.To(), TransactionIndex: rpc.NewHexNumber(txIndex), Value: rpc.NewHexNumber(tx.Value()), }, nil } return nil, nil }
// SignTransaction will sign the given transaction with the from account. // The node needs to have the private key of the account corresponding with // the given from address and it needs to be unlocked. func (s *PublicTransactionPoolAPI) SignTransaction(args *SignTransactionArgs) (*SignTransactionResult, error) { if args.Gas == nil { args.Gas = rpc.NewHexNumber(defaultGas) } if args.GasPrice == nil { args.GasPrice = rpc.NewHexNumber(defaultGasPrice) } if args.Value == nil { args.Value = rpc.NewHexNumber(0) } s.txMu.Lock() defer s.txMu.Unlock() if args.Nonce == nil { args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From)) } var tx *types.Transaction contractCreation := (args.To == common.Address{}) if contractCreation { 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)) } signedTx, err := s.sign(args.From, tx) if err != nil { return nil, err } data, err := rlp.EncodeToBytes(signedTx) if err != nil { return nil, err } return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil }
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain // transaction hashes. func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { fields := map[string]interface{}{ "number": rpc.NewHexNumber(b.Number()), "hash": b.Hash(), "parentHash": b.ParentHash(), "nonce": b.Header().Nonce, "sha3Uncles": b.UncleHash(), "logsBloom": b.Bloom(), "stateRoot": b.Root(), "miner": b.Coinbase(), "difficulty": rpc.NewHexNumber(b.Difficulty()), "totalDifficulty": rpc.NewHexNumber(s.bc.GetTd(b.Hash())), "extraData": fmt.Sprintf("0x%x", b.Extra()), "size": rpc.NewHexNumber(b.Size().Int64()), "gasLimit": rpc.NewHexNumber(b.GasLimit()), "gasUsed": rpc.NewHexNumber(b.GasUsed()), "timestamp": rpc.NewHexNumber(b.Time()), "transactionsRoot": b.TxHash(), "receiptRoot": b.ReceiptHash(), } if inclTx { formatTx := func(tx *types.Transaction) (interface{}, error) { return tx.Hash(), nil } if fullTx { formatTx = func(tx *types.Transaction) (interface{}, error) { return newRPCTransaction(b, tx.Hash()) } } txs := b.Transactions() transactions := make([]interface{}, len(txs)) var err error for i, tx := range b.Transactions() { if transactions[i], err = formatTx(tx); err != nil { return nil, err } } fields["transactions"] = transactions } uncles := b.Uncles() uncleHashes := make([]common.Hash, len(uncles)) for i, uncle := range uncles { uncleHashes[i] = uncle.Hash() } fields["uncles"] = uncleHashes return fields, nil }
// GetBlockTime retrieves the block of the given number from the canonical chain. func (api *API) GetBlockTime(num uint64) (time.Time, error) { res, err := api.request("eth_getBlockByNumber", []interface{}{rpc.NewHexNumber(num), true}) if err != nil { return time.Time{}, err } result := make(map[string]json.RawMessage) if err := json.Unmarshal(res, &result); err != nil { return time.Time{}, err } var hex string if err := json.Unmarshal(result["timestamp"], &hex); err != nil { return time.Time{}, err } return time.Unix(new(big.Int).SetBytes(common.FromHex(hex)).Int64(), 0), nil }
// Resend accepts an existing transaction and a new gas price and limit. It will remove the given transaction from the // pool and reinsert it with the new gas price and limit. func (s *PublicTransactionPoolAPI) Resend(tx *Tx, gasPrice, gasLimit *rpc.HexNumber) (common.Hash, error) { pending := s.txPool.GetTransactions() for _, p := range pending { if pFrom, err := p.From(); err == nil && pFrom == tx.From && p.SigHash() == tx.tx.SigHash() { if gasPrice == nil { gasPrice = rpc.NewHexNumber(tx.tx.GasPrice()) } if gasLimit == nil { gasLimit = rpc.NewHexNumber(tx.tx.Gas()) } var newTx *types.Transaction contractCreation := (*tx.tx.To() == common.Address{}) if contractCreation { newTx = types.NewContractCreation(tx.tx.Nonce(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data()) } else { newTx = types.NewTransaction(tx.tx.Nonce(), *tx.tx.To(), tx.tx.Value(), gasPrice.BigInt(), gasLimit.BigInt(), tx.tx.Data()) } signedTx, err := s.sign(tx.From, newTx) if err != nil { return common.Hash{}, err } s.txPool.RemoveTx(tx.Hash) if err = s.txPool.Add(signedTx); err != nil { return common.Hash{}, err } return signedTx.Hash(), nil } } return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash) }
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction. func (s *PublicBlockChainAPI) EstimateGas(args CallArgs) (*rpc.HexNumber, error) { _, gas, err := s.doCall(args, rpc.LatestBlockNumber) return rpc.NewHexNumber(gas), err }
// Version returns the Whisper version this node offers. func (s *PublicWhisperAPI) Version() (*rpc.HexNumber, error) { if s.w == nil { return rpc.NewHexNumber(0), whisperOffLineErr } return rpc.NewHexNumber(s.w.Version()), nil }
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(blockHash common.Hash) *rpc.HexNumber { if block := s.bc.GetBlock(blockHash); block != nil { return rpc.NewHexNumber(len(block.Transactions())) } return nil }
// ProtocolVersion returns the current Ethereum protocol version this node supports func (s *PublicEthereumAPI) ProtocolVersion() *rpc.HexNumber { return rpc.NewHexNumber(s.e.EthVersion()) }
// Hashrate returns the POW hashrate func (s *PublicEthereumAPI) Hashrate() *rpc.HexNumber { return rpc.NewHexNumber(s.e.Miner().HashRate()) }
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(blockHash common.Hash) *rpc.HexNumber { if block := s.bc.GetBlock(blockHash); block != nil { return rpc.NewHexNumber(len(block.Uncles())) } return nil }
// Peercount returns the number of connected peers func (s *PublicNetAPI) PeerCount() *rpc.HexNumber { return rpc.NewHexNumber(s.net.PeerCount()) }