github.com/klaytn/klaytn@v1.10.2/api/api_ethereum.go (about) 1 // Copyright 2021 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/binary" 23 "errors" 24 "fmt" 25 "math/big" 26 "strconv" 27 "strings" 28 "time" 29 30 "github.com/klaytn/klaytn/rlp" 31 32 "github.com/klaytn/klaytn/blockchain" 33 "github.com/klaytn/klaytn/blockchain/state" 34 "github.com/klaytn/klaytn/blockchain/types" 35 "github.com/klaytn/klaytn/blockchain/vm" 36 "github.com/klaytn/klaytn/common" 37 "github.com/klaytn/klaytn/common/hexutil" 38 "github.com/klaytn/klaytn/common/math" 39 "github.com/klaytn/klaytn/crypto" 40 "github.com/klaytn/klaytn/governance" 41 "github.com/klaytn/klaytn/networks/rpc" 42 "github.com/klaytn/klaytn/node/cn/filters" 43 "github.com/klaytn/klaytn/params" 44 ) 45 46 const ( 47 // EmptySha3Uncles always have value which is the result of 48 // `crypto.Keccak256Hash(rlp.EncodeToBytes([]*types.Header(nil)).String())` 49 // because there is no uncles in Klaytn. 50 // Just use const value because we don't have to calculate it everytime which always be same result. 51 EmptySha3Uncles = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 52 // ZeroHashrate exists for supporting Ethereum compatible data structure. 53 // There is no POW mining mechanism in Klaytn. 54 ZeroHashrate uint64 = 0 55 // ZeroUncleCount is always zero because there is no uncle blocks in Klaytn. 56 ZeroUncleCount uint = 0 57 ) 58 59 var ( 60 errNoMiningWork = errors.New("no mining work available yet") 61 errNotFoundBlock = errors.New("can't find a block in database") 62 ) 63 64 // EthereumAPI provides an API to access the Klaytn through the `eth` namespace. 65 // TODO-Klaytn: Removed unused variable 66 type EthereumAPI struct { 67 publicFilterAPI *filters.PublicFilterAPI 68 governanceKlayAPI *governance.GovernanceKlayAPI 69 70 publicKlayAPI *PublicKlayAPI 71 publicBlockChainAPI *PublicBlockChainAPI 72 publicTransactionPoolAPI *PublicTransactionPoolAPI 73 publicAccountAPI *PublicAccountAPI 74 publicGovernanceAPI *governance.PublicGovernanceAPI 75 } 76 77 // NewEthereumAPI creates a new ethereum API. 78 // EthereumAPI operates using Klaytn's API internally without overriding. 79 // Therefore, it is necessary to use APIs defined in two different packages(cn and api), 80 // so those apis will be defined through a setter. 81 func NewEthereumAPI() *EthereumAPI { 82 return &EthereumAPI{nil, nil, nil, nil, nil, nil, nil} 83 } 84 85 // SetPublicFilterAPI sets publicFilterAPI 86 func (api *EthereumAPI) SetPublicFilterAPI(publicFilterAPI *filters.PublicFilterAPI) { 87 api.publicFilterAPI = publicFilterAPI 88 } 89 90 // SetGovernanceKlayAPI sets governanceKlayAPI 91 func (api *EthereumAPI) SetGovernanceKlayAPI(governanceKlayAPI *governance.GovernanceKlayAPI) { 92 api.governanceKlayAPI = governanceKlayAPI 93 } 94 95 // SetPublicKlayAPI sets publicKlayAPI 96 func (api *EthereumAPI) SetPublicKlayAPI(publicKlayAPI *PublicKlayAPI) { 97 api.publicKlayAPI = publicKlayAPI 98 } 99 100 // SetPublicBlockChainAPI sets publicBlockChainAPI 101 func (api *EthereumAPI) SetPublicBlockChainAPI(publicBlockChainAPI *PublicBlockChainAPI) { 102 api.publicBlockChainAPI = publicBlockChainAPI 103 } 104 105 // SetPublicTransactionPoolAPI sets publicTransactionPoolAPI 106 func (api *EthereumAPI) SetPublicTransactionPoolAPI(publicTransactionPoolAPI *PublicTransactionPoolAPI) { 107 api.publicTransactionPoolAPI = publicTransactionPoolAPI 108 } 109 110 // SetPublicAccountAPI sets publicAccountAPI 111 func (api *EthereumAPI) SetPublicAccountAPI(publicAccountAPI *PublicAccountAPI) { 112 api.publicAccountAPI = publicAccountAPI 113 } 114 115 // SetPublicGovernanceAPI sets publicGovernanceAPI 116 func (api *EthereumAPI) SetPublicGovernanceAPI(publicGovernanceAPI *governance.PublicGovernanceAPI) { 117 api.publicGovernanceAPI = publicGovernanceAPI 118 } 119 120 // Etherbase is the address of operating node. 121 // Unlike Ethereum, it only returns the node address because Klaytn does not have a POW mechanism. 122 func (api *EthereumAPI) Etherbase() (common.Address, error) { 123 return api.publicGovernanceAPI.NodeAddress(), nil 124 } 125 126 // Coinbase is the address of operating node (alias for Etherbase). 127 func (api *EthereumAPI) Coinbase() (common.Address, error) { 128 return api.Etherbase() 129 } 130 131 // Hashrate returns the POW hashrate. 132 // Unlike Ethereum, it always returns ZeroHashrate because Klaytn does not have a POW mechanism. 133 func (api *EthereumAPI) Hashrate() hexutil.Uint64 { 134 return hexutil.Uint64(ZeroHashrate) 135 } 136 137 // Mining returns an indication if this node is currently mining. 138 // Unlike Ethereum, it always returns false because Klaytn does not have a POW mechanism, 139 func (api *EthereumAPI) Mining() bool { 140 return false 141 } 142 143 // GetWork returns an errNoMiningWork because klaytn does not have a POW mechanism. 144 func (api *EthereumAPI) GetWork() ([4]string, error) { 145 return [4]string{}, errNoMiningWork 146 } 147 148 // A BlockNonce is a 64-bit hash which proves (combined with the 149 // mix-hash) that a sufficient amount of computation has been carried 150 // out on a block. 151 type BlockNonce [8]byte 152 153 // EncodeNonce converts the given integer to a block nonce. 154 func EncodeNonce(i uint64) BlockNonce { 155 var n BlockNonce 156 binary.BigEndian.PutUint64(n[:], i) 157 return n 158 } 159 160 // Uint64 returns the integer value of a block nonce. 161 func (n BlockNonce) Uint64() uint64 { 162 return binary.BigEndian.Uint64(n[:]) 163 } 164 165 // MarshalText encodes n as a hex string with 0x prefix. 166 func (n BlockNonce) MarshalText() ([]byte, error) { 167 return hexutil.Bytes(n[:]).MarshalText() 168 } 169 170 // UnmarshalText implements encoding.TextUnmarshaler. 171 func (n *BlockNonce) UnmarshalText(input []byte) error { 172 return hexutil.UnmarshalFixedText("BlockNonce", input, n[:]) 173 } 174 175 // SubmitWork returns false because klaytn does not have a POW mechanism. 176 func (api *EthereumAPI) SubmitWork(nonce BlockNonce, hash, digest common.Hash) bool { 177 return false 178 } 179 180 // SubmitHashrate returns false because klaytn does not have a POW mechanism. 181 func (api *EthereumAPI) SubmitHashrate(rate hexutil.Uint64, id common.Hash) bool { 182 return false 183 } 184 185 // GetHashrate returns ZeroHashrate because klaytn does not have a POW mechanism. 186 func (api *EthereumAPI) GetHashrate() uint64 { 187 return ZeroHashrate 188 } 189 190 // NewPendingTransactionFilter creates a filter that fetches pending transaction hashes 191 // as transactions enter the pending state. 192 // 193 // It is part of the filter package because this filter can be used through the 194 // `eth_getFilterChanges` polling method that is also used for log filters. 195 // 196 // https://eth.wiki/json-rpc/API#eth_newpendingtransactionfilter 197 func (api *EthereumAPI) NewPendingTransactionFilter() rpc.ID { 198 return api.publicFilterAPI.NewPendingTransactionFilter() 199 } 200 201 // NewPendingTransactions creates a subscription that is triggered each time a transaction 202 // enters the transaction pool and was signed from one of the transactions this nodes manages. 203 func (api *EthereumAPI) NewPendingTransactions(ctx context.Context) (*rpc.Subscription, error) { 204 return api.publicFilterAPI.NewPendingTransactions(ctx) 205 } 206 207 // NewBlockFilter creates a filter that fetches blocks that are imported into the chain. 208 // It is part of the filter package since polling goes with eth_getFilterChanges. 209 // 210 // https://eth.wiki/json-rpc/API#eth_newblockfilter 211 func (api *EthereumAPI) NewBlockFilter() rpc.ID { 212 return api.publicFilterAPI.NewBlockFilter() 213 } 214 215 // NewHeads send a notification each time a new (header) block is appended to the chain. 216 func (api *EthereumAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) { 217 notifier, supported := rpc.NotifierFromContext(ctx) 218 if !supported { 219 return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported 220 } 221 222 rpcSub := notifier.CreateSubscription() 223 go func() { 224 headers := make(chan *types.Header) 225 headersSub := api.publicFilterAPI.Events().SubscribeNewHeads(headers) 226 227 for { 228 select { 229 case h := <-headers: 230 header, err := api.rpcMarshalHeader(h) 231 if err != nil { 232 logger.Error("Failed to marshal header during newHeads subscription", "err", err) 233 headersSub.Unsubscribe() 234 return 235 } 236 notifier.Notify(rpcSub.ID, header) 237 case <-rpcSub.Err(): 238 headersSub.Unsubscribe() 239 return 240 case <-notifier.Closed(): 241 headersSub.Unsubscribe() 242 return 243 } 244 } 245 }() 246 247 return rpcSub, nil 248 } 249 250 // Logs creates a subscription that fires for all new log that match the given filter criteria. 251 func (api *EthereumAPI) Logs(ctx context.Context, crit filters.FilterCriteria) (*rpc.Subscription, error) { 252 return api.publicFilterAPI.Logs(ctx, crit) 253 } 254 255 // NewFilter creates a new filter and returns the filter id. It can be 256 // used to retrieve logs when the state changes. This method cannot be 257 // used to fetch logs that are already stored in the state. 258 // 259 // Default criteria for the from and to block are "latest". 260 // Using "latest" as block number will return logs for mined blocks. 261 // Using "pending" as block number returns logs for not yet mined (pending) blocks. 262 // In case logs are removed (chain reorg) previously returned logs are returned 263 // again but with the removed property set to true. 264 // 265 // In case "fromBlock" > "toBlock" an error is returned. 266 // 267 // https://eth.wiki/json-rpc/API#eth_newfilter 268 func (api *EthereumAPI) NewFilter(crit filters.FilterCriteria) (rpc.ID, error) { 269 return api.publicFilterAPI.NewFilter(crit) 270 } 271 272 // GetLogs returns logs matching the given argument that are stored within the state. 273 // 274 // https://eth.wiki/json-rpc/API#eth_getlogs 275 func (api *EthereumAPI) GetLogs(ctx context.Context, crit filters.FilterCriteria) ([]*types.Log, error) { 276 return api.publicFilterAPI.GetLogs(ctx, crit) 277 } 278 279 // UninstallFilter removes the filter with the given filter id. 280 // 281 // https://eth.wiki/json-rpc/API#eth_uninstallfilter 282 func (api *EthereumAPI) UninstallFilter(id rpc.ID) bool { 283 return api.publicFilterAPI.UninstallFilter(id) 284 } 285 286 // GetFilterLogs returns the logs for the filter with the given id. 287 // If the filter could not be found an empty array of logs is returned. 288 // 289 // https://eth.wiki/json-rpc/API#eth_getfilterlogs 290 func (api *EthereumAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Log, error) { 291 return api.publicFilterAPI.GetFilterLogs(ctx, id) 292 } 293 294 // GetFilterChanges returns the logs for the filter with the given id since 295 // last time it was called. This can be used for polling. 296 // 297 // For pending transaction and block filters the result is []common.Hash. 298 // (pending)Log filters return []Log. 299 // 300 // https://eth.wiki/json-rpc/API#eth_getfilterchanges 301 func (api *EthereumAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { 302 return api.publicFilterAPI.GetFilterChanges(id) 303 } 304 305 // GasPrice returns a suggestion for a gas price. 306 func (api *EthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) { 307 return api.publicKlayAPI.GasPrice(ctx) 308 } 309 310 func (api *EthereumAPI) UpperBoundGasPrice(ctx context.Context) *hexutil.Big { 311 return (*hexutil.Big)(api.publicKlayAPI.UpperBoundGasPrice(ctx)) 312 } 313 314 func (api *EthereumAPI) LowerBoundGasPrice(ctx context.Context) *hexutil.Big { 315 return (*hexutil.Big)(api.publicKlayAPI.LowerBoundGasPrice(ctx)) 316 } 317 318 // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. 319 func (api *EthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) { 320 return api.GasPrice(ctx) 321 } 322 323 // DecimalOrHex unmarshals a non-negative decimal or hex parameter into a uint64. 324 type DecimalOrHex uint64 325 326 // UnmarshalJSON implements json.Unmarshaler. 327 func (dh *DecimalOrHex) UnmarshalJSON(data []byte) error { 328 input := strings.TrimSpace(string(data)) 329 if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' { 330 input = input[1 : len(input)-1] 331 } 332 333 value, err := strconv.ParseUint(input, 10, 64) 334 if err != nil { 335 value, err = hexutil.DecodeUint64(input) 336 } 337 if err != nil { 338 return err 339 } 340 *dh = DecimalOrHex(value) 341 return nil 342 } 343 344 func (api *EthereumAPI) FeeHistory(ctx context.Context, blockCount DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*FeeHistoryResult, error) { 345 return api.publicKlayAPI.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) 346 } 347 348 // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not 349 // yet received the latest block headers from its pears. In case it is synchronizing: 350 // - startingBlock: block number this node started to synchronise from 351 // - currentBlock: block number this node is currently importing 352 // - highestBlock: block number of the highest block header this node has received from peers 353 // - pulledStates: number of state entries processed until now 354 // - knownStates: number of known state entries that still need to be pulled 355 func (api *EthereumAPI) Syncing() (interface{}, error) { 356 return api.publicKlayAPI.Syncing() 357 } 358 359 // ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. 360 func (api *EthereumAPI) ChainId() (*hexutil.Big, error) { 361 return api.publicBlockChainAPI.ChainId(), nil 362 } 363 364 // BlockNumber returns the block number of the chain head. 365 func (api *EthereumAPI) BlockNumber() hexutil.Uint64 { 366 return api.publicBlockChainAPI.BlockNumber() 367 } 368 369 // GetBalance returns the amount of wei for the given address in the state of the 370 // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta 371 // block numbers are also allowed. 372 func (api *EthereumAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) { 373 return api.publicBlockChainAPI.GetBalance(ctx, address, blockNrOrHash) 374 } 375 376 // EthAccountResult structs for GetProof 377 // AccountResult in go-ethereum has been renamed to EthAccountResult. 378 // AccountResult is defined in go-ethereum's internal package, so AccountResult is redefined here as EthAccountResult. 379 type EthAccountResult struct { 380 Address common.Address `json:"address"` 381 AccountProof []string `json:"accountProof"` 382 Balance *hexutil.Big `json:"balance"` 383 CodeHash common.Hash `json:"codeHash"` 384 Nonce hexutil.Uint64 `json:"nonce"` 385 StorageHash common.Hash `json:"storageHash"` 386 StorageProof []EthStorageResult `json:"storageProof"` 387 } 388 389 // StorageResult in go-ethereum has been renamed to EthStorageResult. 390 // StorageResult is defined in go-ethereum's internal package, so StorageResult is redefined here as EthStorageResult. 391 type EthStorageResult struct { 392 Key string `json:"key"` 393 Value *hexutil.Big `json:"value"` 394 Proof []string `json:"proof"` 395 } 396 397 // GetProof returns the Merkle-proof for a given account and optionally some storage keys. 398 // This feature is not supported in Klaytn yet. It just returns account information from state trie. 399 func (api *EthereumAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*EthAccountResult, error) { 400 state, _, err := api.publicKlayAPI.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 401 if state == nil || err != nil { 402 return nil, err 403 } 404 storageTrie := state.StorageTrie(address) 405 storageHash := types.EmptyRootHashOriginal 406 codeHash := state.GetCodeHash(address) 407 storageProof := make([]EthStorageResult, len(storageKeys)) 408 409 // if we have a storageTrie, (which means the account exists), we can update the storagehash 410 if storageTrie != nil { 411 storageHash = storageTrie.Hash() 412 } else { 413 // no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray. 414 codeHash = crypto.Keccak256Hash(nil) 415 } 416 417 return &EthAccountResult{ 418 Address: address, 419 AccountProof: []string{}, 420 Balance: (*hexutil.Big)(state.GetBalance(address)), 421 CodeHash: codeHash, 422 Nonce: hexutil.Uint64(state.GetNonce(address)), 423 StorageHash: storageHash, 424 StorageProof: storageProof, 425 }, state.Error() 426 } 427 428 // GetHeaderByNumber returns the requested canonical block header. 429 // * When blockNr is -1 the chain head is returned. 430 // * When blockNr is -2 the pending chain head is returned. 431 func (api *EthereumAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) { 432 // In Ethereum, err is always nil because the backend of Ethereum always return nil. 433 klaytnHeader, err := api.publicBlockChainAPI.b.HeaderByNumber(ctx, number) 434 if err != nil { 435 if strings.Contains(err.Error(), "does not exist") { 436 return nil, nil 437 } 438 return nil, err 439 } 440 response, err := api.rpcMarshalHeader(klaytnHeader) 441 if err != nil { 442 return nil, err 443 } 444 if number == rpc.PendingBlockNumber { 445 // Pending header need to nil out a few fields 446 for _, field := range []string{"hash", "nonce", "miner"} { 447 response[field] = nil 448 } 449 } 450 return response, nil 451 } 452 453 // GetHeaderByHash returns the requested header by hash. 454 func (api *EthereumAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} { 455 // In Ethereum, err is always nil because the backend of Ethereum always return nil. 456 klaytnHeader, _ := api.publicBlockChainAPI.b.HeaderByHash(ctx, hash) 457 if klaytnHeader != nil { 458 response, err := api.rpcMarshalHeader(klaytnHeader) 459 if err != nil { 460 return nil 461 } 462 return response 463 } 464 return nil 465 } 466 467 // GetBlockByNumber returns the requested canonical block. 468 // * When blockNr is -1 the chain head is returned. 469 // * When blockNr is -2 the pending chain head is returned. 470 // * When fullTx is true all transactions in the block are returned, otherwise 471 // only the transaction hash is returned. 472 func (api *EthereumAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { 473 // Klaytn backend returns error when there is no matched block but 474 // Ethereum returns it as nil without error, so we should return is as nil when there is no matched block. 475 klaytnBlock, err := api.publicBlockChainAPI.b.BlockByNumber(ctx, number) 476 if err != nil { 477 if strings.Contains(err.Error(), "does not exist") { 478 return nil, nil 479 } 480 return nil, err 481 } 482 response, err := api.rpcMarshalBlock(klaytnBlock, true, fullTx) 483 if err == nil && number == rpc.PendingBlockNumber { 484 // Pending blocks need to nil out a few fields 485 for _, field := range []string{"hash", "nonce", "miner"} { 486 response[field] = nil 487 } 488 } 489 return response, err 490 } 491 492 // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full 493 // detail, otherwise only the transaction hash is returned. 494 func (api *EthereumAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) { 495 // Klaytn backend returns error when there is no matched block but 496 // Ethereum returns it as nil without error, so we should return is as nil when there is no matched block. 497 klaytnBlock, err := api.publicBlockChainAPI.b.BlockByHash(ctx, hash) 498 if err != nil { 499 if strings.Contains(err.Error(), "does not exist") { 500 return nil, nil 501 } 502 return nil, err 503 } 504 return api.rpcMarshalBlock(klaytnBlock, true, fullTx) 505 } 506 507 // GetUncleByBlockNumberAndIndex returns nil because there is no uncle block in Klaytn. 508 func (api *EthereumAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) { 509 return nil, nil 510 } 511 512 // GetUncleByBlockHashAndIndex returns nil because there is no uncle block in Klaytn. 513 func (api *EthereumAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) { 514 return nil, nil 515 } 516 517 // GetUncleCountByBlockNumber returns 0 when given blockNr exists because there is no uncle block in Klaytn. 518 func (api *EthereumAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { 519 if block, _ := api.publicBlockChainAPI.b.BlockByNumber(ctx, blockNr); block != nil { 520 n := hexutil.Uint(ZeroUncleCount) 521 return &n 522 } 523 return nil 524 } 525 526 // GetUncleCountByBlockHash returns 0 when given blockHash exists because there is no uncle block in Klaytn. 527 func (api *EthereumAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { 528 if block, _ := api.publicBlockChainAPI.b.BlockByHash(ctx, blockHash); block != nil { 529 n := hexutil.Uint(ZeroUncleCount) 530 return &n 531 } 532 return nil 533 } 534 535 // GetCode returns the code stored at the given address in the state for the given block number. 536 func (api *EthereumAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { 537 return api.publicBlockChainAPI.GetCode(ctx, address, blockNrOrHash) 538 } 539 540 // GetStorageAt returns the storage from the state at the given address, key and 541 // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block 542 // numbers are also allowed. 543 func (api *EthereumAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { 544 return api.publicBlockChainAPI.GetStorageAt(ctx, address, key, blockNrOrHash) 545 } 546 547 // EthOverrideAccount indicates the overriding fields of account during the execution 548 // of a message call. 549 // Note, state and stateDiff can't be specified at the same time. If state is 550 // set, message execution will only use the data in the given state. Otherwise 551 // if statDiff is set, all diff will be applied first and then execute the call 552 // message. 553 // OverrideAccount in go-ethereum has been renamed to EthOverrideAccount. 554 // OverrideAccount is defined in go-ethereum's internal package, so OverrideAccount is redefined here as EthOverrideAccount. 555 type EthOverrideAccount struct { 556 Nonce *hexutil.Uint64 `json:"nonce"` 557 Code *hexutil.Bytes `json:"code"` 558 Balance **hexutil.Big `json:"balance"` 559 State *map[common.Hash]common.Hash `json:"state"` 560 StateDiff *map[common.Hash]common.Hash `json:"stateDiff"` 561 } 562 563 // EthStateOverride is the collection of overridden accounts. 564 // StateOverride in go-ethereum has been renamed to EthStateOverride. 565 // StateOverride is defined in go-ethereum's internal package, so StateOverride is redefined here as EthStateOverride. 566 type EthStateOverride map[common.Address]EthOverrideAccount 567 568 func (diff *EthStateOverride) Apply(state *state.StateDB) error { 569 if diff == nil { 570 return nil 571 } 572 for addr, account := range *diff { 573 // Override account nonce. 574 if account.Nonce != nil { 575 state.SetNonce(addr, uint64(*account.Nonce)) 576 } 577 // Override account(contract) code. 578 if account.Code != nil { 579 state.SetCode(addr, *account.Code) 580 } 581 // Override account balance. 582 if account.Balance != nil { 583 state.SetBalance(addr, (*big.Int)(*account.Balance)) 584 } 585 if account.State != nil && account.StateDiff != nil { 586 return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex()) 587 } 588 // Replace entire state if caller requires. 589 if account.State != nil { 590 state.SetStorage(addr, *account.State) 591 } 592 // Apply state diff into specified accounts. 593 if account.StateDiff != nil { 594 for key, value := range *account.StateDiff { 595 state.SetState(addr, key, value) 596 } 597 } 598 } 599 return nil 600 } 601 602 // Call executes the given transaction on the state for the given block number. 603 // 604 // Additionally, the caller can specify a batch of contract for fields overriding. 605 // 606 // Note, this function doesn't make and changes in the state/blockchain and is 607 // useful to execute and retrieve values. 608 func (api *EthereumAPI) Call(ctx context.Context, args EthTransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *EthStateOverride) (hexutil.Bytes, error) { 609 bcAPI := api.publicBlockChainAPI.b 610 gasCap := uint64(0) 611 if rpcGasCap := bcAPI.RPCGasCap(); rpcGasCap != nil { 612 gasCap = rpcGasCap.Uint64() 613 } 614 result, _, status, err := EthDoCall(ctx, bcAPI, args, blockNrOrHash, overrides, bcAPI.RPCEVMTimeout(), gasCap) 615 if err != nil { 616 return nil, err 617 } 618 619 err = blockchain.GetVMerrFromReceiptStatus(status) 620 if err != nil && isReverted(err) && len(result) > 0 { 621 return nil, newRevertError(result) 622 } 623 return common.CopyBytes(result), err 624 } 625 626 // EstimateGas returns an estimate of the amount of gas needed to execute the 627 // given transaction against the current pending block. 628 func (api *EthereumAPI) EstimateGas(ctx context.Context, args EthTransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) { 629 bcAPI := api.publicBlockChainAPI.b 630 bNrOrHash := rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 631 if blockNrOrHash != nil { 632 bNrOrHash = *blockNrOrHash 633 } 634 gasCap := uint64(0) 635 if rpcGasCap := bcAPI.RPCGasCap(); rpcGasCap != nil { 636 gasCap = rpcGasCap.Uint64() 637 } 638 return EthDoEstimateGas(ctx, bcAPI, args, bNrOrHash, gasCap) 639 } 640 641 // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. 642 func (api *EthereumAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { 643 transactionCount, _ := api.publicTransactionPoolAPI.GetBlockTransactionCountByNumber(ctx, blockNr) 644 return transactionCount 645 } 646 647 // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. 648 func (api *EthereumAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { 649 transactionCount, _ := api.publicTransactionPoolAPI.GetBlockTransactionCountByHash(ctx, blockHash) 650 return transactionCount 651 } 652 653 // CreateAccessList creates a EIP-2930 type AccessList for the given transaction. 654 // Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state. 655 func (api *EthereumAPI) CreateAccessList(ctx context.Context, args EthTransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*AccessListResult, error) { 656 // To use CreateAccess of PublicBlockChainAPI, we need to convert the EthTransactionArgs to SendTxArgs. 657 // However, since SendTxArgs does not yet support MaxFeePerGas and MaxPriorityFeePerGas, the conversion logic is bound to be incomplete. 658 // Since this parameter is not actually used and currently only returns an empty result value, implement the logic to return an empty result separately, 659 // and later, when the API is actually implemented, add the relevant fields to SendTxArgs and call the function in PublicBlockChainAPI. 660 // TODO-Klaytn: Modify below logic to use api.publicBlockChainAPI.CreateAccessList 661 result := &AccessListResult{Accesslist: &types.AccessList{}, GasUsed: hexutil.Uint64(0)} 662 return result, nil 663 } 664 665 // EthRPCTransaction represents a transaction that will serialize to the RPC representation of a transaction 666 // RPCTransaction in go-ethereum has been renamed to EthRPCTransaction. 667 // RPCTransaction is defined in go-ethereum's internal package, so RPCTransaction is redefined here as EthRPCTransaction. 668 type EthRPCTransaction struct { 669 BlockHash *common.Hash `json:"blockHash"` 670 BlockNumber *hexutil.Big `json:"blockNumber"` 671 From common.Address `json:"from"` 672 Gas hexutil.Uint64 `json:"gas"` 673 GasPrice *hexutil.Big `json:"gasPrice"` 674 GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` 675 GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` 676 Hash common.Hash `json:"hash"` 677 Input hexutil.Bytes `json:"input"` 678 Nonce hexutil.Uint64 `json:"nonce"` 679 To *common.Address `json:"to"` 680 TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` 681 Value *hexutil.Big `json:"value"` 682 Type hexutil.Uint64 `json:"type"` 683 Accesses *types.AccessList `json:"accessList,omitempty"` 684 ChainID *hexutil.Big `json:"chainId,omitempty"` 685 V *hexutil.Big `json:"v"` 686 R *hexutil.Big `json:"r"` 687 S *hexutil.Big `json:"s"` 688 } 689 690 // ethTxJSON is the JSON representation of Ethereum transaction. 691 // ethTxJSON is used by eth namespace APIs which returns Transaction object as it is. 692 // Because every transaction in Klaytn, implements json.Marshaler interface (MarshalJSON), but 693 // it is marshaled for Klaytn format only. 694 // e.g. Ethereum transaction have V, R, and S field for signature but, 695 // Klaytn transaction have types.TxSignaturesJSON which includes array of signatures which is not 696 // applicable for Ethereum transaction. 697 type ethTxJSON struct { 698 Type hexutil.Uint64 `json:"type"` 699 700 // Common transaction fields: 701 Nonce *hexutil.Uint64 `json:"nonce"` 702 GasPrice *hexutil.Big `json:"gasPrice"` 703 MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` 704 MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` 705 Gas *hexutil.Uint64 `json:"gas"` 706 Value *hexutil.Big `json:"value"` 707 Data *hexutil.Bytes `json:"input"` 708 V *hexutil.Big `json:"v"` 709 R *hexutil.Big `json:"r"` 710 S *hexutil.Big `json:"s"` 711 To *common.Address `json:"to"` 712 713 // Access list transaction fields: 714 ChainID *hexutil.Big `json:"chainId,omitempty"` 715 AccessList *types.AccessList `json:"accessList,omitempty"` 716 717 // Only used for encoding: 718 Hash common.Hash `json:"hash"` 719 } 720 721 // newEthRPCTransactionFromBlockIndex creates an EthRPCTransaction from block and index parameters. 722 func newEthRPCTransactionFromBlockIndex(b *types.Block, index uint64) *EthRPCTransaction { 723 txs := b.Transactions() 724 if index >= uint64(len(txs)) { 725 logger.Error("invalid transaction index", "given index", index, "length of txs", len(txs)) 726 return nil 727 } 728 return newEthRPCTransaction(b, txs[index], b.Hash(), b.NumberU64(), index) 729 } 730 731 // newEthRPCTransactionFromBlockHash returns a transaction that will serialize to the RPC representation. 732 func newEthRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *EthRPCTransaction { 733 for idx, tx := range b.Transactions() { 734 if tx.Hash() == hash { 735 return newEthRPCTransactionFromBlockIndex(b, uint64(idx)) 736 } 737 } 738 return nil 739 } 740 741 // resolveToField returns value which fits to `to` field based on transaction types. 742 // This function is used when converting Klaytn transactions to Ethereum transaction types. 743 func resolveToField(tx *types.Transaction) *common.Address { 744 switch tx.Type() { 745 case types.TxTypeAccountUpdate, types.TxTypeFeeDelegatedAccountUpdate, types.TxTypeFeeDelegatedAccountUpdateWithRatio, 746 types.TxTypeCancel, types.TxTypeFeeDelegatedCancel, types.TxTypeFeeDelegatedCancelWithRatio, 747 types.TxTypeChainDataAnchoring, types.TxTypeFeeDelegatedChainDataAnchoring, types.TxTypeFeeDelegatedChainDataAnchoringWithRatio: 748 // These type of transactions actually do not have `to` address, but Ethereum always have `to` field, 749 // so we Klaytn developers decided to fill the `to` field with `from` address value in these case. 750 from := getFrom(tx) 751 return &from 752 } 753 return tx.To() 754 } 755 756 // newEthRPCTransaction creates an EthRPCTransaction from Klaytn transaction. 757 func newEthRPCTransaction(block *types.Block, tx *types.Transaction, blockHash common.Hash, blockNumber, index uint64) *EthRPCTransaction { 758 // When an unknown transaction is requested through rpc call, 759 // nil is returned by Klaytn API, and it is handled. 760 if tx == nil { 761 return nil 762 } 763 764 typeInt := tx.Type() 765 // If tx is not Ethereum transaction, the type is converted to TxTypeLegacyTransaction. 766 if !tx.IsEthereumTransaction() { 767 typeInt = types.TxTypeLegacyTransaction 768 } 769 770 signature := tx.GetTxInternalData().RawSignatureValues()[0] 771 772 result := &EthRPCTransaction{ 773 Type: hexutil.Uint64(byte(typeInt)), 774 From: getFrom(tx), 775 Gas: hexutil.Uint64(tx.Gas()), 776 GasPrice: (*hexutil.Big)(tx.GasPrice()), 777 Hash: tx.Hash(), 778 Input: tx.Data(), 779 Nonce: hexutil.Uint64(tx.Nonce()), 780 To: resolveToField(tx), 781 Value: (*hexutil.Big)(tx.Value()), 782 V: (*hexutil.Big)(signature.V), 783 R: (*hexutil.Big)(signature.R), 784 S: (*hexutil.Big)(signature.S), 785 } 786 787 if blockHash != (common.Hash{}) { 788 result.BlockHash = &blockHash 789 result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) 790 result.TransactionIndex = (*hexutil.Uint64)(&index) 791 } 792 793 switch typeInt { 794 case types.TxTypeEthereumAccessList: 795 al := tx.AccessList() 796 result.Accesses = &al 797 result.ChainID = (*hexutil.Big)(tx.ChainId()) 798 case types.TxTypeEthereumDynamicFee: 799 al := tx.AccessList() 800 result.Accesses = &al 801 result.ChainID = (*hexutil.Big)(tx.ChainId()) 802 result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) 803 result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) 804 if block != nil { 805 result.GasPrice = (*hexutil.Big)(tx.EffectiveGasPrice(block.Header())) 806 } else { 807 // transaction is not processed yet 808 result.GasPrice = (*hexutil.Big)(tx.EffectiveGasPrice(nil)) 809 } 810 } 811 return result 812 } 813 814 // newEthRPCPendingTransaction creates an EthRPCTransaction for pending tx. 815 func newEthRPCPendingTransaction(tx *types.Transaction) *EthRPCTransaction { 816 return newEthRPCTransaction(nil, tx, common.Hash{}, 0, 0) 817 } 818 819 // formatTxToEthTxJSON formats types.Transaction to ethTxJSON. 820 // Use this function for only Ethereum typed transaction. 821 func formatTxToEthTxJSON(tx *types.Transaction) *ethTxJSON { 822 var enc ethTxJSON 823 824 enc.Type = hexutil.Uint64(byte(tx.Type())) 825 // If tx is not Ethereum transaction, the type is converted to TxTypeLegacyTransaction. 826 if !tx.IsEthereumTransaction() { 827 enc.Type = hexutil.Uint64(types.TxTypeLegacyTransaction) 828 } 829 enc.Hash = tx.Hash() 830 signature := tx.GetTxInternalData().RawSignatureValues()[0] 831 // Initialize signature values when it is nil. 832 if signature.V == nil { 833 signature.V = new(big.Int) 834 } 835 if signature.R == nil { 836 signature.R = new(big.Int) 837 } 838 if signature.S == nil { 839 signature.S = new(big.Int) 840 } 841 nonce := tx.Nonce() 842 gas := tx.Gas() 843 enc.Nonce = (*hexutil.Uint64)(&nonce) 844 enc.Gas = (*hexutil.Uint64)(&gas) 845 enc.Value = (*hexutil.Big)(tx.Value()) 846 data := tx.Data() 847 enc.Data = (*hexutil.Bytes)(&data) 848 enc.To = tx.To() 849 enc.V = (*hexutil.Big)(signature.V) 850 enc.R = (*hexutil.Big)(signature.R) 851 enc.S = (*hexutil.Big)(signature.S) 852 853 switch tx.Type() { 854 case types.TxTypeEthereumAccessList: 855 al := tx.AccessList() 856 enc.AccessList = &al 857 enc.ChainID = (*hexutil.Big)(tx.ChainId()) 858 enc.GasPrice = (*hexutil.Big)(tx.GasPrice()) 859 case types.TxTypeEthereumDynamicFee: 860 al := tx.AccessList() 861 enc.AccessList = &al 862 enc.ChainID = (*hexutil.Big)(tx.ChainId()) 863 enc.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) 864 enc.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) 865 default: 866 enc.GasPrice = (*hexutil.Big)(tx.GasPrice()) 867 } 868 return &enc 869 } 870 871 // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index. 872 func (api *EthereumAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *EthRPCTransaction { 873 block, err := api.publicTransactionPoolAPI.b.BlockByNumber(ctx, blockNr) 874 if err != nil { 875 return nil 876 } 877 878 return newEthRPCTransactionFromBlockIndex(block, uint64(index)) 879 } 880 881 // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. 882 func (api *EthereumAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *EthRPCTransaction { 883 block, err := api.publicTransactionPoolAPI.b.BlockByHash(ctx, blockHash) 884 if err != nil || block == nil { 885 return nil 886 } 887 return newEthRPCTransactionFromBlockIndex(block, uint64(index)) 888 } 889 890 // GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index. 891 func (api *EthereumAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes { 892 rawTx, err := api.publicTransactionPoolAPI.GetRawTransactionByBlockNumberAndIndex(ctx, blockNr, index) 893 if err != nil { 894 return nil 895 } 896 if rawTx[0] == byte(types.EthereumTxTypeEnvelope) { 897 rawTx = rawTx[1:] 898 } 899 return rawTx 900 } 901 902 // GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index. 903 func (api *EthereumAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes { 904 rawTx, err := api.publicTransactionPoolAPI.GetRawTransactionByBlockHashAndIndex(ctx, blockHash, index) 905 if err != nil { 906 return nil 907 } 908 if rawTx[0] == byte(types.EthereumTxTypeEnvelope) { 909 rawTx = rawTx[1:] 910 } 911 return rawTx 912 } 913 914 // GetTransactionCount returns the number of transactions the given address has sent for the given block number. 915 func (api *EthereumAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) { 916 return api.publicTransactionPoolAPI.GetTransactionCount(ctx, address, blockNrOrHash) 917 } 918 919 // GetTransactionByHash returns the transaction for the given hash. 920 func (api *EthereumAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*EthRPCTransaction, error) { 921 txpoolAPI := api.publicTransactionPoolAPI.b 922 923 // Try to return an already finalized transaction 924 if tx, blockHash, blockNumber, index := txpoolAPI.ChainDB().ReadTxAndLookupInfo(hash); tx != nil { 925 block, err := txpoolAPI.BlockByHash(ctx, blockHash) 926 if err != nil { 927 return nil, err 928 } 929 if block == nil { 930 return nil, errNotFoundBlock 931 } 932 return newEthRPCTransaction(block, tx, blockHash, blockNumber, index), nil 933 } 934 // No finalized transaction, try to retrieve it from the pool 935 if tx := txpoolAPI.GetPoolTransaction(hash); tx != nil { 936 return newEthRPCPendingTransaction(tx), nil 937 } 938 // Transaction unknown, return as such 939 return nil, nil 940 } 941 942 // GetRawTransactionByHash returns the bytes of the transaction for the given hash. 943 func (api *EthereumAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { 944 rawTx, err := api.publicTransactionPoolAPI.GetRawTransactionByHash(ctx, hash) 945 if err != nil { 946 return nil, err 947 } 948 if rawTx[0] == byte(types.EthereumTxTypeEnvelope) { 949 return rawTx[1:], nil 950 } 951 return rawTx, nil 952 } 953 954 // GetTransactionReceipt returns the transaction receipt for the given transaction hash. 955 func (api *EthereumAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { 956 txpoolAPI := api.publicTransactionPoolAPI.b 957 958 // Formats return Klaytn Transaction Receipt to the Ethereum Transaction Receipt. 959 tx, blockHash, blockNumber, index, receipt := txpoolAPI.GetTxLookupInfoAndReceipt(ctx, hash) 960 961 if tx == nil { 962 return nil, nil 963 } 964 receipts := txpoolAPI.GetBlockReceipts(ctx, blockHash) 965 cumulativeGasUsed := uint64(0) 966 for i := uint64(0); i <= index; i++ { 967 cumulativeGasUsed += receipts[i].GasUsed 968 } 969 970 // No error handling is required here. 971 // Header is checked in the following newEthTransactionReceipt function 972 header, _ := txpoolAPI.HeaderByHash(ctx, blockHash) 973 974 ethTx, err := newEthTransactionReceipt(header, tx, txpoolAPI, blockHash, blockNumber, index, cumulativeGasUsed, receipt) 975 if err != nil { 976 return nil, err 977 } 978 return ethTx, nil 979 } 980 981 // newEthTransactionReceipt creates a transaction receipt in Ethereum format. 982 func newEthTransactionReceipt(header *types.Header, tx *types.Transaction, b Backend, blockHash common.Hash, blockNumber, index, cumulativeGasUsed uint64, receipt *types.Receipt) (map[string]interface{}, error) { 983 // When an unknown transaction receipt is requested through rpc call, 984 // nil is returned by Klaytn API, and it is handled. 985 if tx == nil || receipt == nil { 986 return nil, nil 987 } 988 989 typeInt := tx.Type() 990 // If tx is not Ethereum transaction, the type is converted to TxTypeLegacyTransaction. 991 if !tx.IsEthereumTransaction() { 992 typeInt = types.TxTypeLegacyTransaction 993 } 994 995 fields := map[string]interface{}{ 996 "blockHash": blockHash, 997 "blockNumber": hexutil.Uint64(blockNumber), 998 "transactionHash": tx.Hash(), 999 "transactionIndex": hexutil.Uint64(index), 1000 "from": getFrom(tx), 1001 "to": resolveToField(tx), 1002 "gasUsed": hexutil.Uint64(receipt.GasUsed), 1003 "cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed), 1004 "contractAddress": nil, 1005 "logs": receipt.Logs, 1006 "logsBloom": receipt.Bloom, 1007 "type": hexutil.Uint(byte(typeInt)), 1008 } 1009 1010 // After Magma hard fork : return header.baseFee 1011 // After EthTxType hard fork : use zero baseFee to calculate effective gas price for EthereumDynamicFeeTx : 1012 // return gas price of tx. 1013 // Before EthTxType hard fork : return gas price of tx. (typed ethereum txs are not available.) 1014 fields["effectiveGasPrice"] = hexutil.Uint64(tx.EffectiveGasPrice(header).Uint64()) 1015 1016 // Always use the "status" field and Ignore the "root" field. 1017 if receipt.Status != types.ReceiptStatusSuccessful { 1018 // In Ethereum, status field can have 0(=Failure) or 1(=Success) only. 1019 fields["status"] = hexutil.Uint(types.ReceiptStatusFailed) 1020 } else { 1021 fields["status"] = hexutil.Uint(receipt.Status) 1022 } 1023 1024 if receipt.Logs == nil { 1025 fields["logs"] = [][]*types.Log{} 1026 } 1027 // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation 1028 if receipt.ContractAddress != (common.Address{}) { 1029 fields["contractAddress"] = receipt.ContractAddress 1030 } 1031 1032 return fields, nil 1033 } 1034 1035 // EthTransactionArgs represents the arguments to construct a new transaction 1036 // or a message call. 1037 // TransactionArgs in go-ethereum has been renamed to EthTransactionArgs. 1038 // TransactionArgs is defined in go-ethereum's internal package, so TransactionArgs is redefined here as EthTransactionArgs. 1039 type EthTransactionArgs struct { 1040 From *common.Address `json:"from"` 1041 To *common.Address `json:"to"` 1042 Gas *hexutil.Uint64 `json:"gas"` 1043 GasPrice *hexutil.Big `json:"gasPrice"` 1044 MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` 1045 MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` 1046 Value *hexutil.Big `json:"value"` 1047 Nonce *hexutil.Uint64 `json:"nonce"` 1048 1049 // We accept "data" and "input" for backwards-compatibility reasons. 1050 // "input" is the newer name and should be preferred by clients. 1051 // Issue detail: https://github.com/ethereum/go-ethereum/issues/15628 1052 Data *hexutil.Bytes `json:"data"` 1053 Input *hexutil.Bytes `json:"input"` 1054 1055 // Introduced by AccessListTxType transaction. 1056 AccessList *types.AccessList `json:"accessList,omitempty"` 1057 ChainID *hexutil.Big `json:"chainId,omitempty"` 1058 } 1059 1060 // from retrieves the transaction sender address. 1061 func (args *EthTransactionArgs) from() common.Address { 1062 if args.From == nil { 1063 return common.Address{} 1064 } 1065 return *args.From 1066 } 1067 1068 // data retrieves the transaction calldata. Input field is preferred. 1069 func (args *EthTransactionArgs) data() []byte { 1070 if args.Input != nil { 1071 return *args.Input 1072 } 1073 if args.Data != nil { 1074 return *args.Data 1075 } 1076 return nil 1077 } 1078 1079 // setDefaults fills in default values for unspecified tx fields. 1080 func (args *EthTransactionArgs) setDefaults(ctx context.Context, b Backend) error { 1081 if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { 1082 return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 1083 } 1084 // After london, default to 1559 uncles gasPrice is set 1085 head := b.CurrentBlock().Header() 1086 isMagma := head.BaseFee != nil 1087 1088 fixedBaseFee := new(big.Int).SetUint64(params.ZeroBaseFee) 1089 1090 // b.SuggestPrice = unitPrice, for before Magma 1091 // = baseFee, for after Magma 1092 gasPrice, err := b.SuggestPrice(ctx) 1093 if err != nil { 1094 return err 1095 } 1096 1097 // If user specifies both maxPriorityFee and maxFee, then we do not 1098 // need to consult the chain for defaults. It's definitely a London tx. 1099 if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil { 1100 if b.ChainConfig().IsEthTxTypeForkEnabled(head.Number) && args.GasPrice == nil { 1101 if args.MaxPriorityFeePerGas == nil { 1102 args.MaxPriorityFeePerGas = (*hexutil.Big)(gasPrice) 1103 } 1104 if args.MaxFeePerGas == nil { 1105 // Before Magma hard fork, `gasFeeCap` was set to `baseFee*2 + maxPriorityFeePerGas` by default. 1106 gasFeeCap := new(big.Int).Add( 1107 (*big.Int)(args.MaxPriorityFeePerGas), 1108 new(big.Int).Mul(fixedBaseFee, big.NewInt(2)), 1109 ) 1110 if isMagma { 1111 // After Magma hard fork, `gasFeeCap` was set to `baseFee*2` by default. 1112 gasFeeCap = gasPrice 1113 } 1114 args.MaxFeePerGas = (*hexutil.Big)(gasFeeCap) 1115 } 1116 if isMagma { 1117 if args.MaxFeePerGas.ToInt().Cmp(new(big.Int).Div(gasPrice, common.Big2)) < 0 { 1118 return fmt.Errorf("maxFeePerGas (%v) < BaseFee (%v)", args.MaxFeePerGas, gasPrice) 1119 } 1120 } else if args.MaxPriorityFeePerGas.ToInt().Cmp(gasPrice) != 0 || args.MaxFeePerGas.ToInt().Cmp(gasPrice) != 0 { 1121 return fmt.Errorf("only %s is allowed to be used as maxFeePerGas and maxPriorityPerGas", gasPrice.Text(16)) 1122 } 1123 if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 { 1124 return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas) 1125 } 1126 } else { 1127 if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil { 1128 return errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet") 1129 } 1130 if args.GasPrice == nil { 1131 // TODO-Klaytn: Original logic of Ethereum uses b.SuggestTipCap which suggests TipCap, not a GasPrice. 1132 // But Klaytn currently uses fixed unit price determined by Governance, so using b.SuggestPrice 1133 // is fine as now. 1134 if b.ChainConfig().IsEthTxTypeForkEnabled(head.Number) { 1135 // TODO-Klaytn: Klaytn is using fixed BaseFee(0) as now but 1136 // if we apply dynamic BaseFee, we should add calculated BaseFee instead of params.ZeroBaseFee. 1137 gasPrice.Add(gasPrice, new(big.Int).SetUint64(params.ZeroBaseFee)) 1138 } 1139 args.GasPrice = (*hexutil.Big)(gasPrice) 1140 } 1141 } 1142 } else { 1143 // Both maxPriorityFee and maxFee set by caller. Sanity-check their internal relation 1144 if isMagma { 1145 if args.MaxFeePerGas.ToInt().Cmp(new(big.Int).Div(gasPrice, common.Big2)) < 0 { 1146 return fmt.Errorf("maxFeePerGas (%v) < BaseFee (%v)", args.MaxFeePerGas, gasPrice) 1147 } 1148 } else { 1149 if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 { 1150 return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas) 1151 } 1152 } 1153 } 1154 if args.Value == nil { 1155 args.Value = new(hexutil.Big) 1156 } 1157 if args.Nonce == nil { 1158 nonce := b.GetPoolNonce(ctx, args.from()) 1159 args.Nonce = (*hexutil.Uint64)(&nonce) 1160 } 1161 if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) { 1162 return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`) 1163 } 1164 if args.To == nil && len(args.data()) == 0 { 1165 return errors.New(`contract creation without any data provided`) 1166 } 1167 // Estimate the gas usage if necessary. 1168 if args.Gas == nil { 1169 // These fields are immutable during the estimation, safe to 1170 // pass the pointer directly. 1171 data := args.data() 1172 callArgs := EthTransactionArgs{ 1173 From: args.From, 1174 To: args.To, 1175 GasPrice: args.GasPrice, 1176 MaxFeePerGas: args.MaxFeePerGas, 1177 MaxPriorityFeePerGas: args.MaxPriorityFeePerGas, 1178 Value: args.Value, 1179 Data: (*hexutil.Bytes)(&data), 1180 AccessList: args.AccessList, 1181 } 1182 pendingBlockNr := rpc.NewBlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1183 gasCap := uint64(0) 1184 if rpcGasCap := b.RPCGasCap(); rpcGasCap != nil { 1185 gasCap = rpcGasCap.Uint64() 1186 } 1187 estimated, err := EthDoEstimateGas(ctx, b, callArgs, pendingBlockNr, gasCap) 1188 if err != nil { 1189 return err 1190 } 1191 args.Gas = &estimated 1192 logger.Trace("Estimate gas usage automatically", "gas", args.Gas) 1193 } 1194 if args.ChainID == nil { 1195 id := (*hexutil.Big)(b.ChainConfig().ChainID) 1196 args.ChainID = id 1197 } 1198 return nil 1199 } 1200 1201 // ToMessage change EthTransactionArgs to types.Transaction in Klaytn. 1202 func (args *EthTransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, intrinsicGas uint64) (*types.Transaction, error) { 1203 // Reject invalid combinations of pre- and post-1559 fee styles 1204 if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { 1205 return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 1206 } else if args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil { 1207 if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 { 1208 return nil, errors.New("MaxPriorityFeePerGas is greater than MaxFeePerGas") 1209 } 1210 } 1211 // Set sender address or use zero address if none specified. 1212 addr := args.from() 1213 1214 // Set default gas & gas price if none were set 1215 gas := globalGasCap 1216 if gas == 0 { 1217 gas = uint64(math.MaxUint64 / 2) 1218 } 1219 if args.Gas != nil { 1220 gas = uint64(*args.Gas) 1221 } 1222 if globalGasCap != 0 && globalGasCap < gas { 1223 logger.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) 1224 gas = globalGasCap 1225 } 1226 1227 // Do not update gasPrice unless any of args.GasPrice and args.MaxFeePerGas is specified. 1228 gasPrice := new(big.Int) 1229 if baseFee.Cmp(new(big.Int).SetUint64(params.ZeroBaseFee)) == 0 { 1230 // If there's no basefee, then it must be a non-1559 execution 1231 if args.GasPrice != nil { 1232 gasPrice = args.GasPrice.ToInt() 1233 } else if args.MaxFeePerGas != nil { 1234 gasPrice = args.MaxFeePerGas.ToInt() 1235 } 1236 } else { 1237 if args.GasPrice != nil { 1238 gasPrice = args.GasPrice.ToInt() 1239 } else if args.MaxFeePerGas != nil { 1240 // User specified 1559 gas fields (or none), use those 1241 gasPrice = args.MaxFeePerGas.ToInt() 1242 } else { 1243 // User specified neither GasPrice nor MaxFeePerGas, use baseFee 1244 gasPrice = new(big.Int).Mul(baseFee, common.Big2) 1245 } 1246 } 1247 1248 value := new(big.Int) 1249 if args.Value != nil { 1250 value = args.Value.ToInt() 1251 } 1252 data := args.data() 1253 1254 // TODO-Klaytn: Klaytn does not support accessList yet. 1255 // var accessList types.AccessList 1256 // if args.AccessList != nil { 1257 // accessList = *args.AccessList 1258 // } 1259 return types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false, intrinsicGas), nil 1260 } 1261 1262 // toTransaction converts the arguments to a transaction. 1263 // This assumes that setDefaults has been called. 1264 func (args *EthTransactionArgs) toTransaction() *types.Transaction { 1265 var tx *types.Transaction 1266 switch { 1267 case args.MaxFeePerGas != nil: 1268 al := types.AccessList{} 1269 if args.AccessList != nil { 1270 al = *args.AccessList 1271 } 1272 tx = types.NewTx(&types.TxInternalDataEthereumDynamicFee{ 1273 ChainID: (*big.Int)(args.ChainID), 1274 AccountNonce: uint64(*args.Nonce), 1275 GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas), 1276 GasFeeCap: (*big.Int)(args.MaxFeePerGas), 1277 GasLimit: uint64(*args.Gas), 1278 Recipient: args.To, 1279 Amount: (*big.Int)(args.Value), 1280 Payload: args.data(), 1281 AccessList: al, 1282 }) 1283 case args.AccessList != nil: 1284 tx = types.NewTx(&types.TxInternalDataEthereumAccessList{ 1285 ChainID: (*big.Int)(args.ChainID), 1286 AccountNonce: uint64(*args.Nonce), 1287 Recipient: args.To, 1288 GasLimit: uint64(*args.Gas), 1289 Price: (*big.Int)(args.GasPrice), 1290 Amount: (*big.Int)(args.Value), 1291 Payload: args.data(), 1292 AccessList: *args.AccessList, 1293 }) 1294 default: 1295 tx = types.NewTx(&types.TxInternalDataLegacy{ 1296 AccountNonce: uint64(*args.Nonce), 1297 Price: (*big.Int)(args.GasPrice), 1298 GasLimit: uint64(*args.Gas), 1299 Recipient: args.To, 1300 Amount: (*big.Int)(args.Value), 1301 Payload: args.data(), 1302 }) 1303 } 1304 return tx 1305 } 1306 1307 func (args *EthTransactionArgs) ToTransaction() *types.Transaction { 1308 return args.toTransaction() 1309 } 1310 1311 // SendTransaction creates a transaction for the given argument, sign it and submit it to the 1312 // transaction pool. 1313 func (api *EthereumAPI) SendTransaction(ctx context.Context, args EthTransactionArgs) (common.Hash, error) { 1314 if args.Nonce == nil { 1315 // Hold the addresses mutex around signing to prevent concurrent assignment of 1316 // the same nonce to multiple accounts. 1317 api.publicTransactionPoolAPI.nonceLock.LockAddr(args.from()) 1318 defer api.publicTransactionPoolAPI.nonceLock.UnlockAddr(args.from()) 1319 } 1320 if err := args.setDefaults(ctx, api.publicTransactionPoolAPI.b); err != nil { 1321 return common.Hash{}, err 1322 } 1323 tx := args.toTransaction() 1324 signedTx, err := api.publicTransactionPoolAPI.sign(args.from(), tx) 1325 if err != nil { 1326 return common.Hash{}, err 1327 } 1328 // Check if signedTx is RLP-Encodable format. 1329 _, err = rlp.EncodeToBytes(signedTx) 1330 if err != nil { 1331 return common.Hash{}, err 1332 } 1333 return submitTransaction(ctx, api.publicTransactionPoolAPI.b, signedTx) 1334 } 1335 1336 // EthSignTransactionResult represents a RLP encoded signed transaction. 1337 // SignTransactionResult in go-ethereum has been renamed to EthSignTransactionResult. 1338 // SignTransactionResult is defined in go-ethereum's internal package, so SignTransactionResult is redefined here as EthSignTransactionResult. 1339 type EthSignTransactionResult struct { 1340 Raw hexutil.Bytes `json:"raw"` 1341 Tx *ethTxJSON `json:"tx"` 1342 } 1343 1344 // FillTransaction fills the defaults (nonce, gas, gasPrice or 1559 fields) 1345 // on a given unsigned transaction, and returns it to the caller for further 1346 // processing (signing + broadcast). 1347 func (api *EthereumAPI) FillTransaction(ctx context.Context, args EthTransactionArgs) (*EthSignTransactionResult, error) { // Set some sanity defaults and terminate on failure 1348 if err := args.setDefaults(ctx, api.publicTransactionPoolAPI.b); err != nil { 1349 return nil, err 1350 } 1351 // Assemble the transaction and obtain rlp 1352 tx := args.toTransaction() 1353 data, err := tx.MarshalBinary() 1354 if err != nil { 1355 return nil, err 1356 } 1357 1358 if tx.IsEthTypedTransaction() { 1359 // Return rawTx except types.TxTypeEthEnvelope: 0x78(= 1 byte) 1360 return &EthSignTransactionResult{data[1:], formatTxToEthTxJSON(tx)}, nil 1361 } 1362 return &EthSignTransactionResult{data, formatTxToEthTxJSON(tx)}, nil 1363 } 1364 1365 // SendRawTransaction will add the signed transaction to the transaction pool. 1366 // The sender is responsible for signing the transaction and using the correct nonce. 1367 func (api *EthereumAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) { 1368 if 0 < input[0] && input[0] < 0x7f { 1369 inputBytes := []byte{byte(types.EthereumTxTypeEnvelope)} 1370 inputBytes = append(inputBytes, input...) 1371 return api.publicTransactionPoolAPI.SendRawTransaction(ctx, inputBytes) 1372 } 1373 // legacy transaction 1374 return api.publicTransactionPoolAPI.SendRawTransaction(ctx, input) 1375 } 1376 1377 // Sign calculates an ECDSA signature for: 1378 // keccack256("\x19Klaytn Signed Message:\n" + len(message) + message). 1379 // 1380 // Note, the produced signature conforms to the secp256k1 curve R, S and V values, 1381 // where the V value will be 27 or 28 for legacy reasons. 1382 // 1383 // The account associated with addr must be unlocked. 1384 // 1385 // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign 1386 func (api *EthereumAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) { 1387 return api.publicTransactionPoolAPI.Sign(addr, data) 1388 } 1389 1390 // SignTransaction will sign the given transaction with the from account. 1391 // The node needs to have the private key of the account corresponding with 1392 // the given from address and it needs to be unlocked. 1393 func (api *EthereumAPI) SignTransaction(ctx context.Context, args EthTransactionArgs) (*EthSignTransactionResult, error) { 1394 b := api.publicTransactionPoolAPI.b 1395 1396 if args.Gas == nil { 1397 return nil, fmt.Errorf("gas not specified") 1398 } 1399 if args.GasPrice == nil && (args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil) { 1400 return nil, fmt.Errorf("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas") 1401 } 1402 if args.Nonce == nil { 1403 return nil, fmt.Errorf("nonce not specified") 1404 } 1405 if err := args.setDefaults(ctx, b); err != nil { 1406 return nil, err 1407 } 1408 // Before actually sign the transaction, ensure the transaction fee is reasonable. 1409 tx := args.toTransaction() 1410 if err := checkTxFee(tx.GasPrice(), tx.Gas(), b.RPCTxFeeCap()); err != nil { 1411 return nil, err 1412 } 1413 signed, err := api.publicTransactionPoolAPI.sign(args.from(), tx) 1414 if err != nil { 1415 return nil, err 1416 } 1417 data, err := signed.MarshalBinary() 1418 if err != nil { 1419 return nil, err 1420 } 1421 if tx.IsEthTypedTransaction() { 1422 // Return rawTx except types.TxTypeEthEnvelope: 0x78(= 1 byte) 1423 return &EthSignTransactionResult{data[1:], formatTxToEthTxJSON(tx)}, nil 1424 } 1425 return &EthSignTransactionResult{data, formatTxToEthTxJSON(tx)}, nil 1426 } 1427 1428 // PendingTransactions returns the transactions that are in the transaction pool 1429 // and have a from address that is one of the accounts this node manages. 1430 func (api *EthereumAPI) PendingTransactions() ([]*EthRPCTransaction, error) { 1431 b := api.publicTransactionPoolAPI.b 1432 pending, err := b.GetPoolTransactions() 1433 if err != nil { 1434 return nil, err 1435 } 1436 accounts := getAccountsFromWallets(b.AccountManager().Wallets()) 1437 transactions := make([]*EthRPCTransaction, 0, len(pending)) 1438 for _, tx := range pending { 1439 from := getFrom(tx) 1440 if _, exists := accounts[from]; exists { 1441 ethTx := newEthRPCPendingTransaction(tx) 1442 if ethTx == nil { 1443 return nil, nil 1444 } 1445 transactions = append(transactions, ethTx) 1446 } 1447 } 1448 return transactions, nil 1449 } 1450 1451 // Resend accepts an existing transaction and a new gas price and limit. It will remove 1452 // the given transaction from the pool and reinsert it with the new gas price and limit. 1453 func (api *EthereumAPI) Resend(ctx context.Context, sendArgs EthTransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) { 1454 return common.Hash{}, errors.New("this api is not supported by Klaytn because Klaytn use fixed gasPrice policy") 1455 } 1456 1457 // Accounts returns the collection of accounts this node manages. 1458 func (api *EthereumAPI) Accounts() []common.Address { 1459 return api.publicAccountAPI.Accounts() 1460 } 1461 1462 // rpcMarshalHeader marshal block header as Ethereum compatible format. 1463 // It returns error when fetching Author which is block proposer is failed. 1464 func (api *EthereumAPI) rpcMarshalHeader(head *types.Header) (map[string]interface{}, error) { 1465 var proposer common.Address 1466 var err error 1467 1468 b := api.publicKlayAPI.b 1469 if head.Number.Sign() != 0 { 1470 proposer, err = b.Engine().Author(head) 1471 if err != nil { 1472 // miner is the field Klaytn should provide the correct value. It's not the field dummy value is allowed. 1473 logger.Error("Failed to fetch author during marshaling header", "err", err.Error()) 1474 return nil, err 1475 } 1476 } 1477 result := map[string]interface{}{ 1478 "number": (*hexutil.Big)(head.Number), 1479 "hash": head.Hash(), 1480 "parentHash": head.ParentHash, 1481 "nonce": BlockNonce{}, // There is no block nonce concept in Klaytn, so it must be empty. 1482 "mixHash": common.Hash{}, // Klaytn does not use mixHash, so it must be empty. 1483 "sha3Uncles": common.HexToHash(EmptySha3Uncles), 1484 "logsBloom": head.Bloom, 1485 "stateRoot": head.Root, 1486 "miner": proposer, 1487 "difficulty": (*hexutil.Big)(head.BlockScore), 1488 "totalDifficulty": (*hexutil.Big)(b.GetTd(head.Hash())), 1489 // extraData always return empty Bytes because actual value of extraData in Klaytn header cannot be used as meaningful way because 1490 // we cannot provide original header of Klaytn and this field is used as consensus info which is encoded value of validators addresses, validators signatures, and proposer signature in Klaytn. 1491 "extraData": hexutil.Bytes{}, 1492 "size": hexutil.Uint64(head.Size()), 1493 // There is no gas limit mechanism in Klaytn, check details in https://docs.klaytn.com/klaytn/design/computation/computation-cost. 1494 "gasLimit": hexutil.Uint64(params.UpperGasLimit), 1495 "gasUsed": hexutil.Uint64(head.GasUsed), 1496 "timestamp": hexutil.Big(*head.Time), 1497 "transactionsRoot": head.TxHash, 1498 "receiptsRoot": head.ReceiptHash, 1499 } 1500 1501 if api.publicBlockChainAPI.b.ChainConfig().IsEthTxTypeForkEnabled(head.Number) { 1502 if head.BaseFee == nil { 1503 result["baseFeePerGas"] = (*hexutil.Big)(new(big.Int).SetUint64(params.ZeroBaseFee)) 1504 } else { 1505 result["baseFeePerGas"] = (*hexutil.Big)(head.BaseFee) 1506 } 1507 } 1508 return result, nil 1509 } 1510 1511 // rpcMarshalBlock marshal block as Ethereum compatible format 1512 func (api *EthereumAPI) rpcMarshalBlock(block *types.Block, inclTx, fullTx bool) (map[string]interface{}, error) { 1513 fields, err := api.rpcMarshalHeader(block.Header()) 1514 if err != nil { 1515 return nil, err 1516 } 1517 fields["size"] = hexutil.Uint64(block.Size()) 1518 1519 if inclTx { 1520 formatTx := func(tx *types.Transaction) (interface{}, error) { 1521 return tx.Hash(), nil 1522 } 1523 if fullTx { 1524 formatTx = func(tx *types.Transaction) (interface{}, error) { 1525 return newEthRPCTransactionFromBlockHash(block, tx.Hash()), nil 1526 } 1527 } 1528 txs := block.Transactions() 1529 transactions := make([]interface{}, len(txs)) 1530 var err error 1531 for i, tx := range txs { 1532 if transactions[i], err = formatTx(tx); err != nil { 1533 return nil, err 1534 } 1535 } 1536 fields["transactions"] = transactions 1537 } 1538 // There is no uncles in Klaytn 1539 fields["uncles"] = []common.Hash{} 1540 1541 return fields, nil 1542 } 1543 1544 func EthDoCall(ctx context.Context, b Backend, args EthTransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *EthStateOverride, timeout time.Duration, globalGasCap uint64) ([]byte, uint64, uint, error) { 1545 defer func(start time.Time) { logger.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) 1546 1547 st, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 1548 if st == nil || err != nil { 1549 return nil, 0, 0, err 1550 } 1551 if err := overrides.Apply(st); err != nil { 1552 return nil, 0, 0, err 1553 } 1554 1555 // Setup context so it may be cancelled the call has completed 1556 // or, in case of unmetered gas, setup a context with a timeout. 1557 var cancel context.CancelFunc 1558 if timeout > 0 { 1559 ctx, cancel = context.WithTimeout(ctx, timeout) 1560 } else { 1561 ctx, cancel = context.WithCancel(ctx) 1562 } 1563 // Make sure the context is cancelled when the call has completed 1564 // this makes sure resources are cleaned up. 1565 defer cancel() 1566 1567 // header.BaseFee != nil means magma hardforked 1568 var baseFee *big.Int 1569 if header.BaseFee != nil { 1570 baseFee = header.BaseFee 1571 } else { 1572 baseFee = new(big.Int).SetUint64(params.ZeroBaseFee) 1573 } 1574 intrinsicGas, err := types.IntrinsicGas(args.data(), nil, args.To == nil, b.ChainConfig().Rules(header.Number)) 1575 if err != nil { 1576 return nil, 0, 0, err 1577 } 1578 msg, err := args.ToMessage(globalGasCap, baseFee, intrinsicGas) 1579 if err != nil { 1580 return nil, 0, 0, err 1581 } 1582 var balanceBaseFee *big.Int 1583 if header.BaseFee != nil { 1584 balanceBaseFee = new(big.Int).Mul(baseFee, common.Big2) 1585 } else { 1586 balanceBaseFee = msg.GasPrice() 1587 } 1588 // Add gas fee to sender for estimating gasLimit/computing cost or calling a function by insufficient balance sender. 1589 st.AddBalance(msg.ValidatedSender(), new(big.Int).Mul(new(big.Int).SetUint64(msg.Gas()), balanceBaseFee)) 1590 1591 // The intrinsicGas is checked again later in the blockchain.ApplyMessage function, 1592 // but we check in advance here in order to keep StateTransition.TransactionDb method as unchanged as possible 1593 // and to clarify error reason correctly to serve eth namespace APIs. 1594 // This case is handled by EthDoEstimateGas function. 1595 if msg.Gas() < intrinsicGas { 1596 return nil, 0, 0, fmt.Errorf("%w: msg.gas %d, want %d", blockchain.ErrIntrinsicGas, msg.Gas(), intrinsicGas) 1597 } 1598 evm, vmError, err := b.GetEVM(ctx, msg, st, header, vm.Config{}) 1599 if err != nil { 1600 return nil, 0, 0, err 1601 } 1602 // Wait for the context to be done and cancel the evm. Even if the 1603 // EVM has finished, cancelling may be done (repeatedly) 1604 go func() { 1605 <-ctx.Done() 1606 evm.Cancel(vm.CancelByCtxDone) 1607 }() 1608 1609 // Execute the message. 1610 res, gas, kerr := blockchain.ApplyMessage(evm, msg) 1611 err = kerr.ErrTxInvalid 1612 if err := vmError(); err != nil { 1613 return nil, 0, 0, err 1614 } 1615 // If the timer caused an abort, return an appropriate error message 1616 if evm.Cancelled() { 1617 return nil, 0, 0, fmt.Errorf("execution aborted (timeout = %v)", timeout) 1618 } 1619 if err != nil { 1620 return res, 0, 0, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) 1621 } 1622 // TODO-Klaytn-Interface: Introduce ExecutionResult struct from geth to return more detail information 1623 return res, gas, kerr.Status, nil 1624 } 1625 1626 func EthDoEstimateGas(ctx context.Context, b Backend, args EthTransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { 1627 // Binary search the gas requirement, as it may be higher than the amount used 1628 var ( 1629 lo uint64 = params.TxGas - 1 1630 hi uint64 = params.UpperGasLimit 1631 cap uint64 1632 ) 1633 // Use zero address if sender unspecified. 1634 if args.From == nil { 1635 args.From = new(common.Address) 1636 } 1637 // Determine the highest gas limit can be used during the estimation. 1638 if args.Gas != nil && uint64(*args.Gas) >= params.TxGas { 1639 hi = uint64(*args.Gas) 1640 } else { 1641 // Ethereum set hi as gas ceiling of the block but, 1642 // there is no actual gas limit in Klaytn, so we set it as params.UpperGasLimit. 1643 hi = params.UpperGasLimit 1644 } 1645 // Normalize the max fee per gas the call is willing to spend. 1646 var feeCap *big.Int 1647 if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { 1648 return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") 1649 } else if args.GasPrice != nil { 1650 feeCap = args.GasPrice.ToInt() 1651 } else if args.MaxFeePerGas != nil { 1652 feeCap = args.MaxFeePerGas.ToInt() 1653 } else { 1654 feeCap = common.Big0 1655 } 1656 // recap the highest gas limit with account's available balance. 1657 if feeCap.BitLen() != 0 { 1658 state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 1659 if err != nil { 1660 return 0, err 1661 } 1662 balance := state.GetBalance(*args.From) // from can't be nil 1663 available := new(big.Int).Set(balance) 1664 if args.Value != nil { 1665 if args.Value.ToInt().Cmp(available) >= 0 { 1666 return 0, errors.New("insufficient funds for transfer") 1667 } 1668 available.Sub(available, args.Value.ToInt()) 1669 } 1670 allowance := new(big.Int).Div(available, feeCap) 1671 1672 // If the allowance is larger than maximum uint64, skip checking 1673 if allowance.IsUint64() && hi > allowance.Uint64() { 1674 transfer := args.Value 1675 if transfer == nil { 1676 transfer = new(hexutil.Big) 1677 } 1678 logger.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, 1679 "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance) 1680 hi = allowance.Uint64() 1681 } 1682 } 1683 // Recap the highest gas allowance with specified gascap. 1684 if gasCap != 0 && hi > gasCap { 1685 logger.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) 1686 hi = gasCap 1687 } 1688 cap = hi 1689 1690 // Create a helper to check if a gas allowance results in an executable transaction. 1691 // executable returns 1692 // - bool: true when a call with given args and gas is executable. 1693 // - []byte: EVM execution result. 1694 // - error: error occurred during EVM execution. 1695 // - error: consensus error which is not EVM related error (less balance of caller, wrong nonce, etc...). 1696 executable := func(gas uint64) (bool, []byte, error, error) { 1697 args.Gas = (*hexutil.Uint64)(&gas) 1698 ret, _, status, err := EthDoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), nil, 0, gasCap) 1699 if err != nil { 1700 if errors.Is(err, blockchain.ErrIntrinsicGas) { 1701 // Special case, raise gas limit 1702 return false, ret, nil, nil 1703 } 1704 // Returns error when it is not VM error (less balance or wrong nonce, etc...). 1705 return false, nil, nil, err 1706 } 1707 // If err is vmError, return vmError with returned data 1708 vmErr := blockchain.GetVMerrFromReceiptStatus(status) 1709 if vmErr != nil { 1710 return false, ret, vmErr, nil 1711 } 1712 return true, ret, vmErr, nil 1713 } 1714 1715 // Execute the binary search and hone in on an executable gas limit 1716 for lo+1 < hi { 1717 mid := (hi + lo) / 2 1718 isExecutable, _, _, err := executable(mid) 1719 if err != nil { 1720 return 0, err 1721 } 1722 1723 if !isExecutable { 1724 lo = mid 1725 } else { 1726 hi = mid 1727 } 1728 } 1729 // Reject the transaction as invalid if it still fails at the highest allowance 1730 if hi == cap { 1731 isExecutable, ret, vmErr, err := executable(hi) 1732 if err != nil { 1733 return 0, err 1734 } 1735 if !isExecutable { 1736 if vmErr != nil { 1737 // Treat vmErr as RevertError only when there was returned data from call. 1738 if isReverted(vmErr) && len(ret) > 0 { 1739 return 0, newRevertError(ret) 1740 } 1741 return 0, vmErr 1742 } 1743 // Otherwise, the specified gas cap is too low 1744 return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) 1745 } 1746 } 1747 return hexutil.Uint64(hi), nil 1748 } 1749 1750 // checkTxFee is an internal function used to check whether the fee of 1751 // the given transaction is _reasonable_(under the cap). 1752 func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error { 1753 // Short circuit if there is no cap for transaction fee at all. 1754 if cap == 0 { 1755 return nil 1756 } 1757 feeEth := new(big.Float).Quo(new(big.Float).SetInt(new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(gas))), new(big.Float).SetInt(big.NewInt(params.KLAY))) 1758 feeFloat, _ := feeEth.Float64() 1759 if feeFloat > cap { 1760 return fmt.Errorf("tx fee (%.2f klay) exceeds the configured cap (%.2f klay)", feeFloat, cap) 1761 } 1762 return nil 1763 }