github.com/amazechain/amc@v0.1.3/internal/api/api.go (about) 1 // Copyright 2022 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "github.com/amazechain/amc/conf" 24 "github.com/amazechain/amc/internal" 25 "github.com/amazechain/amc/internal/api/filters" 26 vm2 "github.com/amazechain/amc/internal/vm" 27 "github.com/amazechain/amc/internal/vm/evmtypes" 28 event "github.com/amazechain/amc/modules/event/v2" 29 "github.com/amazechain/amc/modules/state" 30 "github.com/amazechain/amc/turbo/rpchelper" 31 "github.com/holiman/uint256" 32 33 "math" 34 "math/big" 35 "time" 36 37 "github.com/ledgerwatch/erigon-lib/kv" 38 39 "github.com/amazechain/amc/accounts" 40 "github.com/amazechain/amc/common" 41 "github.com/amazechain/amc/common/block" 42 "github.com/amazechain/amc/common/crypto" 43 "github.com/amazechain/amc/common/hexutil" 44 "github.com/amazechain/amc/common/transaction" 45 "github.com/amazechain/amc/common/types" 46 "github.com/amazechain/amc/internal/avm/abi" 47 mvm_common "github.com/amazechain/amc/internal/avm/common" 48 mvm_types "github.com/amazechain/amc/internal/avm/types" 49 "github.com/amazechain/amc/internal/consensus" 50 "github.com/amazechain/amc/log" 51 "github.com/amazechain/amc/modules/rawdb" 52 "github.com/amazechain/amc/modules/rpc/jsonrpc" 53 "github.com/amazechain/amc/params" 54 ) 55 56 const ( 57 // todo 58 baseFee = 5000000 59 rpcEVMTimeout = time.Duration(5 * time.Second) 60 rpcGasCap = 50000000 61 ) 62 63 // API compatible EthereumAPI provides an API to access related information. 64 type API struct { 65 db kv.RwDB 66 bc common.IBlockChain 67 engine consensus.Engine 68 txspool common.ITxsPool 69 70 accountManager *accounts.Manager 71 chainConfig *params.ChainConfig 72 73 gpo *Oracle 74 } 75 76 // NewAPI creates a new protocol API. 77 func NewAPI(bc common.IBlockChain, db kv.RwDB, engine consensus.Engine, txspool common.ITxsPool, accountManager *accounts.Manager, config *params.ChainConfig) *API { 78 return &API{ 79 db: db, 80 bc: bc, 81 engine: engine, 82 txspool: txspool, 83 accountManager: accountManager, 84 chainConfig: config, 85 } 86 } 87 88 func (api *API) SetGpo(gpo *Oracle) { 89 api.gpo = gpo 90 } 91 92 func (api *API) Apis() []jsonrpc.API { 93 nonceLock := new(AddrLocker) 94 return []jsonrpc.API{ 95 { 96 Namespace: "eth", 97 Service: NewBlockChainAPI(api), 98 }, { 99 Namespace: "eth", 100 Service: NewAmcAPI(api), 101 }, { 102 Namespace: "eth", 103 Service: NewTransactionAPI(api, nonceLock), 104 }, { 105 Namespace: "web3", 106 Service: &Web3API{api}, 107 }, { 108 Namespace: "net", 109 Service: NewNetAPI(api, api.GetChainConfig().ChainID.Uint64()), 110 }, 111 { 112 Namespace: "debug", 113 Service: NewDebugAPI(api), 114 }, 115 { 116 Namespace: "txpool", 117 Service: NewTxsPoolAPI(api), 118 }, { 119 Namespace: "eth", 120 Service: filters.NewFilterAPI(api, 5*time.Minute), 121 }, 122 } 123 } 124 125 func (n *API) TxsPool() common.ITxsPool { return n.txspool } 126 func (n *API) Database() kv.RwDB { return n.db } 127 func (n *API) Engine() consensus.Engine { return n.engine } 128 func (n *API) BlockChain() common.IBlockChain { return n.bc } 129 func (n *API) GetEvm(ctx context.Context, msg internal.Message, ibs evmtypes.IntraBlockState, header block.IHeader, vmConfig *vm2.Config) (*vm2.EVM, func() error, error) { 130 vmError := func() error { return nil } 131 132 txContext := internal.NewEVMTxContext(msg) 133 context := internal.NewEVMBlockContext(header.(*block.Header), internal.GetHashFn(header.(*block.Header), nil), n.engine, nil) 134 //tx, err := n.db.BeginRo(ctx) 135 //if nil != err { 136 // return nil, nil, err 137 //} 138 //defer tx.Rollback() 139 // 140 //stateReader := state.NewPlainStateReader(tx) 141 142 return vm2.NewEVM(context, txContext, ibs, n.GetChainConfig(), *vmConfig), vmError, nil 143 } 144 145 func (n *API) State(tx kv.Tx, blockNrOrHash jsonrpc.BlockNumberOrHash) evmtypes.IntraBlockState { 146 147 _, blockHash, err := rpchelper.GetCanonicalBlockNumber(blockNrOrHash, tx) 148 if err != nil { 149 return nil 150 } 151 152 blockNr := rawdb.ReadHeaderNumber(tx, blockHash) 153 if nil == blockNr { 154 return nil 155 } 156 157 stateReader := state.NewPlainState(tx, *blockNr+1) 158 return state.New(stateReader) 159 } 160 161 func (n *API) GetChainConfig() *params.ChainConfig { 162 return n.chainConfig 163 } 164 165 func (n *API) RPCGasCap() uint64 { 166 return rpcGasCap 167 } 168 169 // AmcAPI provides an API to access metadata related information. 170 type AmcAPI struct { 171 api *API 172 } 173 174 // NewAmcAPI creates a new Meta protocol API. 175 func NewAmcAPI(api *API) *AmcAPI { 176 return &AmcAPI{api} 177 } 178 179 // GasPrice returns a suggestion for a gas price for legacy transactions. 180 func (s *AmcAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) { 181 conf.LightClientGPO.Default = big.NewInt(params.GWei) 182 //oracle := NewOracle(s.api.BlockChain(), conf.LightClientGPO) 183 tipcap, err := s.api.gpo.SuggestTipCap(ctx, s.api.GetChainConfig()) 184 if err != nil { 185 return nil, err 186 } 187 if head := s.api.BlockChain().CurrentBlock().Header(); head.BaseFee64() != uint256.NewInt(0) { 188 tipcap.Add(tipcap, head.BaseFee64().ToBig()) 189 } 190 return (*hexutil.Big)(tipcap), nil 191 //todo hardcode 13Gwei 192 //tipcap := 13000000000 193 //return (*hexutil.Big)(new(big.Int).SetUint64(uint64(tipcap))), nil 194 } 195 196 // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. 197 func (s *AmcAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) { 198 tipcap, err := s.api.gpo.SuggestTipCap(ctx, s.api.GetChainConfig()) 199 if err != nil { 200 return nil, err 201 } 202 return (*hexutil.Big)(tipcap), err 203 } 204 205 type feeHistoryResult struct { 206 OldestBlock *hexutil.Big `json:"oldestBlock"` 207 Reward [][]*hexutil.Big `json:"reward,omitempty"` 208 BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` 209 GasUsedRatio []float64 `json:"gasUsedRatio"` 210 } 211 212 // FeeHistory returns the fee market history. 213 func (s *AmcAPI) FeeHistory(ctx context.Context, blockCount jsonrpc.DecimalOrHex, lastBlock jsonrpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) { 214 215 var ( 216 resolvedLastBlock *uint256.Int 217 err error 218 ) 219 220 s.api.db.View(ctx, func(tx kv.Tx) error { 221 resolvedLastBlock, _, err = rpchelper.GetBlockNumber(jsonrpc.BlockNumberOrHashWithNumber(lastBlock), tx) 222 return nil 223 }) 224 225 if err != nil { 226 return nil, err 227 } 228 229 oldest, reward, baseFee, gasUsed, err := s.api.gpo.FeeHistory(ctx, int(blockCount), lastBlock, resolvedLastBlock, rewardPercentiles) 230 if err != nil { 231 return nil, err 232 } 233 results := &feeHistoryResult{ 234 OldestBlock: (*hexutil.Big)(oldest), 235 GasUsedRatio: gasUsed, 236 } 237 if reward != nil { 238 results.Reward = make([][]*hexutil.Big, len(reward)) 239 for i, w := range reward { 240 results.Reward[i] = make([]*hexutil.Big, len(w)) 241 for j, v := range w { 242 results.Reward[i][j] = (*hexutil.Big)(v) 243 } 244 } 245 } 246 if baseFee != nil { 247 results.BaseFee = make([]*hexutil.Big, len(baseFee)) 248 for i, v := range baseFee { 249 results.BaseFee[i] = (*hexutil.Big)(v) 250 } 251 } 252 return results, nil 253 } 254 255 // TxPoolAPI offers and API for the transaction pool. It only operates on data that is non confidential. 256 type TxPoolAPI struct { 257 api *API 258 } 259 260 // NewTxPoolAPI creates a new tx pool service that gives information about the transaction pool. 261 func NewTxPoolAPI(api *API) *TxPoolAPI { 262 return &TxPoolAPI{api} 263 } 264 265 // Content returns the transactions contained within the transaction pool. 266 func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { 267 content := map[string]map[string]map[string]*RPCTransaction{ 268 "pending": make(map[string]map[string]*RPCTransaction), 269 "queued": make(map[string]map[string]*RPCTransaction), 270 } 271 return content 272 } 273 274 // ContentFrom returns the transactions contained within the transaction pool. 275 func (s *TxPoolAPI) ContentFrom(addr types.Address) map[string]map[string]*RPCTransaction { 276 content := make(map[string]map[string]*RPCTransaction, 2) 277 278 return content 279 } 280 281 // Status returns the number of pending and queued transaction in the pool. 282 func (s *TxPoolAPI) Status() map[string]hexutil.Uint { 283 _, pending, _, queue := s.api.TxsPool().Stats() 284 return map[string]hexutil.Uint{ 285 "pending": hexutil.Uint(pending), 286 "queued": hexutil.Uint(queue), 287 } 288 } 289 290 // Inspect retrieves the content of the transaction pool and flattens it into an 291 // easily inspectable list. 292 func (s *TxPoolAPI) Inspect() map[string]map[string]map[string]string { 293 content := map[string]map[string]map[string]string{ 294 "pending": make(map[string]map[string]string), 295 "queued": make(map[string]map[string]string), 296 } 297 298 return content 299 } 300 301 // AccountAPI provides an API to access accounts managed by this node. 302 // It offers only methods that can retrieve accounts. 303 type AccountAPI struct { 304 } 305 306 // NewAccountAPI creates a new AccountAPI. 307 func NewAccountAPI() *AccountAPI { 308 return &AccountAPI{} 309 } 310 311 // Accounts returns the collection of accounts this node manages. 312 func (s *AccountAPI) Accounts() []types.Address { 313 //return s.am.Accounts() 314 return nil 315 } 316 317 // BlockChainAPI provides an API to access Ethereum blockchain data. 318 type BlockChainAPI struct { 319 api *API 320 } 321 322 // NewBlockChainAPI creates a new blockchain API. 323 func NewBlockChainAPI(api *API) *BlockChainAPI { 324 return &BlockChainAPI{api} 325 } 326 327 // ChainId get Chain ID 328 func (api *BlockChainAPI) ChainId() *hexutil.Big { 329 return (*hexutil.Big)(api.api.GetChainConfig().ChainID) 330 } 331 332 // GetBalance get balance 333 func (s *BlockChainAPI) GetBalance(ctx context.Context, address mvm_common.Address, blockNrOrHash jsonrpc.BlockNumberOrHash) (*hexutil.Big, error) { 334 tx, err := s.api.db.BeginRo(ctx) 335 if nil != err { 336 return nil, err 337 } 338 defer tx.Rollback() 339 340 state := s.api.State(tx, blockNrOrHash) 341 if state == nil { 342 return nil, nil 343 } 344 balance := state.GetBalance(*mvm_types.ToAmcAddress(&address)) 345 return (*hexutil.Big)(balance.ToBig()), nil 346 } 347 348 func (s *BlockChainAPI) BlockNumber() hexutil.Uint64 { 349 //jsonrpc.LatestBlockNumber 350 header := s.api.BlockChain().CurrentBlock().Header() // latest header should always be available 351 return hexutil.Uint64(header.Number64().Uint64()) 352 } 353 354 // GetCode get code 355 func (s *BlockChainAPI) GetCode(ctx context.Context, address mvm_common.Address, blockNrOrHash jsonrpc.BlockNumberOrHash) (hexutil.Bytes, error) { 356 tx, err := s.api.db.BeginRo(ctx) 357 if nil != err { 358 return nil, err 359 } 360 defer tx.Rollback() 361 362 state := s.api.State(tx, blockNrOrHash) 363 if state == nil { 364 return nil, nil 365 } 366 code := state.GetCode(*mvm_types.ToAmcAddress(&address)) 367 return code, nil 368 } 369 370 // GetStorageAt returns the storage from the state at the given address, key and 371 // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber metadata block 372 // numbers are also allowed. 373 func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address types.Address, key string, blockNrOrHash jsonrpc.BlockNumberOrHash) (hexutil.Bytes, error) { 374 tx, err := s.api.db.BeginRo(ctx) 375 if nil != err { 376 return nil, err 377 } 378 defer tx.Rollback() 379 380 state := s.api.State(tx, blockNrOrHash) 381 if state == nil { 382 return nil, nil 383 } 384 var va uint256.Int 385 k := types.HexToHash(key) 386 state.GetState(address, &k, &va) 387 return va.Bytes(), nil 388 } 389 390 // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash 391 func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash mvm_common.Hash) *hexutil.Uint { 392 if block, _ := s.api.BlockChain().GetBlockByHash(mvm_types.ToAmcHash(blockHash)); block != nil { 393 //POA donot have Uncles 394 n := hexutil.Uint(0) 395 return &n 396 } 397 return nil 398 } 399 400 // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. 401 func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash mvm_common.Hash, index hexutil.Uint) (map[string]interface{}, error) { 402 b, err := s.api.BlockChain().GetBlockByHash(mvm_types.ToAmcHash(blockHash)) 403 if b != nil { 404 //POA donot have Uncles 405 var uncles []struct{} 406 if index >= hexutil.Uint(len(uncles)) { 407 return nil, nil 408 } 409 block := block.NewBlock(&block.Header{}, nil) 410 return RPCMarshalBlock(block, s.api.BlockChain(), false, false) 411 } 412 return nil, err 413 } 414 415 // Result structs for GetProof 416 type AccountResult struct { 417 Address types.Address `json:"address"` 418 AccountProof []string `json:"accountProof"` 419 Balance *hexutil.Big `json:"balance"` 420 CodeHash types.Hash `json:"codeHash"` 421 Nonce hexutil.Uint64 `json:"nonce"` 422 StorageHash types.Hash `json:"storageHash"` 423 StorageProof []StorageResult `json:"storageProof"` 424 } 425 426 type StorageResult struct { 427 Key string `json:"key"` 428 Value *hexutil.Big `json:"value"` 429 Proof []string `json:"proof"` 430 } 431 432 // // OverrideAccount indicates the overriding fields of account during the execution 433 // // of a message call. 434 // // Note, state and stateDiff can't be specified at the same time. If state is 435 // // set, message execution will only use the data in the given state. Otherwise 436 // // if statDiff is set, all diff will be applied first and then execute the call 437 // // message. 438 type OverrideAccount struct { 439 Nonce *hexutil.Uint64 `json:"nonce"` 440 Code *hexutil.Bytes `json:"code"` 441 Balance **hexutil.Big `json:"balance"` 442 StatsPrint *map[mvm_common.Hash]mvm_common.Hash `json:"state"` 443 StateDiff *map[mvm_common.Hash]mvm_common.Hash `json:"stateDiff"` 444 } 445 446 // StateOverride is the collection of overridden accounts. 447 type StateOverride map[mvm_common.Address]OverrideAccount 448 449 // Apply overrides the fields of specified accounts into the given state. 450 func (diff *StateOverride) Apply(state *state.IntraBlockState) error { 451 if diff == nil { 452 return nil 453 } 454 for addr, account := range *diff { 455 // Override account nonce. 456 if account.Nonce != nil { 457 state.SetNonce(*mvm_types.ToAmcAddress(&addr), uint64(*account.Nonce)) 458 } 459 // Override account(contract) code. 460 if account.Code != nil { 461 state.SetCode(*mvm_types.ToAmcAddress(&addr), *account.Code) 462 } 463 // Override account balance. 464 if account.Balance != nil { 465 balance, _ := uint256.FromBig((*big.Int)(*account.Balance)) 466 state.SetBalance(*mvm_types.ToAmcAddress(&addr), balance) 467 } 468 if account.StatsPrint != nil && account.StateDiff != nil { 469 return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.String()) 470 } 471 if account.StatsPrint != nil { 472 statesPrint := make(map[types.Hash]uint256.Int) 473 for k, v := range *account.StatsPrint { 474 d, _ := uint256.FromBig(v.Big()) 475 statesPrint[mvm_types.ToAmcHash(k)] = *d 476 } 477 state.SetStorage(*mvm_types.ToAmcAddress(&addr), statesPrint) 478 } 479 // Apply state diff into specified accounts. 480 if account.StateDiff != nil { 481 for key, value := range *account.StateDiff { 482 k := mvm_types.ToAmcHash(key) 483 v, _ := uint256.FromBig(value.Big()) 484 state.SetState(*mvm_types.ToAmcAddress(&addr), &k, *v) 485 } 486 } 487 } 488 return nil 489 } 490 491 // BlockOverrides is a set of header fields to override. 492 type BlockOverrides struct { 493 Number *hexutil.Big 494 Difficulty *hexutil.Big 495 Time *hexutil.Uint64 496 GasLimit *hexutil.Uint64 497 Coinbase *types.Address 498 Random *types.Hash 499 BaseFee *hexutil.Big 500 } 501 502 // Apply overrides the given header fields into the given block context. 503 func (diff *BlockOverrides) Apply(blockCtx *evmtypes.BlockContext) { 504 if diff == nil { 505 return 506 } 507 if diff.Number != nil { 508 blockCtx.BlockNumber = diff.Number.ToInt().Uint64() 509 } 510 if diff.Difficulty != nil { 511 blockCtx.Difficulty = diff.Difficulty.ToInt() 512 } 513 if diff.Time != nil { 514 blockCtx.Time = uint64(*diff.Time) 515 } 516 if diff.GasLimit != nil { 517 blockCtx.GasLimit = uint64(*diff.GasLimit) 518 } 519 if diff.Coinbase != nil { 520 blockCtx.Coinbase = *diff.Coinbase 521 } 522 if diff.Random != nil { 523 blockCtx.PrevRanDao = diff.Random 524 } 525 if diff.BaseFee != nil { 526 blockCtx.BaseFee, _ = uint256.FromBig(diff.BaseFee.ToInt()) 527 } 528 } 529 530 func DoCall(ctx context.Context, api *API, args TransactionArgs, blockNrOrHash jsonrpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*internal.ExecutionResult, error) { 531 defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) 532 533 // header := api.BlockChain().CurrentBlock().Header() 534 //state := api.BlockChain().StateAt(header.Hash()).(*statedb.StateDB) 535 var header block.IHeader 536 var err error 537 if blockNr, ok := blockNrOrHash.Number(); ok { 538 if blockNr < jsonrpc.EarliestBlockNumber { 539 header = api.BlockChain().CurrentBlock().Header() 540 } else { 541 header = api.BlockChain().GetHeaderByNumber(uint256.NewInt(uint64(blockNr.Int64()))) 542 } 543 } 544 if hash, ok := blockNrOrHash.Hash(); ok { 545 header, err = api.BlockChain().GetHeaderByHash(hash) 546 } 547 if err != nil { 548 return nil, err 549 } 550 //state := api.State(blockNrOrHash).(*statedb.StateDB) 551 tx, err := api.db.BeginRo(ctx) 552 if nil != err { 553 return nil, err 554 } 555 defer tx.Rollback() 556 557 //reader := state.NewPlainStateReader(tx) 558 //ibs := state.New(reader) 559 ibs := api.State(tx, blockNrOrHash) 560 if ibs == nil { 561 return nil, errors.New("cannot load state") 562 } 563 if err := overrides.Apply(ibs.(*state.IntraBlockState)); err != nil { 564 return nil, err 565 } 566 // Setup context so it may be cancelled the call has completed 567 // or, in case of unmetered gas, setup a context with a timeout. 568 var cancel context.CancelFunc 569 if timeout > 0 { 570 ctx, cancel = context.WithTimeout(ctx, timeout) 571 } else { 572 ctx, cancel = context.WithCancel(ctx) 573 } 574 // Make sure the context is cancelled when the call has completed 575 // this makes sure resources are cleaned up. 576 defer cancel() 577 578 // Get a new instance of the EVM. 579 msg, err := args.ToMessage(globalGasCap, header.BaseFee64().ToBig()) 580 if err != nil { 581 return nil, err 582 } 583 584 //todo debug: , Debug: true, Tracer: vm.NewMarkdownLogger(os.Stdout) 585 evm, vmError, err := api.GetEvm(ctx, msg, ibs, header, &vm2.Config{NoBaseFee: true}) 586 if err != nil { 587 return nil, err 588 } 589 // Wait for the context to be done and cancel the evm. Even if the 590 // EVM has finished, cancelling may be done (repeatedly) 591 go func() { 592 <-ctx.Done() 593 evm.Cancel() 594 }() 595 596 // Execute the message. 597 gp := new(common.GasPool).AddGas(math.MaxUint64) 598 result, err := internal.ApplyMessage(evm, msg, gp, true, false) 599 if err := vmError(); err != nil { 600 return nil, err 601 } 602 603 if evm.Cancelled() { 604 return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) 605 } 606 if err != nil { 607 return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) 608 } 609 return result, nil 610 } 611 612 func newRevertError(result *internal.ExecutionResult) *revertError { 613 reason, errUnpack := abi.UnpackRevert(result.Revert()) 614 err := fmt.Errorf("execution reverted") 615 if errUnpack == nil { 616 err = fmt.Errorf("execution reverted: %v", reason) 617 } 618 return &revertError{ 619 error: err, 620 reason: hexutil.Encode(result.Revert()), 621 } 622 } 623 624 // revertError is an API error that encompassas an EVM revertal with JSON error 625 // code and a binary data blob. 626 type revertError struct { 627 error 628 reason string // revert reason hex encoded 629 } 630 631 // ErrorCode returns the JSON error code for a revertal. 632 // See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal 633 func (e *revertError) ErrorCode() int { 634 return 3 635 } 636 637 // ErrorData returns the hex encoded revert reason. 638 func (e *revertError) ErrorData() interface{} { 639 return e.reason 640 } 641 642 // Call executes the given transaction on the state for the given block number. 643 // 644 // Additionally, the caller can specify a batch of contract for fields overriding. 645 // 646 // Note, this function doesn't make and changes in the state/blockchain and is 647 // useful to execute and retrieve values. 648 func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash jsonrpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) { 649 650 //b, _ := json.Marshal(args) 651 //log.Info("TransactionArgs %s", string(b)) 652 653 result, err := DoCall(ctx, s.api, args, blockNrOrHash, overrides, rpcEVMTimeout, rpcGasCap) 654 if err != nil { 655 return nil, err 656 } 657 // If the result contains a revert reason, try to unpack and return it. 658 if len(result.Revert()) > 0 { 659 return nil, newRevertError(result) 660 } 661 return result.Return(), result.Err 662 } 663 664 func BlockByNumber(ctx context.Context, number jsonrpc.BlockNumber, n *API) (block.IBlock, error) { 665 // todo 666 // Pending block is only known by the miner 667 if number == jsonrpc.PendingBlockNumber { 668 iblock := n.BlockChain().CurrentBlock() 669 return iblock, nil 670 } 671 // Otherwise resolve and return the block 672 if number == jsonrpc.LatestBlockNumber { 673 iblock := n.BlockChain().CurrentBlock() 674 return iblock, nil 675 } 676 iblock, err := n.BlockChain().GetBlockByNumber(uint256.NewInt(uint64(number))) 677 if err != nil { 678 return nil, err 679 } 680 return iblock, nil 681 } 682 683 func BlockByNumberOrHash(ctx context.Context, blockNrOrHash jsonrpc.BlockNumberOrHash, api *API) (block.IBlock, error) { 684 if blockNr, ok := blockNrOrHash.Number(); ok { 685 if blockNr == jsonrpc.PendingBlockNumber { 686 return api.BlockChain().CurrentBlock(), nil 687 } 688 return BlockByNumber(ctx, blockNr, api) 689 } 690 if hash, ok := blockNrOrHash.Hash(); ok { 691 iblock, err := api.BlockChain().GetBlockByHash(types.Hash(hash)) 692 if err != nil { 693 return nil, err 694 } 695 if iblock == nil { 696 return nil, errors.New("header found, but block body is missing") 697 } 698 699 //todo 700 //header := iblock.Header() 701 //if header == nil { 702 // return nil, errors.New("header for hash not found") 703 //} 704 //iblock, err = n.BlockChain().GetBlockByNumber(header.Number64()) 705 //if err != nil { 706 // return nil, err 707 //} 708 //if blockNrOrHash.RequireCanonical && iblock.Hash() != types.Hash(hash) { 709 // return nil, errors.New("hash is not currently canonical") 710 //} 711 //iblock, err = n.BlockChain().GetBlockByNumber(n.BlockChain().GetHeader(types.Hash(hash), header.Number64()).Number64()) 712 //if err != nil { 713 // return nil, err 714 //} 715 return iblock, nil 716 } 717 return nil, errors.New("invalid arguments; neither block nor hash specified") 718 } 719 720 //func StateAndHeaderByNumber(ctx context.Context, n *API, number jsonrpc.BlockNumber) (*common.IStateDB, *block.IHeader, error) { 721 // var header block.IHeader 722 // var err error 723 // if number == jsonrpc.PendingBlockNumber { 724 // header = n.BlockChain().CurrentBlock().Header() 725 // } else { 726 // header, err = n.BlockChain().GetHeaderByNumber(uint256.NewInt(uint64(number))) 727 // } 728 // if err != nil { 729 // return nil, nil, err 730 // } 731 // if header == nil { 732 // return nil, nil, errors.New("header not found") 733 // } 734 // stateDb := n.BlockChain().StateAt(header.Hash()) 735 // return &stateDb, &header, nil 736 //} 737 738 //func StateAndHeaderByNumberOrHash(ctx context.Context, n *API, blockNrOrHash jsonrpc.BlockNumberOrHash) (*common.IStateDB, *block.IHeader, error) { 739 // if blockNr, ok := blockNrOrHash.Number(); ok { 740 // return StateAndHeaderByNumber(ctx, n, blockNr) 741 // } 742 // if hash, ok := blockNrOrHash.Hash(); ok { 743 // header, err := n.BlockChain().GetHeaderByHash(types.Hash(hash)) 744 // if err != nil { 745 // return nil, nil, err 746 // } 747 // if header == nil { 748 // return nil, nil, errors.New("header for hash not found") 749 // } 750 // //todo 751 // //if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 752 // // return nil, nil, errors.New("hash is not currently canonical") 753 // //} 754 // stateDb := n.BlockChain().StateAt(header.Hash()) 755 // return &stateDb, &header, err 756 // } 757 // return nil, nil, errors.New("invalid arguments; neither block nor hash specified") 758 //} 759 760 func DoEstimateGas(ctx context.Context, n *API, args TransactionArgs, blockNrOrHash jsonrpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { 761 // Binary search the gas requirement, as it may be higher than the amount used 762 var ( 763 lo = params.TxGas - 1 764 hi uint64 765 cap uint64 766 ) 767 // Use zero address if sender unspecified. 768 if args.From == nil { 769 args.From = new(mvm_common.Address) 770 } 771 // Determine the highest gas limit can be used during the estimation. 772 if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { 773 hi = uint64(*args.Gas) 774 } else { 775 // Retrieve the block to act as the gas ceiling 776 iblock, err := BlockByNumberOrHash(ctx, blockNrOrHash, n) 777 if err != nil { 778 return 0, err 779 } 780 if iblock == nil { 781 return 0, errors.New("block not found") 782 } 783 hi = iblock.GasLimit() 784 } 785 786 var feeCap *big.Int 787 if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { 788 return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 789 } else if args.GasPrice != nil { 790 feeCap = args.GasPrice.ToInt() 791 } else if args.MaxFeePerGas != nil { 792 feeCap = args.MaxFeePerGas.ToInt() 793 } else { 794 feeCap = common.Big0 795 } 796 // Recap the highest gas limit with account's available balance. 797 if feeCap.BitLen() != 0 { 798 tx, err := n.db.BeginRo(ctx) 799 if nil != err { 800 return 0, err 801 } 802 defer tx.Rollback() 803 statedb := n.State(tx, blockNrOrHash) 804 if statedb == nil { 805 return 0, errors.New("cannot load stateDB") 806 } 807 balance := statedb.GetBalance(*mvm_types.ToAmcAddress(args.From)) // from 808 809 // can't be nil 810 available := new(big.Int).Set(balance.ToBig()) 811 if args.Value != nil { 812 if args.Value.ToInt().Cmp(available) >= 0 { 813 return 0, errors.New("insufficient funds for transfer") 814 } 815 available.Sub(available, args.Value.ToInt()) 816 } 817 allowance := new(big.Int).Div(available, feeCap) 818 819 // If the allowance is larger than maximum uint64, skip checking 820 if allowance.IsUint64() && hi > allowance.Uint64() { 821 transfer := args.Value 822 if transfer == nil { 823 transfer = new(hexutil.Big) 824 } 825 log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, 826 "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance) 827 hi = allowance.Uint64() 828 } 829 } 830 // Recap the highest gas allowance with specified gascap. 831 if gasCap != 0 && hi > gasCap { 832 log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) 833 hi = gasCap 834 } 835 cap = hi 836 837 // Create a helper to check if a gas allowance results in an executable transaction 838 executable := func(gas uint64) (bool, *internal.ExecutionResult, error) { 839 args.Gas = (*hexutil.Uint64)(&gas) 840 result, err := DoCall(ctx, n, args, blockNrOrHash, nil, 0, gasCap) 841 if err != nil { 842 if errors.Is(err, internal.ErrIntrinsicGas) { 843 return true, nil, nil // Special case, raise gas limit 844 } 845 return true, nil, err // Bail out 846 } 847 return result.Failed(), result, nil 848 } 849 // Execute the binary search and hone in on an executable gas limit 850 for lo+1 < hi { 851 mid := (hi + lo) / 2 852 failed, _, err := executable(mid) 853 854 // If the error is not nil(consensus error), it means the provided message 855 // call or transaction will never be accepted no matter how much gas it is 856 // assigened. Return the error directly, don't struggle any more. 857 if err != nil { 858 return 0, err 859 } 860 if failed { 861 lo = mid 862 } else { 863 hi = mid 864 } 865 } 866 // Reject the transaction as invalid if it still fails at the highest allowance 867 if hi == cap { 868 failed, result, err := executable(hi) 869 if err != nil { 870 return 0, err 871 } 872 if failed { 873 if result != nil && !errors.Is(result.Err, vm2.ErrOutOfGas) { 874 if len(result.Revert()) > 0 { 875 return 0, newRevertError(result) 876 } 877 return 0, result.Err 878 } 879 // Otherwise, the specified gas cap is too low 880 return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) 881 } 882 } 883 return hexutil.Uint64(hi), nil 884 //return hexutil.Uint64(baseFee), nil 885 } 886 887 // EstimateGas returns an estimate of the amount of gas needed to execute the 888 // given transaction against the current pending block. 889 func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *jsonrpc.BlockNumberOrHash) (hexutil.Uint64, error) { 890 bNrOrHash := jsonrpc.BlockNumberOrHashWithNumber(jsonrpc.PendingBlockNumber) 891 if blockNrOrHash != nil { 892 bNrOrHash = *blockNrOrHash 893 } 894 return DoEstimateGas(ctx, s.api, args, bNrOrHash, rpcGasCap) 895 } 896 897 // GetBlockByNumber returns the requested canonical block. 898 // - When blockNr is -1 the chain head is returned. 899 // - When blockNr is -2 the pending chain head is returned. 900 // - When fullTx is true all transactions in the block are returned, otherwise 901 // only the transaction hash is returned. 902 func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number jsonrpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { 903 904 var ( 905 block block.IBlock 906 err error 907 ) 908 // header 909 if number == jsonrpc.LatestBlockNumber { 910 block = s.api.BlockChain().CurrentBlock() 911 err = nil 912 } else { 913 block, err = s.api.BlockChain().GetBlockByNumber(uint256.NewInt(uint64(number.Int64()))) 914 } 915 916 if block != nil && err == nil { 917 response, err := RPCMarshalBlock(block, s.api.BlockChain(), true, fullTx) 918 if err == nil && number == jsonrpc.PendingBlockNumber { 919 // Pending blocks need to nil out a few fields 920 for _, field := range []string{"hash", "nonce", "miner"} { 921 response[field] = nil 922 } 923 } 924 return response, err 925 } 926 927 return nil, err 928 } 929 930 // GetBlockByHash get block by hash 931 func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash mvm_common.Hash, fullTx bool) (map[string]interface{}, error) { 932 block, err := s.api.BlockChain().GetBlockByHash(mvm_types.ToAmcHash(hash)) 933 934 if block != nil { 935 return RPCMarshalBlock(block, s.api.BlockChain(), true, fullTx) 936 } 937 return nil, err 938 } 939 940 func (s *BlockChainAPI) MinedBlock(ctx context.Context, address types.Address) (*jsonrpc.Subscription, error) { 941 notifier, supported := jsonrpc.NotifierFromContext(ctx) 942 if !supported { 943 return &jsonrpc.Subscription{}, jsonrpc.ErrNotificationsUnsupported 944 } 945 946 if is, err := IsDeposit(s.api.db, address); nil != err || !is { 947 if nil != err { 948 log.Errorf("IsDeposit(%s) failed, err= %v", address, err) 949 } 950 return &jsonrpc.Subscription{}, fmt.Errorf("unauthed address: %s", address) 951 } 952 953 rpcSub := notifier.CreateSubscription() 954 go func() { 955 entire := make(chan common.MinedEntireEvent, 20) 956 blocksSub := event.GlobalEvent.Subscribe(entire) 957 for { 958 select { 959 case b := <-entire: 960 var pushData state.EntireCode 961 pushData.Entire = b.Entire.Entire.Clone() 962 pushData.Entire.Header.Root = types.Hash{} 963 pushData.Headers = b.Entire.Headers 964 pushData.Codes = b.Entire.Codes 965 pushData.Rewards = b.Entire.Rewards 966 pushData.CoinBase = b.Entire.CoinBase 967 log.Trace("send mining block", "addr", address, "blockNr", b.Entire.Entire.Header.Number.Hex(), "blockTime", time.Unix(int64(b.Entire.Entire.Header.Time), 0).Format(time.RFC3339)) 968 notifier.Notify(rpcSub.ID, pushData) 969 case <-rpcSub.Err(): 970 blocksSub.Unsubscribe() 971 return 972 case <-notifier.Closed(): 973 blocksSub.Unsubscribe() 974 return 975 } 976 } 977 }() 978 return rpcSub, nil 979 } 980 981 func (s *BlockChainAPI) SubmitSign(sign AggSign) error { 982 info := DepositInfo(s.api.db, sign.Address) 983 if nil == info { 984 return fmt.Errorf("unauthed address: %s", sign.Address) 985 } 986 sign.PublicKey.SetBytes(info.PublicKey.Bytes()) 987 go func() { 988 sigChannel <- sign 989 }() 990 return nil 991 } 992 993 // TransactionAPI exposes methods for reading and creating transaction data. 994 type TransactionAPI struct { 995 api *API 996 nonceLock *AddrLocker 997 //signer types.Signer 998 } 999 1000 // NewTransactionAPI creates a new RPC service with methods for interacting with transactions. 1001 func NewTransactionAPI(api *API, nonceLock *AddrLocker) *TransactionAPI { 1002 //signer := types.LatestSigner(b.ChainConfig()) 1003 return &TransactionAPI{api, nonceLock} 1004 } 1005 1006 // GetTransactionCount returns the number of transactions the given address has sent for the given block number 1007 func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address mvm_common.Address, blockNrOrHash jsonrpc.BlockNumberOrHash) (*hexutil.Uint64, error) { 1008 1009 if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == jsonrpc.PendingBlockNumber { 1010 nonce := s.api.TxsPool().Nonce(*mvm_types.ToAmcAddress(&address)) 1011 return (*hexutil.Uint64)(&nonce), nil 1012 } 1013 1014 tx, err := s.api.db.BeginRo(ctx) 1015 if nil != err { 1016 return nil, err 1017 } 1018 defer tx.Rollback() 1019 1020 state := s.api.State(tx, blockNrOrHash) 1021 if state == nil { 1022 return nil, nil 1023 } 1024 nonce := state.GetNonce(*mvm_types.ToAmcAddress(&address)) 1025 return (*hexutil.Uint64)(&nonce), nil 1026 1027 } 1028 1029 func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (mvm_common.Hash, error) { 1030 1031 //log.Debugf("tx type is : %s", string(input[0])) 1032 tx := new(mvm_types.Transaction) 1033 err := tx.UnmarshalBinary(input) 1034 if err != nil { 1035 return mvm_common.Hash{}, err 1036 } 1037 header := s.api.BlockChain().CurrentBlock().Header() // latest header should always be available 1038 metaTx, err := tx.ToAmcTransaction(s.api.GetChainConfig(), header.Number64().ToBig()) 1039 if err != nil { 1040 return mvm_common.Hash{}, err 1041 } 1042 return SubmitTransaction(context.Background(), s.api, metaTx) 1043 } 1044 1045 func (s *TransactionAPI) BatchRawTransaction(ctx context.Context, inputs []hexutil.Bytes) ([]mvm_common.Hash, error) { 1046 1047 //log.Debugf("tx type is : %s", string(input[0])) 1048 hs := make([]mvm_common.Hash, len(inputs)) 1049 for i, t := range inputs { 1050 tx := new(mvm_types.Transaction) 1051 err := tx.UnmarshalBinary(t) 1052 if err != nil { 1053 hs[i] = mvm_common.Hash{} 1054 return hs, err 1055 } 1056 header := s.api.BlockChain().CurrentBlock().Header() // latest header should always be available 1057 metaTx, err := tx.ToAmcTransaction(s.api.GetChainConfig(), header.Number64().ToBig()) 1058 if err != nil { 1059 hs[i] = mvm_common.Hash{} 1060 return hs, err 1061 } 1062 1063 if hs[i], err = SubmitTransaction(context.Background(), s.api, metaTx); nil != err { 1064 return hs, err 1065 } 1066 } 1067 return hs, nil 1068 } 1069 1070 // GetTransactionReceipt returns the transaction receipt for the given transaction hash. 1071 func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash mvm_common.Hash) (map[string]interface{}, error) { 1072 var tx *transaction.Transaction 1073 var blockHash types.Hash 1074 var index uint64 1075 var blockNumber uint64 1076 var err error 1077 s.api.Database().View(ctx, func(t kv.Tx) error { 1078 tx, blockHash, blockNumber, index, err = rawdb.ReadTransactionByHash(t, mvm_types.ToAmcHash(hash)) 1079 if err != nil || tx == nil { 1080 log.Tracef("rawdb.ReadTransactionByHash, err = %v, txhash = %v \n", err, hash) 1081 // When the transaction doesn't exist, the RPC method should return JSON null 1082 // as per specification. 1083 } 1084 return nil 1085 }) 1086 if tx == nil { 1087 return nil, nil 1088 } 1089 //tx, blockHash, blockNumber, index, err := rawdb.ReadTransactionByHash(s.api.Database().(kv.Tx), mvm_types.ToAmcHash(hash)) 1090 //if err != nil || tx == nil { 1091 // // When the transaction doesn't exist, the RPC method should return JSON null 1092 // // as per specification. 1093 // return nil, nil 1094 //} 1095 //log.Infof("GetTransactionReceipt, hash %+v , %+v, %+v, %+v", tx, blockHash, blockNumber, index) 1096 receipts, err := s.api.BlockChain().GetReceipts(blockHash) 1097 1098 //log.Infof("GetTransactionReceipt, receipts %+v", receipts) 1099 if err != nil { 1100 return nil, err 1101 } 1102 if len(receipts) <= int(index) { 1103 return nil, nil 1104 } 1105 receipt := receipts[index] 1106 1107 from := tx.From() 1108 fields := map[string]interface{}{ 1109 "blockHash": mvm_types.FromAmcHash(blockHash), 1110 "blockNumber": hexutil.Uint64(blockNumber), 1111 "transactionHash": hash, 1112 "transactionIndex": hexutil.Uint64(index), 1113 "from": mvm_types.FromAmcAddress(from), 1114 "to": mvm_types.FromAmcAddress(tx.To()), 1115 "gasUsed": hexutil.Uint64(receipt.GasUsed), 1116 "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), 1117 "contractAddress": nil, 1118 "logsBloom": receipt.Bloom, //receipt.Bloom 1119 "type": hexutil.Uint(tx.Type()), 1120 } 1121 // Assign the effective gas price paid 1122 //todo !IsLondon 1123 if false { 1124 fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64()) 1125 } else { 1126 header, err := s.api.BlockChain().GetHeaderByHash(blockHash) 1127 if err != nil { 1128 return nil, err 1129 } 1130 gasPrice := new(big.Int).Add(header.BaseFee64().ToBig(), tx.EffectiveGasTipValue(header.BaseFee64()).ToBig()) 1131 fields["effectiveGasPrice"] = hexutil.Uint64(gasPrice.Uint64()) 1132 } 1133 // Assign receipt status or post state. 1134 if len(receipt.PostState) > 0 { 1135 fields["root"] = hexutil.Bytes(receipt.PostState) 1136 } else { 1137 fields["status"] = hexutil.Uint(receipt.Status) 1138 } 1139 if receipt.Logs == nil { 1140 fields["logs"] = []*mvm_types.Log{} 1141 } else { 1142 fields["logs"] = mvm_types.FromAmcLogs(receipt.Logs) 1143 } 1144 // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation 1145 if !receipt.ContractAddress.IsNull() { 1146 fields["contractAddress"] = mvm_types.FromAmcAddress(&receipt.ContractAddress) 1147 } 1148 1149 //json, _ := json.Marshal(fields) 1150 //log.Infof("GetTransactionReceipt, result %s", string(json)) 1151 return fields, nil 1152 } 1153 1154 // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. 1155 func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash mvm_common.Hash) *hexutil.Uint { 1156 if block, _ := s.api.BlockChain().GetBlockByHash(mvm_types.ToAmcHash(blockHash)); block != nil { 1157 n := hexutil.Uint(len(block.Transactions())) 1158 return &n 1159 } 1160 return nil 1161 } 1162 1163 // GetTransactionByHash returns the transaction for the given hash 1164 func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash mvm_common.Hash) (*RPCTransaction, error) { 1165 var ( 1166 tx *transaction.Transaction 1167 blockHash types.Hash 1168 blockNumber uint64 1169 index uint64 1170 err error 1171 ) 1172 if err := s.api.Database().View(ctx, func(t kv.Tx) error { 1173 tx, blockHash, blockNumber, index, err = rawdb.ReadTransactionByHash(t, mvm_types.ToAmcHash(hash)) 1174 if err != nil { 1175 // When the transaction doesn't exist, the RPC method should return JSON null 1176 // as per specification. 1177 return err 1178 } 1179 return nil 1180 }); nil != err { 1181 return nil, err 1182 } 1183 //tx, blockHash, blockNumber, index, err := rawdb.ReadTransactionByHash(s.api.Database().(kv.Tx), mvm_types.ToAmcHash(hash)) 1184 //if err != nil { 1185 // // When the transaction doesn't exist, the RPC method should return JSON null 1186 // // as per specification. 1187 // return nil, err 1188 //} 1189 1190 if tx != nil { 1191 header := s.api.BlockChain().GetHeaderByNumber(uint256.NewInt(blockNumber)) 1192 if header == nil { 1193 return nil, nil 1194 } 1195 return newRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee64().ToBig()), nil 1196 } 1197 1198 if tx := s.api.TxsPool().GetTx(mvm_types.ToAmcHash(hash)); tx != nil { 1199 return newRPCPendingTransaction(tx, s.api.BlockChain().CurrentBlock().Header()), nil 1200 } 1201 1202 return nil, nil 1203 } 1204 1205 // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. 1206 func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash mvm_common.Hash, index hexutil.Uint) *RPCTransaction { 1207 if block, _ := s.api.BlockChain().GetBlockByHash(mvm_types.ToAmcHash(blockHash)); block != nil { 1208 for i, tx := range block.Transactions() { 1209 if i == int(index) { 1210 return newRPCTransaction(tx, mvm_types.ToAmcHash(blockHash), block.Number64().Uint64(), uint64(index), block.Header().BaseFee64().ToBig()) 1211 } 1212 } 1213 } 1214 return nil 1215 } 1216 1217 // SubmitTransaction ? 1218 func SubmitTransaction(ctx context.Context, api *API, tx *transaction.Transaction) (mvm_common.Hash, error) { 1219 1220 if err := checkTxFee(*tx.GasPrice(), tx.Gas(), baseFee); err != nil { 1221 return mvm_common.Hash{}, err 1222 } 1223 1224 if err := api.TxsPool().AddLocal(tx); err != nil { 1225 return mvm_common.Hash{}, err 1226 } 1227 1228 if tx.To() == nil { 1229 //log.Info("Submitted contract creation", "hash", tx.Hash().Hex(), "from", from, "nonce", tx.Nonce(), "contract", addr.Hex(), "value", tx.Value()) 1230 } else { 1231 //log.Info("Submitted transaction", "hash", tx.Hash().Hex(), "from", from, "nonce", tx.Nonce(), "recipient", tx.To(), "value", tx.Value()) 1232 } 1233 hash := tx.Hash() 1234 return mvm_types.FromAmcHash(hash), nil 1235 } 1236 1237 // SendTransaction Send Transaction 1238 func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionArgs) (mvm_common.Hash, error) { 1239 // Look up the wallet containing the requested signer 1240 account := accounts.Account{Address: args.from()} 1241 1242 //wallet, err := s.b.AccountManager().Find(account) 1243 wallet, err := s.api.accountManager.Find(account) 1244 if err != nil { 1245 return mvm_common.Hash{}, err 1246 } 1247 1248 if args.Nonce == nil { 1249 s.nonceLock.LockAddr(args.from()) 1250 defer s.nonceLock.UnlockAddr(args.from()) 1251 } 1252 1253 if err := args.setDefaults(ctx, s.api); err != nil { 1254 return mvm_common.Hash{}, err 1255 } 1256 //header := s.api.BlockChain().CurrentBlock().Header() 1257 tx := args.toTransaction() 1258 1259 signed, err := wallet.SignTx(account, tx, s.api.GetChainConfig().ChainID) 1260 if err != nil { 1261 return mvm_common.Hash{}, err 1262 } 1263 // todo sign? 1264 //signed := tx 1265 return SubmitTransaction(ctx, s.api, signed) 1266 } 1267 1268 // checkTxFee todo 1269 func checkTxFee(gasPrice uint256.Int, gas uint64, cap float64) error { 1270 return nil 1271 } 1272 1273 // toHexSlice creates a slice of hex-strings based on []byte. 1274 func toHexSlice(b [][]byte) []string { 1275 r := make([]string, len(b)) 1276 for i := range b { 1277 r[i] = hexutil.Encode(b[i]) 1278 } 1279 return r 1280 } 1281 1282 type Web3API struct { 1283 stack *API 1284 } 1285 1286 func (s *Web3API) ClientVersion() string { 1287 return "testName" 1288 } 1289 1290 func (s *Web3API) Sha3(input hexutil.Bytes) hexutil.Bytes { 1291 return crypto.Keccak256(input) 1292 } 1293 1294 type DebugAPI struct { 1295 api *API 1296 } 1297 1298 // NewDebugAPI creates a new instance of DebugAPI. 1299 func NewDebugAPI(api *API) *DebugAPI { 1300 return &DebugAPI{api: api} 1301 } 1302 1303 // SetHead rewinds the head of the blockchain to a previous block. 1304 func (api *DebugAPI) SetHead(number hexutil.Uint64) { 1305 api.api.BlockChain().SetHead(uint64(number)) 1306 } 1307 1308 func (debug *DebugAPI) GetAccount(ctx context.Context, address types.Address) { 1309 1310 } 1311 1312 // NetAPI offers network related RPC methods 1313 type NetAPI struct { 1314 api *API 1315 networkVersion uint64 1316 } 1317 1318 // NewNetAPI creates a new net API instance. 1319 func NewNetAPI(api *API, networkVersion uint64) *NetAPI { 1320 return &NetAPI{api, networkVersion} 1321 } 1322 1323 // Listening returns an indication if the node is listening for network connections. 1324 func (s *NetAPI) Listening() bool { 1325 return true // always listening 1326 } 1327 1328 // PeerCount returns the number of connected peers 1329 func (s *NetAPI) PeerCount() hexutil.Uint { 1330 //return hexutil.Uint(s.api.P2pServer().PeerCount()) 1331 return 0 1332 } 1333 1334 // Version returns the current ethereum protocol version. 1335 func (s *NetAPI) Version() string { 1336 //todo networkID == chainID? s.api.GetChainConfig().ChainID 1337 return fmt.Sprintf("%d", s.networkVersion) 1338 } 1339 1340 // TxsPoolAPI offers and API for the transaction pool. It only operates on data that is non confidential. 1341 type TxsPoolAPI struct { 1342 api *API 1343 } 1344 1345 // NewTxsPoolAPI creates a new tx pool service that gives information about the transaction pool. 1346 func NewTxsPoolAPI(api *API) *TxsPoolAPI { 1347 return &TxsPoolAPI{api} 1348 } 1349 1350 // Content returns the transactions contained within the transaction pool. 1351 func (s *TxsPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { 1352 content := map[string]map[string]map[string]*RPCTransaction{ 1353 "pending": make(map[string]map[string]*RPCTransaction), 1354 "queued": make(map[string]map[string]*RPCTransaction), 1355 } 1356 pending, queue := s.api.TxsPool().Content() 1357 curHeader := s.api.BlockChain().CurrentBlock().Header() 1358 // Flatten the pending transactions 1359 for account, txs := range pending { 1360 dump := make(map[string]*RPCTransaction) 1361 for _, tx := range txs { 1362 dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader) 1363 } 1364 content["pending"][mvm_types.FromAmcAddress(&account).Hex()] = dump 1365 } 1366 // Flatten the queued transactions 1367 for account, txs := range queue { 1368 dump := make(map[string]*RPCTransaction) 1369 for _, tx := range txs { 1370 dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader) 1371 } 1372 content["queued"][mvm_types.FromAmcAddress(&account).Hex()] = dump 1373 } 1374 return content 1375 } 1376 1377 func (api *TransactionAPI) TestBatchTxs(ctx context.Context) { 1378 go batchTxs(api.api, 0, 1000000) 1379 } 1380 1381 func batchTxs(api *API, start, end uint64) error { 1382 var ( 1383 key, _ = crypto.HexToECDSA("d6d8d19bd786d6676819b806694b1100a4414a94e51e9a82a351bd8f7f3f3658") 1384 addr = crypto.PubkeyToAddress(key.PublicKey) 1385 signer = new(transaction.HomesteadSigner) 1386 content = context.Background() 1387 ) 1388 1389 for i := start; i < end; i++ { 1390 tx, _ := transaction.SignTx(transaction.NewTx( 1391 &transaction.LegacyTx{ 1392 Nonce: uint64(i), 1393 Value: uint256.NewInt(params.Wei), 1394 Gas: params.TxGas, 1395 To: &addr, 1396 GasPrice: uint256.NewInt(params.GWei), 1397 Data: nil}, 1398 ), signer, key) 1399 tx.SetFrom(addr) 1400 _, err := SubmitTransaction(content, api, tx) 1401 if nil != err { 1402 return err 1403 } 1404 } 1405 return nil 1406 }