github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/rpc/web3/eth_service.go (about) 1 package web3 2 3 import ( 4 "context" 5 "encoding/hex" 6 "fmt" 7 "math/big" 8 "strconv" 9 10 "github.com/hyperledger/burrow/encoding" 11 "github.com/hyperledger/burrow/encoding/rlp" 12 "github.com/hyperledger/burrow/encoding/web3hex" 13 14 "github.com/hyperledger/burrow/acm/acmstate" 15 "github.com/hyperledger/burrow/acm/balance" 16 "github.com/hyperledger/burrow/acm/validator" 17 bcm "github.com/hyperledger/burrow/bcm" 18 "github.com/hyperledger/burrow/consensus/tendermint" 19 "github.com/hyperledger/burrow/crypto" 20 "github.com/hyperledger/burrow/execution" 21 "github.com/hyperledger/burrow/execution/exec" 22 "github.com/hyperledger/burrow/execution/state" 23 "github.com/hyperledger/burrow/keys" 24 "github.com/hyperledger/burrow/logging" 25 "github.com/hyperledger/burrow/project" 26 "github.com/hyperledger/burrow/txs" 27 "github.com/hyperledger/burrow/txs/payload" 28 tmConfig "github.com/tendermint/tendermint/config" 29 "github.com/tendermint/tendermint/types" 30 ) 31 32 const ( 33 maxGasLimit = 2<<52 - 1 34 hexZero = "0x0" 35 hexZeroNonce = "0x0000000000000000" 36 pending = "null" 37 ) 38 39 // EthService is a web3 provider 40 type EthService struct { 41 accounts acmstate.IterableStatsReader 42 events EventsReader 43 blockchain bcm.BlockchainInfo 44 validators validator.History 45 nodeView *tendermint.NodeView 46 trans *execution.Transactor 47 keyClient keys.KeyClient 48 keyStore *keys.FilesystemKeyStore 49 config *tmConfig.Config 50 chainID *big.Int 51 logger *logging.Logger 52 } 53 54 // NewEthService returns our web3 provider 55 func NewEthService( 56 accounts acmstate.IterableStatsReader, 57 events EventsReader, 58 blockchain bcm.BlockchainInfo, 59 validators validator.History, 60 nodeView *tendermint.NodeView, 61 trans *execution.Transactor, 62 keyStore *keys.FilesystemKeyStore, 63 logger *logging.Logger, 64 ) *EthService { 65 66 keyClient := keys.NewLocalKeyClient(keyStore, logger) 67 68 return &EthService{ 69 accounts: accounts, 70 events: events, 71 blockchain: blockchain, 72 validators: validators, 73 nodeView: nodeView, 74 trans: trans, 75 keyClient: keyClient, 76 keyStore: keyStore, 77 config: tmConfig.DefaultConfig(), 78 // Ethereum expects ChainID to be an integer value 79 chainID: encoding.GetEthChainID(blockchain.ChainID()), 80 logger: logger, 81 } 82 } 83 84 var _ Service = &EthService{} 85 86 type EventsReader interface { 87 TxsAtHeight(height uint64) ([]*exec.TxExecution, error) 88 TxByHash(txHash []byte) (*exec.TxExecution, error) 89 } 90 91 var _ EventsReader = &state.State{} 92 93 // Web3ClientVersion returns the version of burrow 94 func (srv *EthService) Web3ClientVersion() (*Web3ClientVersionResult, error) { 95 return &Web3ClientVersionResult{ 96 ClientVersion: project.FullVersion(), 97 }, nil 98 } 99 100 // Web3Sha3 returns Keccak-256 (not the standardized SHA3-256) of the given data 101 func (srv *EthService) Web3Sha3(req *Web3Sha3Params) (*Web3Sha3Result, error) { 102 d := new(web3hex.Decoder) 103 return &Web3Sha3Result{ 104 HashedData: web3hex.Encoder.Bytes(crypto.Keccak256(d.Bytes(req.Data))), 105 }, d.Err() 106 } 107 108 // NetListening returns true if the peer is running 109 func (srv *EthService) NetListening() (*NetListeningResult, error) { 110 return &NetListeningResult{ 111 IsNetListening: srv.nodeView.NodeInfo().GetListenAddress() != "", 112 }, nil 113 } 114 115 // NetPeerCount returns the number of connected peers 116 func (srv *EthService) NetPeerCount() (*NetPeerCountResult, error) { 117 s := web3hex.Encoder.Uint64(uint64(srv.nodeView.Peers().Size())) 118 return &NetPeerCountResult{ 119 s, 120 }, nil 121 } 122 123 // NetVersion returns the hex encoding of the network id, 124 // this is typically a small int (where 1 == Ethereum mainnet) 125 func (srv *EthService) NetVersion() (*NetVersionResult, error) { 126 return &NetVersionResult{ 127 ChainID: web3hex.Encoder.BigInt(srv.chainID), 128 }, nil 129 } 130 131 // EthProtocolVersion returns the version of tendermint 132 func (srv *EthService) EthProtocolVersion() (*EthProtocolVersionResult, error) { 133 return &EthProtocolVersionResult{ 134 ProtocolVersion: srv.nodeView.NodeInfo().Version, 135 }, nil 136 } 137 138 // EthChainId returns the chainID 139 func (srv *EthService) EthChainId() (*EthChainIdResult, error) { 140 return &EthChainIdResult{ 141 ChainId: web3hex.Encoder.BigInt(srv.chainID), 142 }, nil 143 } 144 145 // EthBlockNumber returns the latest height 146 func (srv *EthService) EthBlockNumber() (*EthBlockNumberResult, error) { 147 return &EthBlockNumberResult{ 148 BlockNumber: web3hex.Encoder.Uint64(srv.blockchain.LastBlockHeight()), 149 }, nil 150 } 151 152 // EthCall executes a new message call immediately without creating a transaction 153 func (srv *EthService) EthCall(req *EthCallParams) (*EthCallResult, error) { 154 d := new(web3hex.Decoder) 155 156 from := d.Address(req.Transaction.From) 157 to := d.Address(req.Transaction.To) 158 data := d.Bytes(req.Transaction.Data) 159 160 if d.Err() != nil { 161 return nil, d.Err() 162 } 163 txe, err := execution.CallSim(srv.accounts, srv.blockchain, from, to, data, srv.logger) 164 if err != nil { 165 return nil, err 166 } else if txe.Exception != nil { 167 return nil, txe.Exception.AsError() 168 } 169 170 var result string 171 if r := txe.GetResult(); r != nil { 172 result = web3hex.Encoder.Bytes(r.GetReturn()) 173 } 174 175 return &EthCallResult{ 176 ReturnValue: result, 177 }, nil 178 } 179 180 // EthGetBalance returns an accounts balance, or an error if it does not exist 181 func (srv *EthService) EthGetBalance(req *EthGetBalanceParams) (*EthGetBalanceResult, error) { 182 d := new(web3hex.Decoder) 183 addr := d.Address(req.Address) 184 if d.Err() != nil { 185 return nil, d.Err() 186 } 187 188 // TODO: read account state at height 189 acc, err := srv.accounts.GetAccount(addr) 190 if err != nil { 191 return nil, err 192 } else if acc == nil { 193 return nil, fmt.Errorf("account not found at address %s", req.Address) 194 } 195 196 return &EthGetBalanceResult{ 197 GetBalanceResult: web3hex.Encoder.Bytes(balance.NativeToWei(acc.Balance).Bytes()), 198 }, nil 199 } 200 201 // EthGetBlockByHash iterates through all headers to find a matching block height for a given hash 202 func (srv *EthService) EthGetBlockByHash(req *EthGetBlockByHashParams) (*EthGetBlockByHashResult, error) { 203 height, err := srv.getBlockHeightByHash(req.BlockHash) 204 if err != nil { 205 return nil, err 206 } 207 208 block, err := srv.getBlockInfoAtHeight(height, req.IsTransactionsIncluded) 209 if err != nil { 210 return nil, err 211 } 212 213 return &EthGetBlockByHashResult{ 214 GetBlockByHashResult: block, 215 }, nil 216 } 217 218 // EthGetBlockByNumber returns block info at the given height 219 func (srv *EthService) EthGetBlockByNumber(req *EthGetBlockByNumberParams) (*EthGetBlockByNumberResult, error) { 220 height, err := srv.getHeightByWordOrNumber(req.BlockNumber) 221 if err != nil { 222 return nil, err 223 } 224 225 block, err := srv.getBlockInfoAtHeight(height, req.IsTransactionsIncluded) 226 if err != nil { 227 return nil, err 228 } 229 230 return &EthGetBlockByNumberResult{ 231 GetBlockByNumberResult: block, 232 }, nil 233 } 234 235 // EthGetBlockTransactionCountByHash returns the number of transactions in a block matching a given hash 236 func (srv *EthService) EthGetBlockTransactionCountByHash(req *EthGetBlockTransactionCountByHashParams) (*EthGetBlockTransactionCountByHashResult, error) { 237 height, err := srv.getBlockHeightByHash(req.BlockHash) 238 if err != nil { 239 return nil, err 240 } 241 242 numTxs, err := srv.blockchain.GetNumTxs(height) 243 if err != nil { 244 return nil, err 245 } 246 247 return &EthGetBlockTransactionCountByHashResult{ 248 BlockTransactionCountByHash: web3hex.Encoder.Uint64(uint64(numTxs)), 249 }, nil 250 } 251 252 // EthGetBlockTransactionCountByNumber returns the number of transactions in a block matching a given height 253 func (srv *EthService) EthGetBlockTransactionCountByNumber(req *EthGetBlockTransactionCountByNumberParams) (*EthGetBlockTransactionCountByNumberResult, error) { 254 height, err := srv.getHeightByWordOrNumber(req.BlockNumber) 255 if err != nil { 256 return nil, err 257 } 258 259 numTxs, err := srv.blockchain.GetNumTxs(height) 260 if err != nil { 261 return nil, err 262 } 263 264 return &EthGetBlockTransactionCountByNumberResult{ 265 BlockTransactionCountByHash: web3hex.Encoder.Uint64(uint64(numTxs)), 266 }, nil 267 } 268 269 // EthGetCode returns the EVM bytecode at an address 270 func (srv *EthService) EthGetCode(req *EthGetCodeParams) (*EthGetCodeResult, error) { 271 d := new(web3hex.Decoder) 272 addr := d.Address(req.Address) 273 if d.Err() != nil { 274 return nil, d.Err() 275 } 276 277 acc, err := srv.accounts.GetAccount(addr) 278 if err != nil { 279 return nil, err 280 } else if acc == nil { 281 return nil, fmt.Errorf("account not found at address %s", req.Address) 282 } 283 284 return &EthGetCodeResult{ 285 Bytes: web3hex.Encoder.Bytes(acc.EVMCode), 286 }, nil 287 } 288 289 func (srv *EthService) EthGetStorageAt(req *EthGetStorageAtParams) (*EthGetStorageAtResult, error) { 290 // TODO 291 return nil, ErrNotFound 292 } 293 294 func (srv *EthService) EthGetTransactionByBlockHashAndIndex(req *EthGetTransactionByBlockHashAndIndexParams) (*EthGetTransactionByBlockHashAndIndexResult, error) { 295 height, err := srv.getBlockHeightByHash(req.BlockHash) 296 if err != nil { 297 return nil, err 298 } 299 300 head, err := srv.blockchain.GetBlockHeader(height) 301 if err != nil { 302 return nil, err 303 } 304 305 txes, err := srv.events.TxsAtHeight(height) 306 if err != nil { 307 return nil, err 308 } 309 310 d := new(web3hex.Decoder) 311 312 index := d.Uint64(req.Index) 313 314 if d.Err() != nil { 315 return nil, d.Err() 316 } 317 318 for _, txe := range txes { 319 if txe.GetIndex() == index { 320 hash, tx, err := getHashAndCallTxFromExecution(txe) 321 if err != nil { 322 return nil, err 323 } 324 return &EthGetTransactionByBlockHashAndIndexResult{ 325 TransactionResult: getTransaction(head, hash, tx), 326 }, nil 327 } 328 } 329 330 return nil, fmt.Errorf("tx not found at hash %s, index %d", req.BlockHash, index) 331 } 332 333 func (srv *EthService) EthGetTransactionByBlockNumberAndIndex(req *EthGetTransactionByBlockNumberAndIndexParams) (*EthGetTransactionByBlockNumberAndIndexResult, error) { 334 height, err := srv.getHeightByWordOrNumber(req.BlockNumber) 335 if err != nil { 336 return nil, err 337 } 338 339 head, err := srv.blockchain.GetBlockHeader(height) 340 if err != nil { 341 return nil, err 342 } 343 344 txes, err := srv.events.TxsAtHeight(height) 345 if err != nil { 346 return nil, err 347 } 348 d := new(web3hex.Decoder) 349 index := d.Uint64(req.Index) 350 if d.Err() != nil { 351 return nil, d.Err() 352 } 353 354 for _, txe := range txes { 355 if txe.GetIndex() == index { 356 hash, tx, err := getHashAndCallTxFromExecution(txe) 357 if err != nil { 358 return nil, err 359 } 360 return &EthGetTransactionByBlockNumberAndIndexResult{ 361 TransactionResult: getTransaction(head, hash, tx), 362 }, nil 363 } 364 } 365 366 return nil, fmt.Errorf("tx not found at height %d, index %d", height, index) 367 } 368 369 // EthGetTransactionByHash finds a tx by the given hash 370 func (srv *EthService) EthGetTransactionByHash(req *EthGetTransactionByHashParams) (*EthGetTransactionByHashResult, error) { 371 d := new(web3hex.Decoder) 372 373 hash := d.Bytes(req.TransactionHash) 374 if d.Err() != nil { 375 return nil, d.Err() 376 } 377 txe, err := srv.events.TxByHash(hash) 378 if err != nil { 379 return nil, err 380 } 381 382 head, err := srv.blockchain.GetBlockHeader(txe.Height) 383 if err != nil { 384 return nil, err 385 } 386 387 hash, tx, err := getHashAndCallTxFromExecution(txe) 388 if err != nil { 389 return nil, err 390 } 391 392 return &EthGetTransactionByHashResult{ 393 Transaction: getTransaction(head, hash, tx), 394 }, nil 395 } 396 397 // EthGetTransactionCount returns the number of transactions sent from an address 398 func (srv *EthService) EthGetTransactionCount(req *EthGetTransactionCountParams) (*EthGetTransactionCountResult, error) { 399 d := new(web3hex.Decoder) 400 addr := d.Address(req.Address) 401 if d.Err() != nil { 402 return nil, d.Err() 403 } 404 405 // TODO: get tx count at height 406 acc, err := srv.accounts.GetAccount(addr) 407 if err != nil { 408 return nil, err 409 } 410 411 // TODO: sequence may not always be accurate, is there a better way? 412 return &EthGetTransactionCountResult{ 413 NonceOrNull: web3hex.Encoder.Uint64(acc.GetSequence()), 414 }, nil 415 } 416 417 func getHashAndCallTxFromEnvelope(env *txs.Envelope) ([]byte, *payload.CallTx, error) { 418 if env.Tx == nil { 419 return nil, nil, fmt.Errorf("tx not found for %s", env.String()) 420 } else if tx, ok := env.Tx.Payload.(*payload.CallTx); ok { 421 return env.Tx.Hash().Bytes(), tx, nil 422 } 423 return nil, nil, fmt.Errorf("tx not valid") 424 } 425 426 func getHashAndCallTxFromExecution(txe *exec.TxExecution) ([]byte, *payload.CallTx, error) { 427 if txe.Envelope == nil { 428 return nil, nil, fmt.Errorf("envelope not found for %s", txe.GetTxHash().String()) 429 } 430 return getHashAndCallTxFromEnvelope(txe.Envelope) 431 } 432 433 // EthGetTransactionReceipt returns the receipt of a previously committed tx 434 func (srv *EthService) EthGetTransactionReceipt(req *EthGetTransactionReceiptParams) (*EthGetTransactionReceiptResult, error) { 435 d := new(web3hex.Decoder) 436 437 data := d.Bytes(req.TransactionHash) 438 if d.Err() != nil { 439 return nil, d.Err() 440 } 441 442 txe, err := srv.events.TxByHash(data) 443 if err != nil { 444 return nil, err 445 } else if txe == nil { 446 return nil, fmt.Errorf("tx with hash %s does not exist", req.TransactionHash) 447 } 448 449 hash, tx, err := getHashAndCallTxFromExecution(txe) 450 if err != nil { 451 return nil, err 452 } 453 454 block, err := srv.blockchain.GetBlockHeader(txe.Height) 455 if err != nil { 456 return nil, err 457 } 458 459 status := web3hex.Encoder.Uint64(1) 460 if err := txe.Exception.AsError(); err != nil { 461 status = web3hex.Encoder.Uint64(0) 462 } 463 464 result := &EthGetTransactionReceiptResult{ 465 Receipt: Receipt{ 466 Status: status, 467 TransactionIndex: web3hex.Encoder.Uint64(txe.GetIndex()), 468 BlockNumber: web3hex.Encoder.Uint64(uint64(block.Height)), 469 BlockHash: web3hex.Encoder.Bytes(block.Hash()), 470 From: web3hex.Encoder.Bytes(tx.GetInput().Address.Bytes()), 471 GasUsed: web3hex.Encoder.Uint64(txe.Result.GetGasUsed()), 472 TransactionHash: web3hex.Encoder.Bytes(hash), 473 CumulativeGasUsed: hexZero, 474 LogsBloom: hexZero, 475 Logs: []Logs{}, 476 }, 477 } 478 479 if txe.Receipt != nil { 480 result.Receipt.ContractAddress = web3hex.Encoder.Bytes(txe.Receipt.ContractAddress.Bytes()) 481 result.Receipt.To = pending 482 } else if tx.Address != nil { 483 result.Receipt.To = web3hex.Encoder.Bytes(tx.Address.Bytes()) 484 } 485 486 return result, nil 487 } 488 489 // EthHashrate returns the configured tendermint commit timeout 490 func (srv *EthService) EthHashrate() (*EthHashrateResult, error) { 491 return &EthHashrateResult{ 492 HashesPerSecond: srv.config.Consensus.TimeoutCommit.String(), 493 }, nil 494 } 495 496 // EthMining returns true if client is a validator 497 func (srv *EthService) EthMining() (*EthMiningResult, error) { 498 var isVal bool 499 addr := srv.nodeView.ValidatorAddress() 500 val := srv.validators.Validators(1) 501 err := val.IterateValidators(func(id crypto.Addressable, _ *big.Int) error { 502 if addr == id.GetAddress() { 503 isVal = true 504 } 505 return nil 506 }) 507 if err != nil { 508 return nil, err 509 } 510 return &EthMiningResult{ 511 Mining: isVal, 512 }, nil 513 } 514 515 // EthPendingTransactions returns all txs in the mempool 516 func (srv *EthService) EthPendingTransactions() (*EthPendingTransactionsResult, error) { 517 pending := make([]PendingTransactions, 0) 518 envelopes, err := srv.nodeView.MempoolTransactions(-1) 519 if err != nil { 520 return nil, err 521 } 522 523 for _, env := range envelopes { 524 hash, tx, err := getHashAndCallTxFromEnvelope(env) 525 if err != nil { 526 continue 527 } 528 pending = append(pending, PendingTransactions{ 529 Transaction: getTransaction(nil, hash, tx), 530 }) 531 } 532 533 return &EthPendingTransactionsResult{ 534 PendingTransactions: pending, 535 }, nil 536 } 537 538 func (srv *EthService) EthEstimateGas(req *EthEstimateGasParams) (*EthEstimateGasResult, error) { 539 // TODO 540 return &EthEstimateGasResult{ 541 GasUsed: hexZero, 542 }, nil 543 } 544 545 func (srv *EthService) EthGasPrice() (*EthGasPriceResult, error) { 546 // TODO 547 return &EthGasPriceResult{ 548 GasPrice: hexZero, 549 }, nil 550 } 551 552 func (srv *EthService) EthGetRawTransactionByHash(req *EthGetRawTransactionByHashParams) (*EthGetRawTransactionByHashResult, error) { 553 // TODO 554 return nil, ErrNotFound 555 } 556 557 func (srv *EthService) EthGetRawTransactionByBlockHashAndIndex(req *EthGetRawTransactionByBlockHashAndIndexParams) (*EthGetRawTransactionByBlockHashAndIndexResult, error) { 558 // TODO 559 return nil, ErrNotFound 560 } 561 562 func (srv *EthService) EthGetRawTransactionByBlockNumberAndIndex(req *EthGetRawTransactionByBlockNumberAndIndexParams) (*EthGetRawTransactionByBlockNumberAndIndexResult, error) { 563 // TODO 564 return nil, ErrNotFound 565 } 566 567 func (srv *EthService) EthSendRawTransaction(req *EthSendRawTransactionParams) (*EthSendRawTransactionResult, error) { 568 d := new(web3hex.Decoder) 569 570 data := d.Bytes(req.SignedTransactionData) 571 572 if d.Err() != nil { 573 return nil, d.Err() 574 } 575 576 rawTx := txs.NewEthRawTx(srv.chainID) 577 err := rlp.Decode(data, rawTx) 578 if err != nil { 579 return nil, err 580 } 581 582 publicKey, signature, err := rawTx.RecoverPublicKey() 583 if err != nil { 584 return nil, err 585 } 586 587 from := publicKey.GetAddress() 588 589 to, err := crypto.AddressFromBytes(rawTx.To) 590 if err != nil { 591 return nil, err 592 } 593 594 amount := balance.WeiToNative(rawTx.Amount).Uint64() 595 596 txEnv := &txs.Envelope{ 597 Signatories: []txs.Signatory{ 598 { 599 Address: &from, 600 PublicKey: publicKey, 601 Signature: signature, 602 }, 603 }, 604 Encoding: txs.Envelope_RLP, 605 Tx: &txs.Tx{ 606 ChainID: srv.blockchain.ChainID(), 607 Payload: &payload.CallTx{ 608 Input: &payload.TxInput{ 609 Address: from, 610 Amount: amount, 611 // first tx sequence should be 1, 612 // but metamask starts at 0 613 Sequence: rawTx.Sequence + 1, 614 }, 615 Address: &to, 616 GasLimit: rawTx.GasLimit, 617 GasPrice: rawTx.GasPrice, 618 Data: rawTx.Data, 619 }, 620 }, 621 } 622 623 ctx := context.Background() 624 txe, err := srv.trans.BroadcastTxSync(ctx, txEnv) 625 if err != nil { 626 return nil, err 627 } else if txe.Exception != nil { 628 return nil, txe.Exception.AsError() 629 } 630 631 return &EthSendRawTransactionResult{ 632 TransactionHash: web3hex.Encoder.Bytes(txe.GetTxHash().Bytes()), 633 }, nil 634 } 635 636 // EthSyncing returns this nodes syncing status (i.e. whether it has caught up) 637 func (srv *EthService) EthSyncing() (*EthSyncingResult, error) { 638 // TODO: remaining sync fields 639 return &EthSyncingResult{ 640 Syncing: SyncStatus{ 641 CurrentBlock: web3hex.Encoder.Uint64(srv.blockchain.LastBlockHeight()), 642 }, 643 }, nil 644 } 645 646 func (srv *EthService) getBlockHeightByHash(hash string) (uint64, error) { 647 for i := uint64(1); i < srv.blockchain.LastBlockHeight(); i++ { 648 head, err := srv.blockchain.GetBlockHeader(i) 649 if err != nil { 650 return 0, err 651 } else if hexKeccak(head.Hash().Bytes()) == hash { 652 return i, nil 653 } 654 } 655 return 0, ErrNotFound 656 } 657 658 func (srv *EthService) getBlockHeaderAtHeight(height uint64) (*types.Header, error) { 659 return srv.blockchain.GetBlockHeader(height) 660 } 661 662 func hexKeccak(data []byte) string { 663 return web3hex.Encoder.Bytes(crypto.Keccak256(data)) 664 } 665 666 func hexKeccakAddress(data []byte) string { 667 addr := crypto.Keccak256(data) 668 return web3hex.Encoder.Bytes(addr[len(addr)-20:]) 669 } 670 671 func (srv *EthService) getBlockInfoAtHeight(height uint64, includeTxs bool) (Block, error) { 672 doc := srv.blockchain.GenesisDoc() 673 if height == 0 { 674 // genesis 675 return Block{ 676 Transactions: make([]Transactions, 0), 677 Uncles: make([]string, 0), 678 Nonce: hexZeroNonce, 679 Hash: hexKeccak(doc.AppHash.Bytes()), 680 ParentHash: hexKeccak(doc.AppHash.Bytes()), 681 ReceiptsRoot: hexKeccak(doc.AppHash.Bytes()), 682 StateRoot: hexKeccak(doc.AppHash.Bytes()), 683 Miner: web3hex.Encoder.Bytes(doc.Validators[0].Address.Bytes()), 684 Timestamp: web3hex.Encoder.Uint64(uint64(doc.GenesisTime.Unix())), 685 Number: hexZero, 686 Size: hexZero, 687 ExtraData: hexZero, 688 Difficulty: hexZero, 689 TotalDifficulty: hexZero, 690 GasLimit: hexZero, 691 GasUsed: hexZero, 692 }, nil 693 } 694 block, err := srv.getBlockHeaderAtHeight(height) 695 if err != nil { 696 return Block{}, err 697 } else if block == nil { 698 return Block{}, fmt.Errorf("block at height %d does not exist", height) 699 } 700 701 numTxs, err := srv.blockchain.GetNumTxs(height) 702 if err != nil { 703 return Block{}, err 704 } 705 706 transactions := make([]Transactions, 0) 707 if includeTxs { 708 txes, err := srv.events.TxsAtHeight(height) 709 if err != nil { 710 return Block{}, err 711 } 712 for _, txe := range txes { 713 hash, tx, err := getHashAndCallTxFromExecution(txe) 714 if err != nil { 715 continue 716 } 717 transactions = append(transactions, Transactions{ 718 getTransaction(block, hash, tx), 719 }) 720 } 721 } 722 723 return Block{ 724 Hash: hexKeccak(block.Hash().Bytes()), 725 ParentHash: hexKeccak(block.Hash().Bytes()), 726 TransactionsRoot: hexKeccak(block.Hash().Bytes()), 727 StateRoot: hexKeccak(block.Hash().Bytes()), 728 ReceiptsRoot: hexKeccak(block.Hash().Bytes()), 729 Nonce: hexZeroNonce, 730 Size: web3hex.Encoder.Uint64(uint64(numTxs)), 731 Number: web3hex.Encoder.Uint64(uint64(block.Height)), 732 Miner: web3hex.Encoder.Bytes(block.ProposerAddress.Bytes()), 733 Sha3Uncles: hexZero, 734 LogsBloom: hexZero, 735 ExtraData: hexZero, 736 Difficulty: hexZero, 737 TotalDifficulty: hexZero, 738 GasUsed: hexZero, 739 GasLimit: web3hex.Encoder.Uint64(maxGasLimit), 740 Timestamp: web3hex.Encoder.Uint64(uint64(block.Time.Unix())), 741 Transactions: transactions, 742 Uncles: []string{}, 743 }, nil 744 } 745 746 func getTransaction(block *types.Header, hash []byte, tx *payload.CallTx) Transaction { 747 // TODO: sensible defaults for non-call 748 transaction := Transaction{ 749 V: hexZero, 750 R: hexZero, 751 S: hexZero, 752 From: web3hex.Encoder.Bytes(tx.Input.Address.Bytes()), 753 Value: web3hex.Encoder.Uint64(tx.Input.Amount), 754 Nonce: web3hex.Encoder.Uint64(tx.Input.Sequence), 755 Gas: web3hex.Encoder.Uint64(tx.GasLimit), 756 GasPrice: web3hex.Encoder.Uint64(tx.GasPrice), 757 Data: web3hex.Encoder.Bytes(tx.Data), 758 } 759 760 if block != nil { 761 // may be pending 762 transaction.BlockHash = hexKeccak(block.Hash().Bytes()) 763 transaction.Hash = web3hex.Encoder.Bytes(hash) 764 transaction.BlockNumber = web3hex.Encoder.Uint64(uint64(block.Height)) 765 transaction.TransactionIndex = hexZero 766 } 767 768 if tx.Address != nil { 769 transaction.To = web3hex.Encoder.Bytes(tx.Address.Bytes()) 770 } else { 771 transaction.To = pending 772 } 773 774 return transaction 775 } 776 777 func (srv *EthService) getHeightByWord(height string) (uint64, bool) { 778 switch height { 779 case "earliest": 780 return 0, true 781 case "latest", "pending": 782 return srv.blockchain.LastBlockHeight(), true 783 // TODO: pending state/transactions 784 default: 785 return 0, false 786 } 787 } 788 789 func getHeightByNumber(height string) (uint64, error) { 790 d := new(web3hex.Decoder) 791 return d.Uint64(height), d.Err() 792 } 793 794 func (srv *EthService) getHeightByWordOrNumber(i string) (uint64, error) { 795 var err error 796 height, ok := srv.getHeightByWord(i) 797 if !ok { 798 height, err = getHeightByNumber(i) 799 if err != nil { 800 return 0, err 801 } 802 } 803 return height, nil 804 } 805 806 // EthSendTransaction constructs, signs and broadcasts a tx from the local node 807 // Note: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1767.md#rationale 808 func (srv *EthService) EthSendTransaction(req *EthSendTransactionParams) (*EthSendTransactionResult, error) { 809 tx := &payload.CallTx{ 810 Input: new(payload.TxInput), 811 } 812 813 var err error 814 d := new(web3hex.Decoder) 815 if from := req.Transaction.From; from != "" { 816 tx.Input.Address = d.Address(from) 817 if d.Err() != nil { 818 return nil, fmt.Errorf("failed to parse from address: %v", d.Err()) 819 } 820 } else { 821 return nil, fmt.Errorf("no from address specified") 822 } 823 824 if value := req.Transaction.Value; value != "" { 825 tx.Input.Amount, err = strconv.ParseUint(value, 0, 64) 826 if err != nil { 827 return nil, fmt.Errorf("failed to parse amount: %v", err) 828 } 829 } 830 831 if to := req.Transaction.To; to != "" { 832 addr := d.Address(to) 833 if d.Err() != nil { 834 return nil, fmt.Errorf("failed to parse to address: %v", d.Err()) 835 } 836 tx.Address = &addr 837 } 838 839 // gas provided for the transaction execution 840 if gasLimit := req.Transaction.Gas; gasLimit != "" { 841 tx.GasLimit, err = strconv.ParseUint(gasLimit, 0, 64) 842 if err != nil { 843 return nil, fmt.Errorf("failed to parse gasLimit: %v", err) 844 } 845 } 846 847 if gasPrice := req.Transaction.GasPrice; gasPrice != "" { 848 tx.GasPrice, err = strconv.ParseUint(gasPrice, 0, 64) 849 if err != nil { 850 return nil, fmt.Errorf("failed to parse gasPrice: %v", err) 851 } 852 } 853 854 if data := req.Transaction.Data; data != "" { 855 bs := d.Bytes(data) 856 if d.Err() != nil { 857 return nil, fmt.Errorf("failed to parse data: %v", d.Err()) 858 } 859 tx.Data = bs 860 } 861 862 txEnv := txs.Enclose(srv.blockchain.ChainID(), tx) 863 864 ctx := context.Background() 865 txe, err := srv.trans.BroadcastTxSync(ctx, txEnv) 866 if err != nil { 867 return nil, err 868 } else if txe.Exception != nil { 869 return nil, txe.Exception.AsError() 870 } 871 872 return &EthSendTransactionResult{ 873 TransactionHash: web3hex.Encoder.Bytes(txe.GetTxHash().Bytes()), 874 }, nil 875 } 876 877 // EthAccounts returns all accounts signable from the local node 878 func (srv *EthService) EthAccounts() (*EthAccountsResult, error) { 879 addresses, err := srv.keyStore.GetAllAddresses() 880 if err != nil { 881 return nil, err 882 } 883 884 addrs := make([]string, 0, len(addresses)) 885 for _, addr := range addresses { 886 data, err := hex.DecodeString(addr) 887 if err != nil { 888 return nil, fmt.Errorf("could not decode address %s", addr) 889 } 890 key, err := srv.keyStore.GetKey("", data) 891 if err != nil { 892 return nil, fmt.Errorf("could not retrieve key for %s", addr) 893 } else if key.CurveType != crypto.CurveTypeSecp256k1 { 894 // we only want ethereum keys 895 continue 896 } 897 // TODO: only return accounts that exist in current chain 898 addrs = append(addrs, web3hex.Encoder.Bytes(key.Address.Bytes())) 899 } 900 901 return &EthAccountsResult{ 902 Addresses: addrs, 903 }, nil 904 } 905 906 // EthSign: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign 907 func (srv *EthService) EthSign(req *EthSignParams) (*EthSignResult, error) { 908 d := new(web3hex.Decoder) 909 to := d.Address(req.Address) 910 signer, err := keys.AddressableSigner(srv.keyClient, to) 911 if err != nil { 912 return nil, err 913 } 914 915 data := d.Bytes(req.Bytes) 916 if d.Err() != nil { 917 return nil, d.Err() 918 } 919 920 msg := append([]byte{0x19}, []byte("Ethereum Signed Message:\n")...) 921 msg = append(msg, byte(len(data))) 922 msg = append(msg, data...) 923 924 sig, err := signer.Sign(crypto.Keccak256(msg)) 925 if err != nil { 926 return nil, err 927 } 928 929 return &EthSignResult{ 930 Signature: web3hex.Encoder.Bytes(sig.RawBytes()), 931 }, nil 932 } 933 934 // N / A 935 936 func (srv *EthService) EthUninstallFilter(*EthUninstallFilterParams) (*EthUninstallFilterResult, error) { 937 return nil, ErrNotFound 938 } 939 940 func (srv *EthService) EthSubmitHashrate(req *EthSubmitHashrateParams) (*EthSubmitHashrateResult, error) { 941 return nil, ErrNotFound 942 } 943 944 func (srv *EthService) EthSubmitWork(*EthSubmitWorkParams) (*EthSubmitWorkResult, error) { 945 return nil, ErrNotFound 946 } 947 948 func (srv *EthService) EthNewBlockFilter() (*EthNewBlockFilterResult, error) { 949 return nil, ErrNotFound 950 } 951 952 func (srv *EthService) EthNewFilter(req *EthNewFilterParams) (*EthNewFilterResult, error) { 953 return nil, ErrNotFound 954 } 955 956 func (srv *EthService) EthNewPendingTransactionFilter() (*EthNewPendingTransactionFilterResult, error) { 957 return nil, ErrNotFound 958 } 959 960 func (srv *EthService) EthGetUncleByBlockHashAndIndex(req *EthGetUncleByBlockHashAndIndexParams) (*EthGetUncleByBlockHashAndIndexResult, error) { 961 return nil, ErrNotFound 962 } 963 964 func (srv *EthService) EthGetUncleByBlockNumberAndIndex(req *EthGetUncleByBlockNumberAndIndexParams) (*EthGetUncleByBlockNumberAndIndexResult, error) { 965 return nil, ErrNotFound 966 } 967 968 func (srv *EthService) EthGetUncleCountByBlockHash(req *EthGetUncleCountByBlockHashParams) (*EthGetUncleCountByBlockHashResult, error) { 969 return nil, ErrNotFound 970 } 971 972 func (srv *EthService) EthGetUncleCountByBlockNumber(req *EthGetUncleCountByBlockNumberParams) (*EthGetUncleCountByBlockNumberResult, error) { 973 return nil, ErrNotFound 974 } 975 976 func (srv *EthService) EthGetProof(req *EthGetProofParams) (*EthGetProofResult, error) { 977 return nil, ErrNotFound 978 } 979 980 func (srv *EthService) EthGetWork() (*EthGetWorkResult, error) { 981 return nil, ErrNotFound 982 } 983 984 func (srv *EthService) EthGetFilterChanges(req *EthGetFilterChangesParams) (*EthGetFilterChangesResult, error) { 985 return nil, ErrNotFound 986 } 987 988 func (srv *EthService) EthGetFilterLogs(req *EthGetFilterLogsParams) (*EthGetFilterLogsResult, error) { 989 return nil, ErrNotFound 990 } 991 992 func (srv *EthService) EthCoinbase() (*EthCoinbaseResult, error) { 993 return nil, ErrNotFound 994 } 995 996 func (srv *EthService) EthGetLogs(req *EthGetLogsParams) (*EthGetLogsResult, error) { 997 return nil, ErrNotFound 998 }