github.com/dominant-strategies/go-quai@v0.28.2/internal/quaiapi/quai_api.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package quaiapi 18 19 import ( 20 "context" 21 "encoding/json" 22 "errors" 23 "math/big" 24 "time" 25 26 "github.com/dominant-strategies/go-quai/common" 27 "github.com/dominant-strategies/go-quai/common/hexutil" 28 "github.com/dominant-strategies/go-quai/core" 29 "github.com/dominant-strategies/go-quai/core/types" 30 "github.com/dominant-strategies/go-quai/crypto" 31 "github.com/dominant-strategies/go-quai/log" 32 "github.com/dominant-strategies/go-quai/rpc" 33 "github.com/dominant-strategies/go-quai/trie" 34 ) 35 36 // PublicQuaiAPI provides an API to access Quai related information. 37 // It offers only methods that operate on public data that is freely available to anyone. 38 type PublicQuaiAPI struct { 39 b Backend 40 } 41 42 // NewPublicQuaiAPI creates a new Quai protocol API. 43 func NewPublicQuaiAPI(b Backend) *PublicQuaiAPI { 44 return &PublicQuaiAPI{b} 45 } 46 47 // GasPrice returns a suggestion for a gas price for legacy transactions. 48 func (s *PublicQuaiAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) { 49 tipcap, err := s.b.SuggestGasTipCap(ctx) 50 if err != nil { 51 return nil, err 52 } 53 if head := s.b.CurrentHeader(); head.BaseFee() != nil { 54 tipcap.Add(tipcap, head.BaseFee()) 55 } 56 return (*hexutil.Big)(tipcap), err 57 } 58 59 // MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions. 60 func (s *PublicQuaiAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) { 61 tipcap, err := s.b.SuggestGasTipCap(ctx) 62 if err != nil { 63 return nil, err 64 } 65 return (*hexutil.Big)(tipcap), err 66 } 67 68 func (s *PublicQuaiAPI) FeeHistory(ctx context.Context, blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) { 69 oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, int(blockCount), lastBlock, rewardPercentiles) 70 if err != nil { 71 return nil, err 72 } 73 results := &feeHistoryResult{ 74 OldestBlock: (*hexutil.Big)(oldest), 75 GasUsedRatio: gasUsed, 76 } 77 if reward != nil { 78 results.Reward = make([][]*hexutil.Big, len(reward)) 79 for i, w := range reward { 80 results.Reward[i] = make([]*hexutil.Big, len(w)) 81 for j, v := range w { 82 results.Reward[i][j] = (*hexutil.Big)(v) 83 } 84 } 85 } 86 if baseFee != nil { 87 results.BaseFee = make([]*hexutil.Big, len(baseFee)) 88 for i, v := range baseFee { 89 results.BaseFee[i] = (*hexutil.Big)(v) 90 } 91 } 92 return results, nil 93 } 94 95 // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not 96 // yet received the latest block headers from its pears. In case it is synchronizing: 97 // - startingBlock: block number this node started to synchronise from 98 // - currentBlock: block number this node is currently importing 99 // - highestBlock: block number of the highest block header this node has received from peers 100 // - pulledStates: number of state entries processed until now 101 // - knownStates: number of known state entries that still need to be pulled 102 func (s *PublicQuaiAPI) Syncing() (interface{}, error) { 103 progress := s.b.SyncProgress() 104 105 // Return not syncing if the synchronisation already completed 106 if progress.CurrentBlock >= progress.HighestBlock { 107 return false, nil 108 } 109 // Otherwise gather the block sync stats 110 return map[string]interface{}{ 111 "startingBlock": hexutil.Uint64(progress.StartingBlock), 112 "currentBlock": hexutil.Uint64(progress.CurrentBlock), 113 "highestBlock": hexutil.Uint64(progress.HighestBlock), 114 "pulledStates": hexutil.Uint64(progress.PulledStates), 115 "knownStates": hexutil.Uint64(progress.KnownStates), 116 }, nil 117 } 118 119 // PublicBlockChainQuaiAPI provides an API to access the Quai blockchain. 120 // It offers only methods that operate on public data that is freely available to anyone. 121 type PublicBlockChainQuaiAPI struct { 122 b Backend 123 } 124 125 // NewPublicBlockChainQuaiAPI creates a new Quai blockchain API. 126 func NewPublicBlockChainQuaiAPI(b Backend) *PublicBlockChainQuaiAPI { 127 return &PublicBlockChainQuaiAPI{b} 128 } 129 130 // ChainId is the replay-protection chain id for the current Quai chain config. 131 func (api *PublicBlockChainQuaiAPI) ChainId() (*hexutil.Big, error) { 132 return (*hexutil.Big)(api.b.ChainConfig().ChainID), nil 133 } 134 135 // NodeLocation is the access call to the location of the node. 136 func (api *PublicBlockChainQuaiAPI) NodeLocation() []hexutil.Uint64 { 137 return common.NodeLocation.RPCMarshal() 138 } 139 140 // BlockNumber returns the block number of the chain head. 141 func (s *PublicBlockChainQuaiAPI) BlockNumber() hexutil.Uint64 { 142 header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available 143 return hexutil.Uint64(header.NumberU64()) 144 145 } 146 147 // GetBalance returns the amount of wei for the given address in the state of the 148 // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta 149 // block numbers are also allowed. 150 func (s *PublicBlockChainQuaiAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) { 151 nodeCtx := common.NodeLocation.Context() 152 if nodeCtx != common.ZONE_CTX { 153 return nil, errors.New("getBalance call can only be made in zone chain") 154 } 155 if !s.b.ProcessingState() { 156 return nil, errors.New("getBalance call can only be made on chain processing the state") 157 } 158 state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 159 if state == nil || err != nil { 160 return nil, err 161 } 162 internal, err := address.InternalAddress() 163 if err != nil { 164 return nil, err 165 } 166 return (*hexutil.Big)(state.GetBalance(internal)), state.Error() 167 } 168 169 // GetProof returns the Merkle-proof for a given account and optionally some storage keys. 170 func (s *PublicBlockChainQuaiAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { 171 nodeCtx := common.NodeLocation.Context() 172 if nodeCtx != common.ZONE_CTX { 173 return nil, errors.New("getProof call can only be made in zone chain") 174 } 175 if !s.b.ProcessingState() { 176 return nil, errors.New("getProof call can only be made on chain processing the state") 177 } 178 state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 179 if state == nil || err != nil { 180 return nil, err 181 } 182 internal, err := address.InternalAddress() 183 if err != nil { 184 return nil, err 185 } 186 187 storageTrie := state.StorageTrie(internal) 188 storageHash := types.EmptyRootHash 189 codeHash := state.GetCodeHash(internal) 190 storageProof := make([]StorageResult, len(storageKeys)) 191 192 // if we have a storageTrie, (which means the account exists), we can update the storagehash 193 if storageTrie != nil { 194 storageHash = storageTrie.Hash() 195 } else { 196 // no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray. 197 codeHash = crypto.Keccak256Hash(nil) 198 } 199 200 // create the proof for the storageKeys 201 for i, key := range storageKeys { 202 if storageTrie != nil { 203 proof, storageError := state.GetStorageProof(internal, common.HexToHash(key)) 204 if storageError != nil { 205 return nil, storageError 206 } 207 storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(internal, common.HexToHash(key)).Big()), toHexSlice(proof)} 208 } else { 209 storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}} 210 } 211 } 212 213 // create the accountProof 214 accountProof, proofErr := state.GetProof(internal) 215 if proofErr != nil { 216 return nil, proofErr 217 } 218 219 return &AccountResult{ 220 Address: address, 221 AccountProof: toHexSlice(accountProof), 222 Balance: (*hexutil.Big)(state.GetBalance(internal)), 223 CodeHash: codeHash, 224 Nonce: hexutil.Uint64(state.GetNonce(internal)), 225 StorageHash: storageHash, 226 StorageProof: storageProof, 227 }, state.Error() 228 } 229 230 // GetHeaderByNumber returns the requested canonical block header. 231 // * When blockNr is -1 the chain head is returned. 232 // * When blockNr is -2 the pending chain head is returned. 233 func (s *PublicBlockChainQuaiAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) { 234 header, err := s.b.HeaderByNumber(ctx, number) 235 if header != nil && err == nil { 236 response := header.RPCMarshalHeader() 237 if number == rpc.PendingBlockNumber { 238 // Pending header need to nil out a few fields 239 for _, field := range []string{"hash", "nonce", "miner"} { 240 response[field] = nil 241 } 242 } 243 return response, err 244 } 245 return nil, err 246 } 247 248 // GetHeaderByHash returns the requested header by hash. 249 func (s *PublicBlockChainQuaiAPI) GetHeaderHashByNumber(ctx context.Context, number rpc.BlockNumber) common.Hash { 250 header, err := s.b.HeaderByNumber(ctx, number) 251 if err != nil { 252 return common.Hash{} 253 } 254 return header.Hash() 255 } 256 257 // GetHeaderByHash returns the requested header by hash. 258 func (s *PublicBlockChainQuaiAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} { 259 header, _ := s.b.HeaderByHash(ctx, hash) 260 if header != nil { 261 return header.RPCMarshalHeader() 262 } 263 return nil 264 } 265 266 // GetBlockByNumber returns the requested canonical block. 267 // - When blockNr is -1 the chain head is returned. 268 // - When blockNr is -2 the pending chain head is returned. 269 // - When fullTx is true all transactions in the block are returned, otherwise 270 // only the transaction hash is returned. 271 func (s *PublicBlockChainQuaiAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { 272 block, err := s.b.BlockByNumber(ctx, number) 273 if block != nil && err == nil { 274 response, err := s.rpcMarshalBlock(ctx, block, true, fullTx) 275 if err == nil && number == rpc.PendingBlockNumber { 276 // Pending blocks need to nil out a few fields 277 for _, field := range []string{"hash", "nonce", "miner"} { 278 response[field] = nil 279 } 280 } 281 return response, err 282 } 283 return nil, err 284 } 285 286 // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full 287 // detail, otherwise only the transaction hash is returned. 288 func (s *PublicBlockChainQuaiAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) { 289 block, err := s.b.BlockByHash(ctx, hash) 290 if block != nil { 291 return s.rpcMarshalBlock(ctx, block, true, fullTx) 292 } 293 return nil, err 294 } 295 296 // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true 297 // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned. 298 func (s *PublicBlockChainQuaiAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) { 299 block, err := s.b.BlockByNumber(ctx, blockNr) 300 if block != nil { 301 uncles := block.Uncles() 302 if index >= hexutil.Uint(len(uncles)) { 303 log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index) 304 return nil, nil 305 } 306 block = types.NewBlockWithHeader(uncles[index]) 307 return s.rpcMarshalBlock(ctx, block, false, false) 308 } 309 return nil, err 310 } 311 312 // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true 313 // all transactions in the block are returned in full detail, otherwise only the transaction hash is returned. 314 func (s *PublicBlockChainQuaiAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) { 315 block, err := s.b.BlockByHash(ctx, blockHash) 316 if block != nil { 317 uncles := block.Uncles() 318 if index >= hexutil.Uint(len(uncles)) { 319 log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index) 320 return nil, nil 321 } 322 block = types.NewBlockWithHeader(uncles[index]) 323 return s.rpcMarshalBlock(ctx, block, false, false) 324 } 325 pendBlock, _ := s.b.PendingBlockAndReceipts() 326 if pendBlock != nil && pendBlock.Hash() == blockHash { 327 uncles := pendBlock.Uncles() 328 if index >= hexutil.Uint(len(uncles)) { 329 log.Debug("Requested uncle not found in pending block", "number", block.Number(), "hash", blockHash, "index", index) 330 return nil, nil 331 } 332 block = types.NewBlockWithHeader(uncles[index]) 333 return s.rpcMarshalBlock(ctx, block, false, false) 334 } 335 return nil, err 336 } 337 338 // GetUncleCountByBlockNumber returns number of uncles in the block for the given block number 339 func (s *PublicBlockChainQuaiAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { 340 if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { 341 n := hexutil.Uint(len(block.Uncles())) 342 return &n 343 } 344 return nil 345 } 346 347 // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash 348 func (s *PublicBlockChainQuaiAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { 349 if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { 350 n := hexutil.Uint(len(block.Uncles())) 351 return &n 352 } 353 return nil 354 } 355 356 // GetCode returns the code stored at the given address in the state for the given block number. 357 func (s *PublicBlockChainQuaiAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { 358 nodeCtx := common.NodeLocation.Context() 359 if nodeCtx != common.ZONE_CTX { 360 return nil, errors.New("getCode can only called in a zone chain") 361 } 362 if !s.b.ProcessingState() { 363 return nil, errors.New("getCode call can only be made on chain processing the state") 364 } 365 state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 366 if state == nil || err != nil { 367 return nil, err 368 } 369 internal, err := address.InternalAddress() 370 if err != nil { 371 return nil, err 372 } 373 code := state.GetCode(internal) 374 return code, state.Error() 375 } 376 377 // GetStorageAt returns the storage from the state at the given address, key and 378 // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block 379 // numbers are also allowed. 380 func (s *PublicBlockChainQuaiAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) { 381 nodeCtx := common.NodeLocation.Context() 382 if nodeCtx != common.ZONE_CTX { 383 return nil, errors.New("getStorageAt can only called in a zone chain") 384 } 385 if !s.b.ProcessingState() { 386 return nil, errors.New("getStorageAt call can only be made on chain processing the state") 387 } 388 state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) 389 if state == nil || err != nil { 390 return nil, err 391 } 392 internal, err := address.InternalAddress() 393 if err != nil { 394 return nil, err 395 } 396 res := state.GetState(internal, common.HexToHash(key)) 397 return res[:], state.Error() 398 } 399 400 // Call executes the given transaction on the state for the given block number. 401 // 402 // Additionally, the caller can specify a batch of contract for fields overriding. 403 // 404 // Note, this function doesn't make and changes in the state/blockchain and is 405 // useful to execute and retrieve values. 406 func (s *PublicBlockChainQuaiAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) { 407 result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, 5*time.Second, s.b.RPCGasCap()) 408 if err != nil { 409 return nil, err 410 } 411 // If the result contains a revert reason, try to unpack and return it. 412 if len(result.Revert()) > 0 { 413 return nil, newRevertError(result) 414 } 415 return result.Return(), result.Err 416 } 417 418 // EstimateGas returns an estimate of the amount of gas needed to execute the 419 // given transaction against the current pending block. 420 func (s *PublicBlockChainQuaiAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) { 421 nodeCtx := common.NodeLocation.Context() 422 if nodeCtx != common.ZONE_CTX { 423 return 0, errors.New("estimateGas can only called in a zone chain") 424 } 425 if !s.b.ProcessingState() { 426 return 0, errors.New("estimateGas call can only be made on chain processing the state") 427 } 428 bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 429 if blockNrOrHash != nil { 430 bNrOrHash = *blockNrOrHash 431 } 432 return DoEstimateGas(ctx, s.b, args, bNrOrHash, s.b.RPCGasCap()) 433 } 434 435 // RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are 436 // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain 437 // transaction hashes. 438 func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { 439 fields := block.Header().RPCMarshalHeader() 440 fields["size"] = hexutil.Uint64(block.Size()) 441 442 if inclTx { 443 formatTx := func(tx *types.Transaction) (interface{}, error) { 444 return tx.Hash(), nil 445 } 446 formatEtx := formatTx 447 if fullTx { 448 formatTx = func(tx *types.Transaction) (interface{}, error) { 449 return newRPCTransactionFromBlockHash(block, tx.Hash(), false), nil 450 } 451 formatEtx = func(tx *types.Transaction) (interface{}, error) { 452 return newRPCTransactionFromBlockHash(block, tx.Hash(), true), nil 453 } 454 } 455 txs := block.Transactions() 456 transactions := make([]interface{}, len(txs)) 457 var err error 458 for i, tx := range txs { 459 if transactions[i], err = formatTx(tx); err != nil { 460 return nil, err 461 } 462 } 463 fields["transactions"] = transactions 464 etxs := block.ExtTransactions() 465 extTransactions := make([]interface{}, len(etxs)) 466 for i, etx := range etxs { 467 if extTransactions[i], err = formatEtx(etx); err != nil { 468 return nil, err 469 } 470 } 471 fields["extTransactions"] = extTransactions 472 } 473 474 fields["uncles"] = block.Uncles() 475 fields["subManifest"] = block.SubManifest() 476 477 return fields, nil 478 } 479 480 // rpcMarshalReOrgData converts the reOrgData obtained to the right header format 481 func RPCMarshalReOrgData(header *types.Header, newHeaders []*types.Header, oldHeaders []*types.Header) (map[string]interface{}, error) { 482 fields := map[string]interface{}{"header": header.RPCMarshalHeader()} 483 484 fieldNewHeaders := make([]interface{}, len(newHeaders)) 485 for i, newHeader := range newHeaders { 486 fieldNewHeaders[i] = newHeader.RPCMarshalHeader() 487 } 488 489 fieldOldHeaders := make([]interface{}, len(oldHeaders)) 490 for i, oldHeader := range oldHeaders { 491 fieldOldHeaders[i] = oldHeader.RPCMarshalHeader() 492 } 493 494 fields["newHeaders"] = fieldNewHeaders 495 fields["oldHeaders"] = fieldOldHeaders 496 return fields, nil 497 } 498 499 // RPCMarshalHash convert the hash into a the correct interface. 500 func RPCMarshalHash(hash common.Hash) (map[string]interface{}, error) { 501 fields := map[string]interface{}{"Hash": hash} 502 return fields, nil 503 } 504 505 // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires 506 // a `PublicBlockchainQuaiAPI`. 507 func (s *PublicBlockChainQuaiAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} { 508 fields := header.RPCMarshalHeader() 509 fields["totalEntropy"] = (*hexutil.Big)(s.b.TotalLogS(header)) 510 return fields 511 } 512 513 // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires 514 // a `PublicBlockchainAPI`. 515 func (s *PublicBlockChainQuaiAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { 516 fields, err := RPCMarshalBlock(b, inclTx, fullTx) 517 if err != nil { 518 return nil, err 519 } 520 _, order, err := s.b.CalcOrder(b.Header()) 521 if err != nil { 522 return nil, err 523 } 524 fields["order"] = order 525 fields["totalEntropy"] = (*hexutil.Big)(s.b.TotalLogS(b.Header())) 526 return fields, err 527 } 528 529 // CreateAccessList creates an AccessList for the given transaction. 530 // Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state. 531 func (s *PublicBlockChainQuaiAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) { 532 nodeCtx := common.NodeLocation.Context() 533 if nodeCtx != common.ZONE_CTX { 534 return nil, errors.New("createAccessList can only be called in zone chain") 535 } 536 if !s.b.ProcessingState() { 537 return nil, errors.New("createAccessList call can only be made on chain processing the state") 538 } 539 bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 540 if blockNrOrHash != nil { 541 bNrOrHash = *blockNrOrHash 542 } 543 acl, gasUsed, vmerr, err := AccessList(ctx, s.b, bNrOrHash, args) 544 if err != nil { 545 return nil, err 546 } 547 result := &accessListResult{Accesslist: &acl, GasUsed: hexutil.Uint64(gasUsed)} 548 if vmerr != nil { 549 result.Error = vmerr.Error() 550 } 551 return result, nil 552 } 553 554 func (s *PublicBlockChainQuaiAPI) fillSubordinateManifest(b *types.Block) (*types.Block, error) { 555 nodeCtx := common.NodeLocation.Context() 556 if b.ManifestHash(nodeCtx+1) == types.EmptyRootHash { 557 return nil, errors.New("cannot fill empty subordinate manifest") 558 } else if subManifestHash := types.DeriveSha(b.SubManifest(), trie.NewStackTrie(nil)); subManifestHash == b.ManifestHash(nodeCtx+1) { 559 // If the manifest hashes match, nothing to do 560 return b, nil 561 } else { 562 subParentHash := b.ParentHash(nodeCtx + 1) 563 var subManifest types.BlockManifest 564 if subParent, err := s.b.BlockByHash(context.Background(), subParentHash); err == nil && subParent != nil { 565 // If we have the the subordinate parent in our chain, that means that block 566 // was also coincident. In this case, the subordinate manifest resets, and 567 // only consists of the subordinate parent hash. 568 subManifest = types.BlockManifest{subParentHash} 569 } else { 570 // Otherwise we need to reconstruct the sub manifest, by getting the 571 // parent's sub manifest and appending the parent hash. 572 subManifest, err = s.b.GetSubManifest(b.Location(), subParentHash) 573 if err != nil { 574 return nil, err 575 } 576 } 577 if len(subManifest) == 0 { 578 return nil, errors.New("reconstructed sub manifest is empty") 579 } 580 if subManifest == nil || b.ManifestHash(nodeCtx+1) != types.DeriveSha(subManifest, trie.NewStackTrie(nil)) { 581 return nil, errors.New("reconstructed sub manifest does not match manifest hash") 582 } 583 return types.NewBlockWithHeader(b.Header()).WithBody(b.Transactions(), b.Uncles(), b.ExtTransactions(), subManifest), nil 584 } 585 } 586 587 // ReceiveMinedHeader will run checks on the block and add to canonical chain if valid. 588 func (s *PublicBlockChainQuaiAPI) ReceiveMinedHeader(ctx context.Context, raw json.RawMessage) error { 589 nodeCtx := common.NodeLocation.Context() 590 // Decode header and transactions. 591 var header *types.Header 592 if err := json.Unmarshal(raw, &header); err != nil { 593 return err 594 } 595 block, err := s.b.ConstructLocalMinedBlock(header) 596 if err != nil && err.Error() == core.ErrBadSubManifest.Error() && nodeCtx < common.ZONE_CTX { 597 log.Info("filling sub manifest") 598 // If we just mined this block, and we have a subordinate chain, its possible 599 // the subordinate manifest in our block body is incorrect. If so, ask our sub 600 // for the correct manifest and reconstruct the block. 601 var err error 602 block, err = s.fillSubordinateManifest(block) 603 if err != nil { 604 return err 605 } 606 } else if err != nil { 607 return err 608 } 609 s.b.WriteBlock(block) 610 // Broadcast the block and announce chain insertion event 611 if block.Header() != nil { 612 s.b.EventMux().Post(core.NewMinedBlockEvent{Block: block}) 613 } 614 log.Info("Retrieved mined block", "number", header.Number(), "location", header.Location()) 615 616 return nil 617 } 618 619 type tdBlock struct { 620 Header *types.Header `json:"header"` 621 Manifest types.BlockManifest `json:"manifest"` 622 DomPendingHeader *types.Header `json:"domPendingHeader"` 623 DomTerminus common.Hash `json:"domTerminus"` 624 DomOrigin bool `json:"domOrigin"` 625 NewInboundEtxs types.Transactions `json:"newInboundEtxs"` 626 } 627 628 func (s *PublicBlockChainQuaiAPI) Append(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) { 629 // Decode header and transactions. 630 var body tdBlock 631 632 if err := json.Unmarshal(raw, &body); err != nil { 633 return nil, err 634 } 635 636 pendingEtxs, subReorg, setHead, err := s.b.Append(body.Header, body.Manifest, body.DomPendingHeader, body.DomTerminus, body.DomOrigin, body.NewInboundEtxs) 637 if err != nil { 638 return nil, err 639 } 640 // Marshal the output for decoding 641 fields := map[string]interface{}{ 642 "pendingEtxs": pendingEtxs, 643 "subReorg": subReorg, 644 "setHead": setHead, 645 } 646 647 return fields, nil 648 649 } 650 651 type DownloadBlocksInManifestArgs struct { 652 Hash common.Hash `json:"hash"` 653 Manifest types.BlockManifest `json:"manifest"` 654 Entropy *big.Int `json:"entropy"` 655 } 656 657 func (s *PublicBlockChainQuaiAPI) DownloadBlocksInManifest(ctx context.Context, raw json.RawMessage) { 658 var manifest DownloadBlocksInManifestArgs 659 if err := json.Unmarshal(raw, &manifest); err != nil { 660 return 661 } 662 s.b.DownloadBlocksInManifest(manifest.Hash, manifest.Manifest, manifest.Entropy) 663 } 664 665 type SubRelay struct { 666 Header *types.Header `json:"header"` 667 Termini types.Termini `json:"termini"` 668 NewEntropy *big.Int 669 Location common.Location 670 SubReorg bool 671 Order int 672 } 673 674 func (s *PublicBlockChainQuaiAPI) SubRelayPendingHeader(ctx context.Context, raw json.RawMessage) { 675 var subRelay SubRelay 676 if err := json.Unmarshal(raw, &subRelay); err != nil { 677 return 678 } 679 pendingHeader := types.NewPendingHeader(subRelay.Header, subRelay.Termini) 680 s.b.SubRelayPendingHeader(pendingHeader, subRelay.NewEntropy, subRelay.Location, subRelay.SubReorg, subRelay.Order) 681 } 682 683 type DomUpdate struct { 684 OldTerminus common.Hash 685 Header *types.Header `json:"header"` 686 Termini types.Termini `json:"termini"` 687 Location common.Location 688 } 689 690 func (s *PublicBlockChainQuaiAPI) UpdateDom(ctx context.Context, raw json.RawMessage) { 691 var domUpdate DomUpdate 692 if err := json.Unmarshal(raw, &domUpdate); err != nil { 693 log.Error("Error unmarshaling domUpdate in api", "err", err) 694 return 695 } 696 697 pendingHeader := types.NewPendingHeader(domUpdate.Header, domUpdate.Termini) 698 s.b.UpdateDom(domUpdate.OldTerminus, pendingHeader, domUpdate.Location) 699 } 700 701 type RequestDomToAppendOrFetchArgs struct { 702 Hash common.Hash 703 Entropy *big.Int 704 Order int 705 } 706 707 func (s *PublicBlockChainQuaiAPI) RequestDomToAppendOrFetch(ctx context.Context, raw json.RawMessage) { 708 var requestDom RequestDomToAppendOrFetchArgs 709 if err := json.Unmarshal(raw, &requestDom); err != nil { 710 return 711 } 712 s.b.RequestDomToAppendOrFetch(requestDom.Hash, requestDom.Entropy, requestDom.Order) 713 } 714 func (s *PublicBlockChainQuaiAPI) NewGenesisPendingHeader(ctx context.Context, raw json.RawMessage) { 715 var pendingHeader *types.Header 716 if err := json.Unmarshal(raw, &pendingHeader); err != nil { 717 return 718 } 719 s.b.NewGenesisPendingHeader(pendingHeader) 720 } 721 722 func (s *PublicBlockChainQuaiAPI) GetPendingHeader(ctx context.Context) (map[string]interface{}, error) { 723 nodeCtx := common.NodeLocation.Context() 724 if nodeCtx != common.ZONE_CTX { 725 return nil, errors.New("getPendingHeader can only be called in zone chain") 726 } 727 if !s.b.ProcessingState() { 728 return nil, errors.New("getPendingHeader call can only be made on chain processing the state") 729 } 730 pendingHeader, err := s.b.GetPendingHeader() 731 if err != nil { 732 return nil, err 733 } else if pendingHeader == nil { 734 return nil, errors.New("no pending header found") 735 } 736 // Marshal the response. 737 marshaledPh := pendingHeader.RPCMarshalHeader() 738 return marshaledPh, nil 739 } 740 741 func (s *PublicBlockChainQuaiAPI) GetManifest(ctx context.Context, raw json.RawMessage) (types.BlockManifest, error) { 742 var blockHash common.Hash 743 if err := json.Unmarshal(raw, &blockHash); err != nil { 744 return nil, err 745 } 746 manifest, err := s.b.GetManifest(blockHash) 747 if err != nil { 748 return nil, err 749 } 750 return manifest, nil 751 } 752 753 type SendPendingEtxsToDomArgs struct { 754 Header types.Header `json:"header"` 755 NewPendingEtxs []types.Transactions `json:"newPendingEtxs"` 756 } 757 758 func (s *PublicBlockChainQuaiAPI) SendPendingEtxsToDom(ctx context.Context, raw json.RawMessage) error { 759 var pEtxs types.PendingEtxs 760 if err := json.Unmarshal(raw, &pEtxs); err != nil { 761 return err 762 } 763 return s.b.AddPendingEtxs(pEtxs) 764 } 765 766 type SendPendingEtxsRollupToDomArgs struct { 767 Header *types.Header `json:"header"` 768 Manifest types.BlockManifest `json:"manifest"` 769 } 770 771 func (s *PublicBlockChainQuaiAPI) SendPendingEtxsRollupToDom(ctx context.Context, raw json.RawMessage) error { 772 var pEtxsRollup SendPendingEtxsRollupToDomArgs 773 if err := json.Unmarshal(raw, &pEtxsRollup); err != nil { 774 return err 775 } 776 return s.b.AddPendingEtxsRollup(types.PendingEtxsRollup{Header: pEtxsRollup.Header, Manifest: pEtxsRollup.Manifest}) 777 } 778 779 type GenerateRecoveryPendingHeaderArgs struct { 780 PendingHeader *types.Header `json:"pendingHeader"` 781 CheckpointHashes types.Termini `json:"checkpointHashes"` 782 } 783 784 func (s *PublicBlockChainQuaiAPI) GenerateRecoveryPendingHeader(ctx context.Context, raw json.RawMessage) error { 785 var pHandcheckPointHashes GenerateRecoveryPendingHeaderArgs 786 if err := json.Unmarshal(raw, &pHandcheckPointHashes); err != nil { 787 return err 788 } 789 return s.b.GenerateRecoveryPendingHeader(pHandcheckPointHashes.PendingHeader, pHandcheckPointHashes.CheckpointHashes) 790 } 791 792 type GetPendingEtxsRollupFuncArgs struct { 793 Hash common.Hash 794 Location common.Location 795 } 796 797 func (s *PublicBlockChainQuaiAPI) GetPendingEtxsRollupFromSub(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) { 798 var getPEtxsRollup GetPendingEtxsFuncArgs 799 if err := json.Unmarshal(raw, &getPEtxsRollup); err != nil { 800 return nil, err 801 } 802 pEtxsRollup, err := s.b.GetPendingEtxsRollupFromSub(getPEtxsRollup.Hash, getPEtxsRollup.Location) 803 if err != nil { 804 return nil, err 805 } 806 fields := make(map[string]interface{}) 807 fields["header"] = pEtxsRollup.Header.RPCMarshalHeader() 808 fields["manifest"] = pEtxsRollup.Manifest 809 810 return fields, nil 811 } 812 813 type GetPendingEtxsFuncArgs struct { 814 Hash common.Hash 815 Location common.Location 816 } 817 818 func (s *PublicBlockChainQuaiAPI) GetPendingEtxsFromSub(ctx context.Context, raw json.RawMessage) (map[string]interface{}, error) { 819 var getPEtxs GetPendingEtxsFuncArgs 820 if err := json.Unmarshal(raw, &getPEtxs); err != nil { 821 return nil, err 822 } 823 pEtxs, err := s.b.GetPendingEtxsFromSub(getPEtxs.Hash, getPEtxs.Location) 824 if err != nil { 825 return nil, err 826 } 827 fields := make(map[string]interface{}) 828 fields["header"] = pEtxs.Header.RPCMarshalHeader() 829 fields["etxs"] = pEtxs.Etxs 830 831 return fields, nil 832 } 833 834 func (s *PublicBlockChainQuaiAPI) SetSyncTarget(ctx context.Context, raw json.RawMessage) error { 835 var header *types.Header 836 if err := json.Unmarshal(raw, &header); err != nil { 837 return err 838 } 839 s.b.SetSyncTarget(header) 840 return nil 841 }