github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/eth/api.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package eth 18 19 import ( 20 "bytes" 21 "compress/gzip" 22 "errors" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "math/big" 27 "os" 28 "runtime" 29 "strings" 30 "time" 31 32 "github.com/ethereum/go-ethereum/common" 33 "github.com/ethereum/go-ethereum/common/hexutil" 34 "github.com/ethereum/go-ethereum/core" 35 "github.com/ethereum/go-ethereum/core/state" 36 "github.com/ethereum/go-ethereum/core/types" 37 "github.com/ethereum/go-ethereum/core/vm" 38 "github.com/ethereum/go-ethereum/internal/ethapi" 39 "github.com/ethereum/go-ethereum/miner" 40 "github.com/ethereum/go-ethereum/params" 41 "github.com/ethereum/go-ethereum/rlp" 42 "golang.org/x/net/context" 43 ) 44 45 const defaultTraceTimeout = 5 * time.Second 46 47 // PublicEthereumAPI provides an API to access Ethereum full node-related 48 // information. 49 type PublicEthereumAPI struct { 50 e *Ethereum 51 } 52 53 // NewPublicEthereumAPI creates a new Etheruem protocol API for full nodes. 54 func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI { 55 return &PublicEthereumAPI{e} 56 } 57 58 // Etherbase is the address that mining rewards will be send to 59 func (s *PublicEthereumAPI) Etherbase() (common.Address, error) { 60 return s.e.Etherbase() 61 } 62 63 // Coinbase is the address that mining rewards will be send to (alias for Etherbase) 64 func (s *PublicEthereumAPI) Coinbase() (common.Address, error) { 65 return s.Etherbase() 66 } 67 68 // Hashrate returns the POW hashrate 69 func (s *PublicEthereumAPI) Hashrate() hexutil.Uint64 { 70 return hexutil.Uint64(s.e.Miner().HashRate()) 71 } 72 73 // PublicMinerAPI provides an API to control the miner. 74 // It offers only methods that operate on data that pose no security risk when it is publicly accessible. 75 type PublicMinerAPI struct { 76 e *Ethereum 77 agent *miner.RemoteAgent 78 } 79 80 // NewPublicMinerAPI create a new PublicMinerAPI instance. 81 func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI { 82 agent := miner.NewRemoteAgent(e.Pow()) 83 e.Miner().Register(agent) 84 85 return &PublicMinerAPI{e, agent} 86 } 87 88 // Mining returns an indication if this node is currently mining. 89 func (s *PublicMinerAPI) Mining() bool { 90 return s.e.IsMining() 91 } 92 93 // SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was 94 // accepted. Note, this is not an indication if the provided work was valid! 95 func (s *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest common.Hash) bool { 96 return s.agent.SubmitWork(nonce, digest, solution) 97 } 98 99 // GetWork returns a work package for external miner. The work package consists of 3 strings 100 // result[0], 32 bytes hex encoded current block header pow-hash 101 // result[1], 32 bytes hex encoded seed hash used for DAG 102 // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty 103 func (s *PublicMinerAPI) GetWork() ([3]string, error) { 104 if !s.e.IsMining() { 105 if err := s.e.StartMining(0); err != nil { 106 return [3]string{}, err 107 } 108 } 109 work, err := s.agent.GetWork() 110 if err != nil { 111 return work, fmt.Errorf("mining not ready: %v", err) 112 } 113 return work, nil 114 } 115 116 // SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined 117 // hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which 118 // must be unique between nodes. 119 func (s *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool { 120 s.agent.SubmitHashrate(id, uint64(hashrate)) 121 return true 122 } 123 124 // PrivateMinerAPI provides private RPC methods to control the miner. 125 // These methods can be abused by external users and must be considered insecure for use by untrusted users. 126 type PrivateMinerAPI struct { 127 e *Ethereum 128 } 129 130 // NewPrivateMinerAPI create a new RPC service which controls the miner of this node. 131 func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI { 132 return &PrivateMinerAPI{e: e} 133 } 134 135 // Start the miner with the given number of threads. If threads is nil the number of 136 // workers started is equal to the number of logical CPU's that are usable by this process. 137 func (s *PrivateMinerAPI) Start(threads *int) (bool, error) { 138 var err error 139 if threads == nil { 140 err = s.e.StartMining(runtime.NumCPU()) 141 } else { 142 err = s.e.StartMining(*threads) 143 } 144 return err == nil, err 145 } 146 147 // Stop the miner 148 func (s *PrivateMinerAPI) Stop() bool { 149 s.e.StopMining() 150 return true 151 } 152 153 // SetExtra sets the extra data string that is included when this miner mines a block. 154 func (s *PrivateMinerAPI) SetExtra(extra string) (bool, error) { 155 if err := s.e.Miner().SetExtra([]byte(extra)); err != nil { 156 return false, err 157 } 158 return true, nil 159 } 160 161 // SetGasPrice sets the minimum accepted gas price for the miner. 162 func (s *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { 163 s.e.Miner().SetGasPrice((*big.Int)(&gasPrice)) 164 return true 165 } 166 167 // SetEtherbase sets the etherbase of the miner 168 func (s *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool { 169 s.e.SetEtherbase(etherbase) 170 return true 171 } 172 173 // GetHashrate returns the current hashrate of the miner. 174 func (s *PrivateMinerAPI) GetHashrate() uint64 { 175 return uint64(s.e.miner.HashRate()) 176 } 177 178 // PrivateAdminAPI is the collection of Etheruem full node-related APIs 179 // exposed over the private admin endpoint. 180 type PrivateAdminAPI struct { 181 eth *Ethereum 182 } 183 184 // NewPrivateAdminAPI creates a new API definition for the full node private 185 // admin methods of the Ethereum service. 186 func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI { 187 return &PrivateAdminAPI{eth: eth} 188 } 189 190 // ExportChain exports the current blockchain into a local file. 191 func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) { 192 // Make sure we can create the file to export into 193 out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) 194 if err != nil { 195 return false, err 196 } 197 defer out.Close() 198 199 var writer io.Writer = out 200 if strings.HasSuffix(file, ".gz") { 201 writer = gzip.NewWriter(writer) 202 defer writer.(*gzip.Writer).Close() 203 } 204 205 // Export the blockchain 206 if err := api.eth.BlockChain().Export(writer); err != nil { 207 return false, err 208 } 209 return true, nil 210 } 211 212 func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool { 213 for _, b := range bs { 214 if !chain.HasBlock(b.Hash()) { 215 return false 216 } 217 } 218 219 return true 220 } 221 222 // ImportChain imports a blockchain from a local file. 223 func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) { 224 // Make sure the can access the file to import 225 in, err := os.Open(file) 226 if err != nil { 227 return false, err 228 } 229 defer in.Close() 230 231 var reader io.Reader = in 232 if strings.HasSuffix(file, ".gz") { 233 if reader, err = gzip.NewReader(reader); err != nil { 234 return false, err 235 } 236 } 237 238 // Run actual the import in pre-configured batches 239 stream := rlp.NewStream(reader, 0) 240 241 blocks, index := make([]*types.Block, 0, 2500), 0 242 for batch := 0; ; batch++ { 243 // Load a batch of blocks from the input file 244 for len(blocks) < cap(blocks) { 245 block := new(types.Block) 246 if err := stream.Decode(block); err == io.EOF { 247 break 248 } else if err != nil { 249 return false, fmt.Errorf("block %d: failed to parse: %v", index, err) 250 } 251 blocks = append(blocks, block) 252 index++ 253 } 254 if len(blocks) == 0 { 255 break 256 } 257 258 if hasAllBlocks(api.eth.BlockChain(), blocks) { 259 blocks = blocks[:0] 260 continue 261 } 262 // Import the batch and reset the buffer 263 if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil { 264 return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err) 265 } 266 blocks = blocks[:0] 267 } 268 return true, nil 269 } 270 271 // PublicDebugAPI is the collection of Etheruem full node APIs exposed 272 // over the public debugging endpoint. 273 type PublicDebugAPI struct { 274 eth *Ethereum 275 } 276 277 // NewPublicDebugAPI creates a new API definition for the full node- 278 // related public debug methods of the Ethereum service. 279 func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI { 280 return &PublicDebugAPI{eth: eth} 281 } 282 283 // DumpBlock retrieves the entire state of the database at a given block. 284 func (api *PublicDebugAPI) DumpBlock(number uint64) (state.Dump, error) { 285 block := api.eth.BlockChain().GetBlockByNumber(number) 286 if block == nil { 287 return state.Dump{}, fmt.Errorf("block #%d not found", number) 288 } 289 stateDb, err := api.eth.BlockChain().StateAt(block.Root()) 290 if err != nil { 291 return state.Dump{}, err 292 } 293 return stateDb.RawDump(), nil 294 } 295 296 // PrivateDebugAPI is the collection of Etheruem full node APIs exposed over 297 // the private debugging endpoint. 298 type PrivateDebugAPI struct { 299 config *params.ChainConfig 300 eth *Ethereum 301 } 302 303 // NewPrivateDebugAPI creates a new API definition for the full node-related 304 // private debug methods of the Ethereum service. 305 func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI { 306 return &PrivateDebugAPI{config: config, eth: eth} 307 } 308 309 // BlockTraceResult is the returned value when replaying a block to check for 310 // consensus results and full VM trace logs for all included transactions. 311 type BlockTraceResult struct { 312 Validated bool `json:"validated"` 313 StructLogs []ethapi.StructLogRes `json:"structLogs"` 314 Error string `json:"error"` 315 } 316 317 // TraceArgs holds extra parameters to trace functions 318 type TraceArgs struct { 319 *vm.LogConfig 320 Tracer *string 321 Timeout *string 322 } 323 324 // TraceBlock processes the given block's RLP but does not import the block in to 325 // the chain. 326 func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.LogConfig) BlockTraceResult { 327 var block types.Block 328 err := rlp.Decode(bytes.NewReader(blockRlp), &block) 329 if err != nil { 330 return BlockTraceResult{Error: fmt.Sprintf("could not decode block: %v", err)} 331 } 332 333 validated, logs, err := api.traceBlock(&block, config) 334 return BlockTraceResult{ 335 Validated: validated, 336 StructLogs: ethapi.FormatLogs(logs), 337 Error: formatError(err), 338 } 339 } 340 341 // TraceBlockFromFile loads the block's RLP from the given file name and attempts to 342 // process it but does not import the block in to the chain. 343 func (api *PrivateDebugAPI) TraceBlockFromFile(file string, config *vm.LogConfig) BlockTraceResult { 344 blockRlp, err := ioutil.ReadFile(file) 345 if err != nil { 346 return BlockTraceResult{Error: fmt.Sprintf("could not read file: %v", err)} 347 } 348 return api.TraceBlock(blockRlp, config) 349 } 350 351 // TraceBlockByNumber processes the block by canonical block number. 352 func (api *PrivateDebugAPI) TraceBlockByNumber(number uint64, config *vm.LogConfig) BlockTraceResult { 353 // Fetch the block that we aim to reprocess 354 block := api.eth.BlockChain().GetBlockByNumber(number) 355 if block == nil { 356 return BlockTraceResult{Error: fmt.Sprintf("block #%d not found", number)} 357 } 358 359 validated, logs, err := api.traceBlock(block, config) 360 return BlockTraceResult{ 361 Validated: validated, 362 StructLogs: ethapi.FormatLogs(logs), 363 Error: formatError(err), 364 } 365 } 366 367 // TraceBlockByHash processes the block by hash. 368 func (api *PrivateDebugAPI) TraceBlockByHash(hash common.Hash, config *vm.LogConfig) BlockTraceResult { 369 // Fetch the block that we aim to reprocess 370 block := api.eth.BlockChain().GetBlockByHash(hash) 371 if block == nil { 372 return BlockTraceResult{Error: fmt.Sprintf("block #%x not found", hash)} 373 } 374 375 validated, logs, err := api.traceBlock(block, config) 376 return BlockTraceResult{ 377 Validated: validated, 378 StructLogs: ethapi.FormatLogs(logs), 379 Error: formatError(err), 380 } 381 } 382 383 // traceBlock processes the given block but does not save the state. 384 func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConfig) (bool, []vm.StructLog, error) { 385 // Validate and reprocess the block 386 var ( 387 blockchain = api.eth.BlockChain() 388 validator = blockchain.Validator() 389 processor = blockchain.Processor() 390 ) 391 392 structLogger := vm.NewStructLogger(logConfig) 393 394 config := vm.Config{ 395 Debug: true, 396 Tracer: structLogger, 397 } 398 399 if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash(), block.NumberU64()-1), true, false); err != nil { 400 return false, structLogger.StructLogs(), err 401 } 402 statedb, err := blockchain.StateAt(blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1).Root()) 403 if err != nil { 404 return false, structLogger.StructLogs(), err 405 } 406 407 receipts, _, usedGas, err := processor.Process(block, statedb, config) 408 if err != nil { 409 return false, structLogger.StructLogs(), err 410 } 411 if err := validator.ValidateState(block, blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1), statedb, receipts, usedGas); err != nil { 412 return false, structLogger.StructLogs(), err 413 } 414 return true, structLogger.StructLogs(), nil 415 } 416 417 // callmsg is the message type used for call transitions. 418 type callmsg struct { 419 addr common.Address 420 to *common.Address 421 gas, gasPrice *big.Int 422 value *big.Int 423 data []byte 424 } 425 426 // accessor boilerplate to implement core.Message 427 func (m callmsg) From() (common.Address, error) { return m.addr, nil } 428 func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil } 429 func (m callmsg) Nonce() uint64 { return 0 } 430 func (m callmsg) CheckNonce() bool { return false } 431 func (m callmsg) To() *common.Address { return m.to } 432 func (m callmsg) GasPrice() *big.Int { return m.gasPrice } 433 func (m callmsg) Gas() *big.Int { return m.gas } 434 func (m callmsg) Value() *big.Int { return m.value } 435 func (m callmsg) Data() []byte { return m.data } 436 437 // formatError formats a Go error into either an empty string or the data content 438 // of the error itself. 439 func formatError(err error) string { 440 if err == nil { 441 return "" 442 } 443 return err.Error() 444 } 445 446 type timeoutError struct{} 447 448 func (t *timeoutError) Error() string { 449 return "Execution time exceeded" 450 } 451 452 // TraceTransaction returns the structured logs created during the execution of EVM 453 // and returns them as a JSON object. 454 func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.Hash, config *TraceArgs) (interface{}, error) { 455 var tracer vm.Tracer 456 if config != nil && config.Tracer != nil { 457 timeout := defaultTraceTimeout 458 if config.Timeout != nil { 459 var err error 460 if timeout, err = time.ParseDuration(*config.Timeout); err != nil { 461 return nil, err 462 } 463 } 464 465 var err error 466 if tracer, err = ethapi.NewJavascriptTracer(*config.Tracer); err != nil { 467 return nil, err 468 } 469 470 // Handle timeouts and RPC cancellations 471 deadlineCtx, cancel := context.WithTimeout(ctx, timeout) 472 go func() { 473 <-deadlineCtx.Done() 474 tracer.(*ethapi.JavascriptTracer).Stop(&timeoutError{}) 475 }() 476 defer cancel() 477 } else if config == nil { 478 tracer = vm.NewStructLogger(nil) 479 } else { 480 tracer = vm.NewStructLogger(config.LogConfig) 481 } 482 483 // Retrieve the tx from the chain and the containing block 484 tx, blockHash, _, txIndex := core.GetTransaction(api.eth.ChainDb(), txHash) 485 if tx == nil { 486 return nil, fmt.Errorf("transaction %x not found", txHash) 487 } 488 block := api.eth.BlockChain().GetBlockByHash(blockHash) 489 if block == nil { 490 return nil, fmt.Errorf("block %x not found", blockHash) 491 } 492 // Create the state database to mutate and eventually trace 493 parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1) 494 if parent == nil { 495 return nil, fmt.Errorf("block parent %x not found", block.ParentHash()) 496 } 497 stateDb, err := api.eth.BlockChain().StateAt(parent.Root()) 498 if err != nil { 499 return nil, err 500 } 501 502 signer := types.MakeSigner(api.config, block.Number()) 503 // Mutate the state and trace the selected transaction 504 for idx, tx := range block.Transactions() { 505 // Assemble the transaction call message 506 msg, err := tx.AsMessage(signer) 507 if err != nil { 508 return nil, fmt.Errorf("sender retrieval failed: %v", err) 509 } 510 context := core.NewEVMContext(msg, block.Header(), api.eth.BlockChain()) 511 512 // Mutate the state if we haven't reached the tracing transaction yet 513 if uint64(idx) < txIndex { 514 vmenv := vm.NewEVM(context, stateDb, api.config, vm.Config{}) 515 _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())) 516 if err != nil { 517 return nil, fmt.Errorf("mutation failed: %v", err) 518 } 519 stateDb.DeleteSuicides() 520 continue 521 } 522 523 vmenv := vm.NewEVM(context, stateDb, api.config, vm.Config{Debug: true, Tracer: tracer}) 524 ret, gas, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())) 525 if err != nil { 526 return nil, fmt.Errorf("tracing failed: %v", err) 527 } 528 529 switch tracer := tracer.(type) { 530 case *vm.StructLogger: 531 return ðapi.ExecutionResult{ 532 Gas: gas, 533 ReturnValue: fmt.Sprintf("%x", ret), 534 StructLogs: ethapi.FormatLogs(tracer.StructLogs()), 535 }, nil 536 case *ethapi.JavascriptTracer: 537 return tracer.GetResult() 538 } 539 } 540 return nil, errors.New("database inconsistency") 541 } 542 543 // Preimage is a debug API function that returns the preimage for a sha3 hash, if known. 544 func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { 545 db := core.PreimageTable(api.eth.ChainDb()) 546 return db.Get(hash.Bytes()) 547 } 548 549 // GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network 550 // and returns them as a JSON list of block-hashes 551 func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]core.BadBlockArgs, error) { 552 return api.eth.BlockChain().BadBlocks() 553 }