github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/internal/ethapi/api.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:38</date> 10 //</624450092182540288> 11 12 13 package ethapi 14 15 import ( 16 "bytes" 17 "context" 18 "errors" 19 "fmt" 20 "math/big" 21 "strings" 22 "time" 23 24 "github.com/davecgh/go-spew/spew" 25 "github.com/ethereum/go-ethereum/accounts" 26 "github.com/ethereum/go-ethereum/accounts/keystore" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/common/hexutil" 29 "github.com/ethereum/go-ethereum/common/math" 30 "github.com/ethereum/go-ethereum/consensus/ethash" 31 "github.com/ethereum/go-ethereum/core" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/core/vm" 35 "github.com/ethereum/go-ethereum/crypto" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/p2p" 38 "github.com/ethereum/go-ethereum/params" 39 "github.com/ethereum/go-ethereum/rlp" 40 "github.com/ethereum/go-ethereum/rpc" 41 "github.com/syndtr/goleveldb/leveldb" 42 "github.com/syndtr/goleveldb/leveldb/util" 43 ) 44 45 const ( 46 defaultGasPrice = params.GWei 47 ) 48 49 //PublicEthereumAPI提供一个API来访问与以太坊相关的信息。 50 //它只提供对任何人都可以自由使用的公共数据进行操作的方法。 51 type PublicEthereumAPI struct { 52 b Backend 53 } 54 55 //NewPublicEthereumAPI创建新的Ethereum协议API。 56 func NewPublicEthereumAPI(b Backend) *PublicEthereumAPI { 57 return &PublicEthereumAPI{b} 58 } 59 60 //加斯普赖斯返回了一个天然气价格的建议。 61 func (s *PublicEthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) { 62 price, err := s.b.SuggestPrice(ctx) 63 return (*hexutil.Big)(price), err 64 } 65 66 //ProtocolVersion返回此节点支持的当前以太坊协议版本 67 func (s *PublicEthereumAPI) ProtocolVersion() hexutil.Uint { 68 return hexutil.Uint(s.b.ProtocolVersion()) 69 } 70 71 //如果节点当前未与网络同步,则同步将返回false。它可以是最新的,也可以没有。 72 //yet received the latest block headers from its pears. In case it is synchronizing: 73 //-startingblock:此节点开始同步的块号 74 //-currentblock:此节点当前导入的块号 75 //-highest block:此节点从对等方接收到的最高块头的块号 76 //-pulledstates:到目前为止处理的状态条目数 77 //-knownstates:仍需要提取的已知状态条目数 78 func (s *PublicEthereumAPI) Syncing() (interface{}, error) { 79 progress := s.b.Downloader().Progress() 80 81 //如果同步已完成,则返回“未同步” 82 if progress.CurrentBlock >= progress.HighestBlock { 83 return false, nil 84 } 85 //否则收集块同步状态 86 return map[string]interface{}{ 87 "startingBlock": hexutil.Uint64(progress.StartingBlock), 88 "currentBlock": hexutil.Uint64(progress.CurrentBlock), 89 "highestBlock": hexutil.Uint64(progress.HighestBlock), 90 "pulledStates": hexutil.Uint64(progress.PulledStates), 91 "knownStates": hexutil.Uint64(progress.KnownStates), 92 }, nil 93 } 94 95 //publicTxPoolapi为事务池提供和API。它只对非机密数据进行操作。 96 type PublicTxPoolAPI struct { 97 b Backend 98 } 99 100 //newpublicTxPoolapi创建一个新的TxPool服务,提供有关事务池的信息。 101 func NewPublicTxPoolAPI(b Backend) *PublicTxPoolAPI { 102 return &PublicTxPoolAPI{b} 103 } 104 105 //Content返回事务池中包含的事务。 106 func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction { 107 content := map[string]map[string]map[string]*RPCTransaction{ 108 "pending": make(map[string]map[string]*RPCTransaction), 109 "queued": make(map[string]map[string]*RPCTransaction), 110 } 111 pending, queue := s.b.TxPoolContent() 112 113 //平摊未决交易 114 for account, txs := range pending { 115 dump := make(map[string]*RPCTransaction) 116 for _, tx := range txs { 117 dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx) 118 } 119 content["pending"][account.Hex()] = dump 120 } 121 //扁平排队的事务 122 for account, txs := range queue { 123 dump := make(map[string]*RPCTransaction) 124 for _, tx := range txs { 125 dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx) 126 } 127 content["queued"][account.Hex()] = dump 128 } 129 return content 130 } 131 132 //status返回池中挂起和排队的事务数。 133 func (s *PublicTxPoolAPI) Status() map[string]hexutil.Uint { 134 pending, queue := s.b.Stats() 135 return map[string]hexutil.Uint{ 136 "pending": hexutil.Uint(pending), 137 "queued": hexutil.Uint(queue), 138 } 139 } 140 141 //inspect检索事务池的内容并将其扁平化为 142 //易于检查的列表。 143 func (s *PublicTxPoolAPI) Inspect() map[string]map[string]map[string]string { 144 content := map[string]map[string]map[string]string{ 145 "pending": make(map[string]map[string]string), 146 "queued": make(map[string]map[string]string), 147 } 148 pending, queue := s.b.TxPoolContent() 149 150 //定义格式化程序以将事务扁平化为字符串 151 var format = func(tx *types.Transaction) string { 152 if to := tx.To(); to != nil { 153 return fmt.Sprintf("%s: %v wei + %v gas × %v wei", tx.To().Hex(), tx.Value(), tx.Gas(), tx.GasPrice()) 154 } 155 return fmt.Sprintf("contract creation: %v wei + %v gas × %v wei", tx.Value(), tx.Gas(), tx.GasPrice()) 156 } 157 //平摊未决交易 158 for account, txs := range pending { 159 dump := make(map[string]string) 160 for _, tx := range txs { 161 dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx) 162 } 163 content["pending"][account.Hex()] = dump 164 } 165 //扁平排队的事务 166 for account, txs := range queue { 167 dump := make(map[string]string) 168 for _, tx := range txs { 169 dump[fmt.Sprintf("%d", tx.Nonce())] = format(tx) 170 } 171 content["queued"][account.Hex()] = dump 172 } 173 return content 174 } 175 176 //PublicAccountAPI提供了一个API,用于访问此节点管理的帐户。 177 //它只提供可以检索帐户的方法。 178 type PublicAccountAPI struct { 179 am *accounts.Manager 180 } 181 182 //我创建了一个新的公共会计。 183 func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI { 184 return &PublicAccountAPI{am: am} 185 } 186 187 //帐户返回此节点管理的帐户集合 188 func (s *PublicAccountAPI) Accounts() []common.Address { 189 addresses := make([]common.Address, 0) //如果为空,则返回[]而不是零 190 for _, wallet := range s.am.Wallets() { 191 for _, account := range wallet.Accounts() { 192 addresses = append(addresses, account.Address) 193 } 194 } 195 return addresses 196 } 197 198 //privateaccountapi提供了访问此节点管理的帐户的API。 199 //它提供创建(取消)锁定列表帐户的方法。有些方法可以接受 200 //密码,因此默认情况下被视为私有密码。 201 type PrivateAccountAPI struct { 202 am *accounts.Manager 203 nonceLock *AddrLocker 204 b Backend 205 } 206 207 //new privateaccountapi创建新的privateaccountapi。 208 func NewPrivateAccountAPI(b Backend, nonceLock *AddrLocker) *PrivateAccountAPI { 209 return &PrivateAccountAPI{ 210 am: b.AccountManager(), 211 nonceLock: nonceLock, 212 b: b, 213 } 214 } 215 216 //list accounts将返回此节点管理的帐户的地址列表。 217 func (s *PrivateAccountAPI) ListAccounts() []common.Address { 218 addresses := make([]common.Address, 0) //如果为空,则返回[]而不是零 219 for _, wallet := range s.am.Wallets() { 220 for _, account := range wallet.Accounts() { 221 addresses = append(addresses, account.Address) 222 } 223 } 224 return addresses 225 } 226 227 //rawwallet是一个帐户.wallet接口的JSON表示,其 228 //将数据内容提取到普通字段中。 229 type rawWallet struct { 230 URL string `json:"url"` 231 Status string `json:"status"` 232 Failure string `json:"failure,omitempty"` 233 Accounts []accounts.Account `json:"accounts,omitempty"` 234 } 235 236 //list wallets将返回此节点管理的钱包列表。 237 func (s *PrivateAccountAPI) ListWallets() []rawWallet { 238 wallets := make([]rawWallet, 0) //如果为空,则返回[]而不是零 239 for _, wallet := range s.am.Wallets() { 240 status, failure := wallet.Status() 241 242 raw := rawWallet{ 243 URL: wallet.URL().String(), 244 Status: status, 245 Accounts: wallet.Accounts(), 246 } 247 if failure != nil { 248 raw.Failure = failure.Error() 249 } 250 wallets = append(wallets, raw) 251 } 252 return wallets 253 } 254 255 //OpenWallet启动硬件钱包打开程序,建立USB 256 //连接并尝试通过提供的密码短语进行身份验证。注: 257 //the method may return an extra challenge requiring a second open (e.g. the 258 //Trezor针矩阵挑战)。 259 func (s *PrivateAccountAPI) OpenWallet(url string, passphrase *string) error { 260 wallet, err := s.am.Wallet(url) 261 if err != nil { 262 return err 263 } 264 pass := "" 265 if passphrase != nil { 266 pass = *passphrase 267 } 268 return wallet.Open(pass) 269 } 270 271 //DeriveAccount请求HD钱包派生一个新帐户,可以选择固定 272 //it for later reuse. 273 func (s *PrivateAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) { 274 wallet, err := s.am.Wallet(url) 275 if err != nil { 276 return accounts.Account{}, err 277 } 278 derivPath, err := accounts.ParseDerivationPath(path) 279 if err != nil { 280 return accounts.Account{}, err 281 } 282 if pin == nil { 283 pin = new(bool) 284 } 285 return wallet.Derive(derivPath, *pin) 286 } 287 288 //new account将创建一个新帐户并返回新帐户的地址。 289 func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error) { 290 acc, err := fetchKeystore(s.am).NewAccount(password) 291 if err == nil { 292 return acc.Address, nil 293 } 294 return common.Address{}, err 295 } 296 297 //fetchkeystore从帐户管理器检索加密的密钥库。 298 func fetchKeystore(am *accounts.Manager) *keystore.KeyStore { 299 return am.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 300 } 301 302 //importrawkey将给定的十六进制编码的ecdsa密钥存储到密钥目录中, 303 //用密码短语加密。 304 func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) { 305 key, err := crypto.HexToECDSA(privkey) 306 if err != nil { 307 return common.Address{}, err 308 } 309 acc, err := fetchKeystore(s.am).ImportECDSA(key, password) 310 return acc.Address, err 311 } 312 313 //解锁帐户将解锁与给定地址关联的帐户 314 //持续时间秒的给定密码。如果持续时间为零,则使用 315 //默认为300秒。它返回帐户是否已解锁的指示。 316 func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *uint64) (bool, error) { 317 const max = uint64(time.Duration(math.MaxInt64) / time.Second) 318 var d time.Duration 319 if duration == nil { 320 d = 300 * time.Second 321 } else if *duration > max { 322 return false, errors.New("unlock duration too large") 323 } else { 324 d = time.Duration(*duration) * time.Second 325 } 326 err := fetchKeystore(s.am).TimedUnlock(accounts.Account{Address: addr}, password, d) 327 if err != nil { 328 log.Warn("Failed account unlock attempt", "address", addr, "err", err) 329 } 330 return err == nil, err 331 } 332 333 //LockAccount解锁后将锁定与给定地址关联的帐户。 334 func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool { 335 return fetchKeystore(s.am).Lock(addr) == nil 336 } 337 338 //signtransaction设置默认值并对给定事务进行签名 339 //注:如果适用,呼叫方需要确保保持非锁定状态。 340 //并在事务提交到Tx池后释放它 341 func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args *SendTxArgs, passwd string) (*types.Transaction, error) { 342 //查找包含请求签名者的钱包 343 account := accounts.Account{Address: args.From} 344 wallet, err := s.am.Find(account) 345 if err != nil { 346 return nil, err 347 } 348 //Set some sanity defaults and terminate on failure 349 if err := args.setDefaults(ctx, s.b); err != nil { 350 return nil, err 351 } 352 //整理交易并用钱包签名 353 tx := args.toTransaction() 354 355 var chainID *big.Int 356 if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { 357 chainID = config.ChainID 358 } 359 return wallet.SignTxWithPassphrase(account, passwd, tx, chainID) 360 } 361 362 //sendTransaction将根据给定的参数和 363 //tries to sign it with the key associated with args.To. If the given passwd isn't 364 //能够解密失败的密钥。 365 func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) { 366 if args.Nonce == nil { 367 //在签名周围保持地址的互斥体,以防止同时分配 368 //对多个帐户使用同一个nonce。 369 s.nonceLock.LockAddr(args.From) 370 defer s.nonceLock.UnlockAddr(args.From) 371 } 372 signed, err := s.signTransaction(ctx, &args, passwd) 373 if err != nil { 374 log.Warn("Failed transaction send attempt", "from", args.From, "to", args.To, "value", args.Value.ToInt(), "err", err) 375 return common.Hash{}, err 376 } 377 return submitTransaction(ctx, s.b, signed) 378 } 379 380 //signTransaction将根据给定的参数和 381 //tries to sign it with the key associated with args.To. If the given passwd isn't 382 //能够解密失败的密钥。事务以RLP形式返回,而不是广播 383 //其他节点 384 func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args SendTxArgs, passwd string) (*SignTransactionResult, error) { 385 //不需要获取非CELSOCK互斥体,因为我们不会发送这个 386 //发送到事务池,但立即返回给用户 387 if args.Gas == nil { 388 return nil, fmt.Errorf("gas not specified") 389 } 390 if args.GasPrice == nil { 391 return nil, fmt.Errorf("gasPrice not specified") 392 } 393 if args.Nonce == nil { 394 return nil, fmt.Errorf("nonce not specified") 395 } 396 signed, err := s.signTransaction(ctx, &args, passwd) 397 if err != nil { 398 log.Warn("Failed transaction sign attempt", "from", args.From, "to", args.To, "value", args.Value.ToInt(), "err", err) 399 return nil, err 400 } 401 data, err := rlp.EncodeToBytes(signed) 402 if err != nil { 403 return nil, err 404 } 405 return &SignTransactionResult{data, signed}, nil 406 } 407 408 //signHash is a helper function that calculates a hash for the given message that can be 409 //安全地用于计算签名。 410 // 411 //哈希被计算为 412 //keccak256(“\x19ethereum签名消息:\n”$消息长度$消息)。 413 // 414 //这将为已签名的消息提供上下文,并防止对事务进行签名。 415 func signHash(data []byte) []byte { 416 msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data) 417 return crypto.Keccak256([]byte(msg)) 418 } 419 420 //sign计算以太坊ECDSA签名: 421 //keccack256(“\x19ethereum签名消息:\n”+len(消息)+消息) 422 // 423 //注:生成的签名符合secp256k1曲线r、s和v值, 424 //由于遗产原因,V值将为27或28。 425 // 426 //用于计算签名的密钥用给定的密码解密。 427 // 428 //https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign 429 func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { 430 //查找包含请求签名者的钱包 431 account := accounts.Account{Address: addr} 432 433 wallet, err := s.b.AccountManager().Find(account) 434 if err != nil { 435 return nil, err 436 } 437 //集合用钱包签名数据 438 signature, err := wallet.SignHashWithPassphrase(account, passwd, signHash(data)) 439 if err != nil { 440 log.Warn("Failed data sign attempt", "address", addr, "err", err) 441 return nil, err 442 } 443 signature[64] += 27 //Transform V from 0/1 to 27/28 according to the yellow paper 444 return signature, nil 445 } 446 447 //ecrecover返回用于创建签名的帐户的地址。 448 //注意,此功能与ETH标志和个人标志兼容。因此,它恢复了 449 //地址: 450 //hash=keccak256(“\x19ethereum签名消息:\n”$消息长度$消息) 451 //addr = ecrecover(hash, signature) 452 // 453 //注意,签名必须符合secp256k1曲线r、s和v值,其中 454 //the V value must be 27 or 28 for legacy reasons. 455 // 456 //https://github.com/ethereum/go-ethereum/wiki/management-apis个人\u-ecrecover 457 func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { 458 if len(sig) != 65 { 459 return common.Address{}, fmt.Errorf("signature must be 65 bytes long") 460 } 461 if sig[64] != 27 && sig[64] != 28 { 462 return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") 463 } 464 sig[64] -= 27 //将黄纸V从27/28转换为0/1 465 466 rpk, err := crypto.SigToPub(signHash(data), sig) 467 if err != nil { 468 return common.Address{}, err 469 } 470 return crypto.PubkeyToAddress(*rpk), nil 471 } 472 473 //SignandSendTransaction已重命名为SendTransaction。此方法已弃用 474 //and will be removed in the future. It primary goal is to give clients time to update. 475 func (s *PrivateAccountAPI) SignAndSendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) { 476 return s.SendTransaction(ctx, args, passwd) 477 } 478 479 //PublicBlockChainAPI提供访问以太坊区块链的API。 480 //它只提供对任何人都可以自由使用的公共数据进行操作的方法。 481 type PublicBlockChainAPI struct { 482 b Backend 483 } 484 485 //NewPublicBlockChainAPI创建新的以太坊区块链API。 486 func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI { 487 return &PublicBlockChainAPI{b} 488 } 489 490 //BlockNumber返回链头的块号。 491 func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 { 492 header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) //最新的标题应始终可用 493 return hexutil.Uint64(header.Number.Uint64()) 494 } 495 496 //GetBalance返回给定地址在 497 //给定的块编号。rpc.latestBlockNumber和rpc.pendingBlockNumber元 498 //block numbers are also allowed. 499 func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Big, error) { 500 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 501 if state == nil || err != nil { 502 return nil, err 503 } 504 return (*hexutil.Big)(state.GetBalance(address)), state.Error() 505 } 506 507 //GetProof的结果结构 508 type AccountResult struct { 509 Address common.Address `json:"address"` 510 AccountProof []string `json:"accountProof"` 511 Balance *hexutil.Big `json:"balance"` 512 CodeHash common.Hash `json:"codeHash"` 513 Nonce hexutil.Uint64 `json:"nonce"` 514 StorageHash common.Hash `json:"storageHash"` 515 StorageProof []StorageResult `json:"storageProof"` 516 } 517 type StorageResult struct { 518 Key string `json:"key"` 519 Value *hexutil.Big `json:"value"` 520 Proof []string `json:"proof"` 521 } 522 523 //GetProof returns the Merkle-proof for a given account and optionally some storage keys. 524 func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNr rpc.BlockNumber) (*AccountResult, error) { 525 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 526 if state == nil || err != nil { 527 return nil, err 528 } 529 530 storageTrie := state.StorageTrie(address) 531 storageHash := types.EmptyRootHash 532 codeHash := state.GetCodeHash(address) 533 storageProof := make([]StorageResult, len(storageKeys)) 534 535 //如果我们有一个storagetrie(这意味着帐户存在),我们可以更新storagehash 536 if storageTrie != nil { 537 storageHash = storageTrie.Hash() 538 } else { 539 //no storagetrie表示帐户不存在,因此codehash是空bytearray的哈希。 540 codeHash = crypto.Keccak256Hash(nil) 541 } 542 543 //create the proof for the storageKeys 544 for i, key := range storageKeys { 545 if storageTrie != nil { 546 proof, storageError := state.GetStorageProof(address, common.HexToHash(key)) 547 if storageError != nil { 548 return nil, storageError 549 } 550 storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), common.ToHexArray(proof)} 551 } else { 552 storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}} 553 } 554 } 555 556 //创建会计凭证 557 accountProof, proofErr := state.GetProof(address) 558 if proofErr != nil { 559 return nil, proofErr 560 } 561 562 return &AccountResult{ 563 Address: address, 564 AccountProof: common.ToHexArray(accountProof), 565 Balance: (*hexutil.Big)(state.GetBalance(address)), 566 CodeHash: codeHash, 567 Nonce: hexutil.Uint64(state.GetNonce(address)), 568 StorageHash: storageHash, 569 StorageProof: storageProof, 570 }, state.Error() 571 } 572 573 //GetBlockByNumber返回请求的块。当blocknr为-1时,链头返回。当fulltx为真时,所有 574 //transactions in the block are returned in full detail, otherwise only the transaction hash is returned. 575 func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { 576 block, err := s.b.BlockByNumber(ctx, blockNr) 577 if block != nil { 578 response, err := s.rpcOutputBlock(block, true, fullTx) 579 if err == nil && blockNr == rpc.PendingBlockNumber { 580 //挂起的块需要去掉几个字段 581 for _, field := range []string{"hash", "nonce", "miner"} { 582 response[field] = nil 583 } 584 } 585 return response, err 586 } 587 return nil, err 588 } 589 590 //GetBlockByHash返回请求的块。当fulltx为true时,块中的所有事务都将全部返回 591 //详细信息,否则只返回事务哈希。 592 func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) { 593 block, err := s.b.GetBlock(ctx, blockHash) 594 if block != nil { 595 return s.rpcOutputBlock(block, true, fullTx) 596 } 597 return nil, err 598 } 599 600 //GetUncleByBlockNumberAndIndex返回给定块哈希和索引的叔叔块。当fulltx为真时 601 //块中的所有事务都将返回完整的详细信息,否则只返回事务哈希。 602 func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) { 603 block, err := s.b.BlockByNumber(ctx, blockNr) 604 if block != nil { 605 uncles := block.Uncles() 606 if index >= hexutil.Uint(len(uncles)) { 607 log.Debug("Requested uncle not found", "number", blockNr, "hash", block.Hash(), "index", index) 608 return nil, nil 609 } 610 block = types.NewBlockWithHeader(uncles[index]) 611 return s.rpcOutputBlock(block, false, false) 612 } 613 return nil, err 614 } 615 616 //GetUncleByBlockHashAndIndex返回给定块哈希和索引的叔叔块。当fulltx为真时 617 //块中的所有事务都将返回完整的详细信息,否则只返回事务哈希。 618 func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) { 619 block, err := s.b.GetBlock(ctx, blockHash) 620 if block != nil { 621 uncles := block.Uncles() 622 if index >= hexutil.Uint(len(uncles)) { 623 log.Debug("Requested uncle not found", "number", block.Number(), "hash", blockHash, "index", index) 624 return nil, nil 625 } 626 block = types.NewBlockWithHeader(uncles[index]) 627 return s.rpcOutputBlock(block, false, false) 628 } 629 return nil, err 630 } 631 632 //GetUncleCountByBlockNumber returns number of uncles in the block for the given block number 633 func (s *PublicBlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { 634 if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { 635 n := hexutil.Uint(len(block.Uncles())) 636 return &n 637 } 638 return nil 639 } 640 641 //GetUncleCountByBlockHash返回给定块哈希的块中的叔叔数 642 func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { 643 if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { 644 n := hexutil.Uint(len(block.Uncles())) 645 return &n 646 } 647 return nil 648 } 649 650 //getcode返回给定块号状态下存储在给定地址的代码。 651 func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { 652 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 653 if state == nil || err != nil { 654 return nil, err 655 } 656 code := state.GetCode(address) 657 return code, state.Error() 658 } 659 660 //GetStorageAt返回给定地址、键和 661 //块号。The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block 662 //也允许使用数字。 663 func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { 664 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 665 if state == nil || err != nil { 666 return nil, err 667 } 668 res := state.GetState(address, common.HexToHash(key)) 669 return res[:], state.Error() 670 } 671 672 //callargs表示调用的参数。 673 type CallArgs struct { 674 From common.Address `json:"from"` 675 To *common.Address `json:"to"` 676 Gas hexutil.Uint64 `json:"gas"` 677 GasPrice hexutil.Big `json:"gasPrice"` 678 Value hexutil.Big `json:"value"` 679 Data hexutil.Bytes `json:"data"` 680 } 681 682 func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, timeout time.Duration) ([]byte, uint64, bool, error) { 683 defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) 684 685 state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 686 if state == nil || err != nil { 687 return nil, 0, false, err 688 } 689 //Set sender address or use a default if none specified 690 addr := args.From 691 if addr == (common.Address{}) { 692 if wallets := s.b.AccountManager().Wallets(); len(wallets) > 0 { 693 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 694 addr = accounts[0].Address 695 } 696 } 697 } 698 //如果未设置,则设置默认的天然气和天然气价格 699 gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt() 700 if gas == 0 { 701 gas = math.MaxUint64 / 2 702 } 703 if gasPrice.Sign() == 0 { 704 gasPrice = new(big.Int).SetUint64(defaultGasPrice) 705 } 706 707 //创建新的呼叫消息 708 msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false) 709 710 //设置上下文,以便取消调用 711 //或者,对于未计量的气体,设置一个超时上下文。 712 var cancel context.CancelFunc 713 if timeout > 0 { 714 ctx, cancel = context.WithTimeout(ctx, timeout) 715 } else { 716 ctx, cancel = context.WithCancel(ctx) 717 } 718 //Make sure the context is cancelled when the call has completed 719 //这可以确保清理资源。 720 defer cancel() 721 722 //获取EVM的新实例。 723 evm, vmError, err := s.b.GetEVM(ctx, msg, state, header) 724 if err != nil { 725 return nil, 0, false, err 726 } 727 //Wait for the context to be done and cancel the evm. 即使 728 //EVM已完成,可以取消(重复) 729 go func() { 730 <-ctx.Done() 731 evm.Cancel() 732 }() 733 734 //设置燃气池(也适用于未计量的请求) 735 //and apply the message. 736 gp := new(core.GasPool).AddGas(math.MaxUint64) 737 res, gas, failed, err := core.ApplyMessage(evm, msg, gp) 738 if err := vmError(); err != nil { 739 return nil, 0, false, err 740 } 741 return res, gas, failed, err 742 } 743 744 //调用对给定块号的状态执行给定事务。 745 //它不会在状态/区块链中进行更改,并且对执行和检索值很有用。 746 func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { 747 result, _, _, err := s.doCall(ctx, args, blockNr, 5*time.Second) 748 return (hexutil.Bytes)(result), err 749 } 750 751 //EstimateGas返回执行 752 //针对当前挂起块的给定事务。 753 func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) { 754 //Binary search the gas requirement, as it may be higher than the amount used 755 var ( 756 lo uint64 = params.TxGas - 1 757 hi uint64 758 cap uint64 759 ) 760 if uint64(args.Gas) >= params.TxGas { 761 hi = uint64(args.Gas) 762 } else { 763 //检索当前挂起的块作为气体天花板 764 block, err := s.b.BlockByNumber(ctx, rpc.PendingBlockNumber) 765 if err != nil { 766 return 0, err 767 } 768 hi = block.GasLimit() 769 } 770 cap = hi 771 772 //创建一个助手以检查气体限额是否导致可执行事务 773 executable := func(gas uint64) bool { 774 args.Gas = hexutil.Uint64(gas) 775 776 _, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, 0) 777 if err != nil || failed { 778 return false 779 } 780 return true 781 } 782 //执行二进制搜索并按可执行的气体限值接通。 783 for lo+1 < hi { 784 mid := (hi + lo) / 2 785 if !executable(mid) { 786 lo = mid 787 } else { 788 hi = mid 789 } 790 } 791 //如果交易仍以最高限额失败,则将其视为无效拒绝交易 792 if hi == cap { 793 if !executable(hi) { 794 return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction") 795 } 796 } 797 return hexutil.Uint64(hi), nil 798 } 799 800 //ExecutionResult将EVM发出的所有结构化日志分组 801 //在调试模式和事务中重播事务时 802 //执行状态、使用的气体量和返回值 803 type ExecutionResult struct { 804 Gas uint64 `json:"gas"` 805 Failed bool `json:"failed"` 806 ReturnValue string `json:"returnValue"` 807 StructLogs []StructLogRes `json:"structLogs"` 808 } 809 810 //structlogres存储EVM在重播时发出的结构化日志 811 //调试模式下的事务处理 812 type StructLogRes struct { 813 Pc uint64 `json:"pc"` 814 Op string `json:"op"` 815 Gas uint64 `json:"gas"` 816 GasCost uint64 `json:"gasCost"` 817 Depth int `json:"depth"` 818 Error error `json:"error,omitempty"` 819 Stack *[]string `json:"stack,omitempty"` 820 Memory *[]string `json:"memory,omitempty"` 821 Storage *map[string]string `json:"storage,omitempty"` 822 } 823 824 //FORMATLOGS FORMATS EVM为JSON输出返回结构化日志 825 func FormatLogs(logs []vm.StructLog) []StructLogRes { 826 formatted := make([]StructLogRes, len(logs)) 827 for index, trace := range logs { 828 formatted[index] = StructLogRes{ 829 Pc: trace.Pc, 830 Op: trace.Op.String(), 831 Gas: trace.Gas, 832 GasCost: trace.GasCost, 833 Depth: trace.Depth, 834 Error: trace.Err, 835 } 836 if trace.Stack != nil { 837 stack := make([]string, len(trace.Stack)) 838 for i, stackValue := range trace.Stack { 839 stack[i] = fmt.Sprintf("%x", math.PaddedBigBytes(stackValue, 32)) 840 } 841 formatted[index].Stack = &stack 842 } 843 if trace.Memory != nil { 844 memory := make([]string, 0, (len(trace.Memory)+31)/32) 845 for i := 0; i+32 <= len(trace.Memory); i += 32 { 846 memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32])) 847 } 848 formatted[index].Memory = &memory 849 } 850 if trace.Storage != nil { 851 storage := make(map[string]string) 852 for i, storageValue := range trace.Storage { 853 storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue) 854 } 855 formatted[index].Storage = &storage 856 } 857 } 858 return formatted 859 } 860 861 //rpcmarshalblock将给定的块转换为依赖于fulltx的rpc输出。如果incltx为真,则事务为 862 //返回。当fulltx为true时,返回的块包含完整的事务详细信息,否则它将只包含 863 //事务哈希。 864 func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { 865 head := b.Header() //复制头一次 866 fields := map[string]interface{}{ 867 "number": (*hexutil.Big)(head.Number), 868 "hash": b.Hash(), 869 "parentHash": head.ParentHash, 870 "nonce": head.Nonce, 871 "mixHash": head.MixDigest, 872 "sha3Uncles": head.UncleHash, 873 "logsBloom": head.Bloom, 874 "stateRoot": head.Root, 875 "miner": head.Coinbase, 876 "difficulty": (*hexutil.Big)(head.Difficulty), 877 "extraData": hexutil.Bytes(head.Extra), 878 "size": hexutil.Uint64(b.Size()), 879 "gasLimit": hexutil.Uint64(head.GasLimit), 880 "gasUsed": hexutil.Uint64(head.GasUsed), 881 "timestamp": (*hexutil.Big)(head.Time), 882 "transactionsRoot": head.TxHash, 883 "receiptsRoot": head.ReceiptHash, 884 } 885 886 if inclTx { 887 formatTx := func(tx *types.Transaction) (interface{}, error) { 888 return tx.Hash(), nil 889 } 890 if fullTx { 891 formatTx = func(tx *types.Transaction) (interface{}, error) { 892 return newRPCTransactionFromBlockHash(b, tx.Hash()), nil 893 } 894 } 895 txs := b.Transactions() 896 transactions := make([]interface{}, len(txs)) 897 var err error 898 for i, tx := range txs { 899 if transactions[i], err = formatTx(tx); err != nil { 900 return nil, err 901 } 902 } 903 fields["transactions"] = transactions 904 } 905 906 uncles := b.Uncles() 907 uncleHashes := make([]common.Hash, len(uncles)) 908 for i, uncle := range uncles { 909 uncleHashes[i] = uncle.Hash() 910 } 911 fields["uncles"] = uncleHashes 912 913 return fields, nil 914 } 915 916 //rpcoutputblock使用通用的输出填充符,然后添加总难度字段,这需要 917 //一个“publicBlockChainAPI”。 918 func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { 919 fields, err := RPCMarshalBlock(b, inclTx, fullTx) 920 if err != nil { 921 return nil, err 922 } 923 fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(b.Hash())) 924 return fields, err 925 } 926 927 //rpc transaction表示将序列化为事务的rpc表示形式的事务 928 type RPCTransaction struct { 929 BlockHash common.Hash `json:"blockHash"` 930 BlockNumber *hexutil.Big `json:"blockNumber"` 931 From common.Address `json:"from"` 932 Gas hexutil.Uint64 `json:"gas"` 933 GasPrice *hexutil.Big `json:"gasPrice"` 934 Hash common.Hash `json:"hash"` 935 Input hexutil.Bytes `json:"input"` 936 Nonce hexutil.Uint64 `json:"nonce"` 937 To *common.Address `json:"to"` 938 TransactionIndex hexutil.Uint `json:"transactionIndex"` 939 Value *hexutil.Big `json:"value"` 940 V *hexutil.Big `json:"v"` 941 R *hexutil.Big `json:"r"` 942 S *hexutil.Big `json:"s"` 943 } 944 945 //NewRpcTransaction返回将序列化到RPC的事务 946 //表示法,使用给定的位置元数据集(如果可用)。 947 func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64) *RPCTransaction { 948 var signer types.Signer = types.FrontierSigner{} 949 if tx.Protected() { 950 signer = types.NewEIP155Signer(tx.ChainId()) 951 } 952 from, _ := types.Sender(signer, tx) 953 v, r, s := tx.RawSignatureValues() 954 955 result := &RPCTransaction{ 956 From: from, 957 Gas: hexutil.Uint64(tx.Gas()), 958 GasPrice: (*hexutil.Big)(tx.GasPrice()), 959 Hash: tx.Hash(), 960 Input: hexutil.Bytes(tx.Data()), 961 Nonce: hexutil.Uint64(tx.Nonce()), 962 To: tx.To(), 963 Value: (*hexutil.Big)(tx.Value()), 964 V: (*hexutil.Big)(v), 965 R: (*hexutil.Big)(r), 966 S: (*hexutil.Big)(s), 967 } 968 if blockHash != (common.Hash{}) { 969 result.BlockHash = blockHash 970 result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) 971 result.TransactionIndex = hexutil.Uint(index) 972 } 973 return result 974 } 975 976 //NewRpcPendingTransaction返回一个挂起的事务,该事务将序列化为RPC表示形式 977 func newRPCPendingTransaction(tx *types.Transaction) *RPCTransaction { 978 return newRPCTransaction(tx, common.Hash{}, 0, 0) 979 } 980 981 //newRpcTransactionFromBlockIndex返回将序列化到RPC表示形式的事务。 982 func newRPCTransactionFromBlockIndex(b *types.Block, index uint64) *RPCTransaction { 983 txs := b.Transactions() 984 if index >= uint64(len(txs)) { 985 return nil 986 } 987 return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index) 988 } 989 990 //newrpcrawTransactionFromBlockIndex返回给定块和事务索引的事务的字节。 991 func newRPCRawTransactionFromBlockIndex(b *types.Block, index uint64) hexutil.Bytes { 992 txs := b.Transactions() 993 if index >= uint64(len(txs)) { 994 return nil 995 } 996 blob, _ := rlp.EncodeToBytes(txs[index]) 997 return blob 998 } 999 1000 //newRpcTransactionFromBlockHash返回将序列化到RPC表示形式的事务。 1001 func newRPCTransactionFromBlockHash(b *types.Block, hash common.Hash) *RPCTransaction { 1002 for idx, tx := range b.Transactions() { 1003 if tx.Hash() == hash { 1004 return newRPCTransactionFromBlockIndex(b, uint64(idx)) 1005 } 1006 } 1007 return nil 1008 } 1009 1010 //PublicTransactionPoolapi公开RPC接口的方法 1011 type PublicTransactionPoolAPI struct { 1012 b Backend 1013 nonceLock *AddrLocker 1014 } 1015 1016 //NewPublicTransactionPoolapi使用特定于事务池的方法创建新的RPC服务。 1017 func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransactionPoolAPI { 1018 return &PublicTransactionPoolAPI{b, nonceLock} 1019 } 1020 1021 //GetBlockTransactionCountByNumber返回具有给定块号的块中的事务数。 1022 func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { 1023 if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { 1024 n := hexutil.Uint(len(block.Transactions())) 1025 return &n 1026 } 1027 return nil 1028 } 1029 1030 //GetBlockTransactionCountByHash返回具有给定哈希的块中的事务数。 1031 func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { 1032 if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { 1033 n := hexutil.Uint(len(block.Transactions())) 1034 return &n 1035 } 1036 return nil 1037 } 1038 1039 //GetTransactionByBlockNumberAndIndex返回给定块号和索引的事务。 1040 func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction { 1041 if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { 1042 return newRPCTransactionFromBlockIndex(block, uint64(index)) 1043 } 1044 return nil 1045 } 1046 1047 //GetTransactionByBlockHashAndIndex返回给定块哈希和索引的事务。 1048 func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction { 1049 if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { 1050 return newRPCTransactionFromBlockIndex(block, uint64(index)) 1051 } 1052 return nil 1053 } 1054 1055 //GetRawTransactionByBlockNumberAndIndex返回给定块号和索引的事务字节。 1056 func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes { 1057 if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { 1058 return newRPCRawTransactionFromBlockIndex(block, uint64(index)) 1059 } 1060 return nil 1061 } 1062 1063 //GetRawTransactionByBlockHashAndIndex返回给定块哈希和索引的事务字节。 1064 func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes { 1065 if block, _ := s.b.GetBlock(ctx, blockHash); block != nil { 1066 return newRPCRawTransactionFromBlockIndex(block, uint64(index)) 1067 } 1068 return nil 1069 } 1070 1071 //GetTransactionCount返回给定地址为给定块号发送的事务数。 1072 func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) { 1073 //为包含挂起事务的nonce请求事务池 1074 if blockNr == rpc.PendingBlockNumber { 1075 nonce, err := s.b.GetPoolNonce(ctx, address) 1076 if err != nil { 1077 return nil, err 1078 } 1079 return (*hexutil.Uint64)(&nonce), nil 1080 } 1081 //解析块号并使用其状态请求nonce 1082 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 1083 if state == nil || err != nil { 1084 return nil, err 1085 } 1086 nonce := state.GetNonce(address) 1087 return (*hexutil.Uint64)(&nonce), state.Error() 1088 } 1089 1090 //GetTransactionByHash返回给定哈希的事务 1091 func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) *RPCTransaction { 1092 //尝试返回已完成的事务 1093 if tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash); tx != nil { 1094 return newRPCTransaction(tx, blockHash, blockNumber, index) 1095 } 1096 //没有完成的事务,请尝试从池中检索它 1097 if tx := s.b.GetPoolTransaction(hash); tx != nil { 1098 return newRPCPendingTransaction(tx) 1099 } 1100 //事务未知,因此返回 1101 return nil 1102 } 1103 1104 //GetRawTransactionByHash返回给定哈希的事务字节。 1105 func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { 1106 var tx *types.Transaction 1107 1108 //检索已完成的事务,或以其他方式合并 1109 if tx, _, _, _ = rawdb.ReadTransaction(s.b.ChainDb(), hash); tx == nil { 1110 if tx = s.b.GetPoolTransaction(hash); tx == nil { 1111 //找不到事务,中止 1112 return nil, nil 1113 } 1114 } 1115 //序列化到rlp并返回 1116 return rlp.EncodeToBytes(tx) 1117 } 1118 1119 //GetTransactionReceipt返回给定事务哈希的事务回执。 1120 func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { 1121 tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash) 1122 if tx == nil { 1123 return nil, nil 1124 } 1125 receipts, err := s.b.GetReceipts(ctx, blockHash) 1126 if err != nil { 1127 return nil, err 1128 } 1129 if len(receipts) <= int(index) { 1130 return nil, nil 1131 } 1132 receipt := receipts[index] 1133 1134 var signer types.Signer = types.FrontierSigner{} 1135 if tx.Protected() { 1136 signer = types.NewEIP155Signer(tx.ChainId()) 1137 } 1138 from, _ := types.Sender(signer, tx) 1139 1140 fields := map[string]interface{}{ 1141 "blockHash": blockHash, 1142 "blockNumber": hexutil.Uint64(blockNumber), 1143 "transactionHash": hash, 1144 "transactionIndex": hexutil.Uint64(index), 1145 "from": from, 1146 "to": tx.To(), 1147 "gasUsed": hexutil.Uint64(receipt.GasUsed), 1148 "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), 1149 "contractAddress": nil, 1150 "logs": receipt.Logs, 1151 "logsBloom": receipt.Bloom, 1152 } 1153 1154 //分配收据状态或过账状态。 1155 if len(receipt.PostState) > 0 { 1156 fields["root"] = hexutil.Bytes(receipt.PostState) 1157 } else { 1158 fields["status"] = hexutil.Uint(receipt.Status) 1159 } 1160 if receipt.Logs == nil { 1161 fields["logs"] = [][]*types.Log{} 1162 } 1163 //如果contractAddress为20 0x0字节,则假定它不是合同创建 1164 if receipt.ContractAddress != (common.Address{}) { 1165 fields["contractAddress"] = receipt.ContractAddress 1166 } 1167 return fields, nil 1168 } 1169 1170 //sign是一个助手函数,它使用给定地址的私钥对事务进行签名。 1171 func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { 1172 //查找包含请求签名者的钱包 1173 account := accounts.Account{Address: addr} 1174 1175 wallet, err := s.b.AccountManager().Find(account) 1176 if err != nil { 1177 return nil, err 1178 } 1179 //请求钱包签署交易 1180 var chainID *big.Int 1181 if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { 1182 chainID = config.ChainID 1183 } 1184 return wallet.SignTx(account, tx, chainID) 1185 } 1186 1187 //sendtxargs表示向事务池中sumbit新事务的参数。 1188 type SendTxArgs struct { 1189 From common.Address `json:"from"` 1190 To *common.Address `json:"to"` 1191 Gas *hexutil.Uint64 `json:"gas"` 1192 GasPrice *hexutil.Big `json:"gasPrice"` 1193 Value *hexutil.Big `json:"value"` 1194 Nonce *hexutil.Uint64 `json:"nonce"` 1195 //出于向后兼容性的原因,我们接受“数据”和“输入”。“输入”是 1196 //更新的名称,应为客户首选。 1197 Data *hexutil.Bytes `json:"data"` 1198 Input *hexutil.Bytes `json:"input"` 1199 } 1200 1201 //setdefaults是一个帮助函数,它为未指定的tx字段填充默认值。 1202 func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error { 1203 if args.Gas == nil { 1204 args.Gas = new(hexutil.Uint64) 1205 *(*uint64)(args.Gas) = 90000 1206 } 1207 if args.GasPrice == nil { 1208 price, err := b.SuggestPrice(ctx) 1209 if err != nil { 1210 return err 1211 } 1212 args.GasPrice = (*hexutil.Big)(price) 1213 } 1214 if args.Value == nil { 1215 args.Value = new(hexutil.Big) 1216 } 1217 if args.Nonce == nil { 1218 nonce, err := b.GetPoolNonce(ctx, args.From) 1219 if err != nil { 1220 return err 1221 } 1222 args.Nonce = (*hexutil.Uint64)(&nonce) 1223 } 1224 if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) { 1225 return errors.New(`Both "data" and "input" are set and not equal. Please use "input" to pass transaction call data.`) 1226 } 1227 if args.To == nil { 1228 //合同创建 1229 var input []byte 1230 if args.Data != nil { 1231 input = *args.Data 1232 } else if args.Input != nil { 1233 input = *args.Input 1234 } 1235 if len(input) == 0 { 1236 return errors.New(`contract creation without any data provided`) 1237 } 1238 } 1239 return nil 1240 } 1241 1242 func (args *SendTxArgs) toTransaction() *types.Transaction { 1243 var input []byte 1244 if args.Data != nil { 1245 input = *args.Data 1246 } else if args.Input != nil { 1247 input = *args.Input 1248 } 1249 if args.To == nil { 1250 return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) 1251 } 1252 return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input) 1253 } 1254 1255 //SubmitTransaction是一个助手函数,它将Tx提交到TxPool并记录消息。 1256 func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) { 1257 if err := b.SendTx(ctx, tx); err != nil { 1258 return common.Hash{}, err 1259 } 1260 if tx.To() == nil { 1261 signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number()) 1262 from, err := types.Sender(signer, tx) 1263 if err != nil { 1264 return common.Hash{}, err 1265 } 1266 addr := crypto.CreateAddress(from, tx.Nonce()) 1267 log.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex()) 1268 } else { 1269 log.Info("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To()) 1270 } 1271 return tx.Hash(), nil 1272 } 1273 1274 //sendTransaction为给定参数创建一个事务,对其签名并将其提交给 1275 //事务池。 1276 func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) { 1277 1278 //查找包含请求签名者的钱包 1279 account := accounts.Account{Address: args.From} 1280 1281 wallet, err := s.b.AccountManager().Find(account) 1282 if err != nil { 1283 return common.Hash{}, err 1284 } 1285 1286 if args.Nonce == nil { 1287 //在签名周围保持地址的互斥体,以防止同时分配 1288 //对多个帐户使用同一个nonce。 1289 s.nonceLock.LockAddr(args.From) 1290 defer s.nonceLock.UnlockAddr(args.From) 1291 } 1292 1293 //设置一些健全的默认值并在失败时终止 1294 if err := args.setDefaults(ctx, s.b); err != nil { 1295 return common.Hash{}, err 1296 } 1297 //整理交易并用钱包签名 1298 tx := args.toTransaction() 1299 1300 var chainID *big.Int 1301 if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { 1302 chainID = config.ChainID 1303 } 1304 signed, err := wallet.SignTx(account, tx, chainID) 1305 if err != nil { 1306 return common.Hash{}, err 1307 } 1308 return submitTransaction(ctx, s.b, signed) 1309 } 1310 1311 //sendrawtransaction将把签名的事务添加到事务池中。 1312 //发送方负责签署事务并使用正确的nonce。 1313 func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) { 1314 tx := new(types.Transaction) 1315 if err := rlp.DecodeBytes(encodedTx, tx); err != nil { 1316 return common.Hash{}, err 1317 } 1318 return submitTransaction(ctx, s.b, tx) 1319 } 1320 1321 //sign为以下项计算ECDSA签名: 1322 //keccack256(“\x19ethereum签名消息:\n”+len(消息)+消息)。 1323 // 1324 //注:生成的签名符合secp256k1曲线r、s和v值, 1325 //由于遗产原因,V值将为27或28。 1326 // 1327 //必须解锁与addr关联的帐户。 1328 // 1329 //https://github.com/ethereum/wiki/wiki/json-rpc eth_符号 1330 func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) { 1331 //查找包含请求签名者的钱包 1332 account := accounts.Account{Address: addr} 1333 1334 wallet, err := s.b.AccountManager().Find(account) 1335 if err != nil { 1336 return nil, err 1337 } 1338 //用钱包在请求的哈希表上签名 1339 signature, err := wallet.SignHash(account, signHash(data)) 1340 if err == nil { 1341 signature[64] += 27 //根据黄纸将V从0/1转换为27/28 1342 } 1343 return signature, err 1344 } 1345 1346 //SignTransactionResult表示RLP编码的签名事务。 1347 type SignTransactionResult struct { 1348 Raw hexutil.Bytes `json:"raw"` 1349 Tx *types.Transaction `json:"tx"` 1350 } 1351 1352 //SignTransaction将使用From帐户对给定的事务进行签名。 1353 //节点需要具有与 1354 //从地址发出,需要解锁。 1355 func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) { 1356 if args.Gas == nil { 1357 return nil, fmt.Errorf("gas not specified") 1358 } 1359 if args.GasPrice == nil { 1360 return nil, fmt.Errorf("gasPrice not specified") 1361 } 1362 if args.Nonce == nil { 1363 return nil, fmt.Errorf("nonce not specified") 1364 } 1365 if err := args.setDefaults(ctx, s.b); err != nil { 1366 return nil, err 1367 } 1368 tx, err := s.sign(args.From, args.toTransaction()) 1369 if err != nil { 1370 return nil, err 1371 } 1372 data, err := rlp.EncodeToBytes(tx) 1373 if err != nil { 1374 return nil, err 1375 } 1376 return &SignTransactionResult{data, tx}, nil 1377 } 1378 1379 //PendingtTransactions返回事务池中的事务 1380 //并且有一个发件人地址,该地址是此节点管理的帐户之一。 1381 func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, error) { 1382 pending, err := s.b.GetPoolTransactions() 1383 if err != nil { 1384 return nil, err 1385 } 1386 accounts := make(map[common.Address]struct{}) 1387 for _, wallet := range s.b.AccountManager().Wallets() { 1388 for _, account := range wallet.Accounts() { 1389 accounts[account.Address] = struct{}{} 1390 } 1391 } 1392 transactions := make([]*RPCTransaction, 0, len(pending)) 1393 for _, tx := range pending { 1394 var signer types.Signer = types.HomesteadSigner{} 1395 if tx.Protected() { 1396 signer = types.NewEIP155Signer(tx.ChainId()) 1397 } 1398 from, _ := types.Sender(signer, tx) 1399 if _, exists := accounts[from]; exists { 1400 transactions = append(transactions, newRPCPendingTransaction(tx)) 1401 } 1402 } 1403 return transactions, nil 1404 } 1405 1406 //重新发送接受现有交易和新的天然气价格和限额。它将移除 1407 //从池中指定的交易,并重新插入新的天然气价格和限额。 1408 func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) { 1409 if sendArgs.Nonce == nil { 1410 return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec") 1411 } 1412 if err := sendArgs.setDefaults(ctx, s.b); err != nil { 1413 return common.Hash{}, err 1414 } 1415 matchTx := sendArgs.toTransaction() 1416 pending, err := s.b.GetPoolTransactions() 1417 if err != nil { 1418 return common.Hash{}, err 1419 } 1420 1421 for _, p := range pending { 1422 var signer types.Signer = types.HomesteadSigner{} 1423 if p.Protected() { 1424 signer = types.NewEIP155Signer(p.ChainId()) 1425 } 1426 wantSigHash := signer.Hash(matchTx) 1427 1428 if pFrom, err := types.Sender(signer, p); err == nil && pFrom == sendArgs.From && signer.Hash(p) == wantSigHash { 1429 //比赛。重新签署并发送交易。 1430 if gasPrice != nil && (*big.Int)(gasPrice).Sign() != 0 { 1431 sendArgs.GasPrice = gasPrice 1432 } 1433 if gasLimit != nil && *gasLimit != 0 { 1434 sendArgs.Gas = gasLimit 1435 } 1436 signedTx, err := s.sign(sendArgs.From, sendArgs.toTransaction()) 1437 if err != nil { 1438 return common.Hash{}, err 1439 } 1440 if err = s.b.SendTx(ctx, signedTx); err != nil { 1441 return common.Hash{}, err 1442 } 1443 return signedTx.Hash(), nil 1444 } 1445 } 1446 1447 return common.Hash{}, fmt.Errorf("Transaction %#x not found", matchTx.Hash()) 1448 } 1449 1450 //publicDebugAPI是公开的以太坊API集合 1451 //调试终结点。 1452 type PublicDebugAPI struct { 1453 b Backend 1454 } 1455 1456 //NewPublicDebugGapi为公共调试方法创建新的API定义 1457 //以太坊服务。 1458 func NewPublicDebugAPI(b Backend) *PublicDebugAPI { 1459 return &PublicDebugAPI{b: b} 1460 } 1461 1462 //getblockrlp检索为单个块编码的rlp。 1463 func (api *PublicDebugAPI) GetBlockRlp(ctx context.Context, number uint64) (string, error) { 1464 block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) 1465 if block == nil { 1466 return "", fmt.Errorf("block #%d not found", number) 1467 } 1468 encoded, err := rlp.EncodeToBytes(block) 1469 if err != nil { 1470 return "", err 1471 } 1472 return fmt.Sprintf("%x", encoded), nil 1473 } 1474 1475 //printblock检索一个块并返回其漂亮的打印表单。 1476 func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) { 1477 block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) 1478 if block == nil { 1479 return "", fmt.Errorf("block #%d not found", number) 1480 } 1481 return spew.Sdump(block), nil 1482 } 1483 1484 //seed hash检索块的种子哈希。 1485 func (api *PublicDebugAPI) SeedHash(ctx context.Context, number uint64) (string, error) { 1486 block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) 1487 if block == nil { 1488 return "", fmt.Errorf("block #%d not found", number) 1489 } 1490 return fmt.Sprintf("0x%x", ethash.SeedHash(number)), nil 1491 } 1492 1493 //privatedebugapi是在私有服务器上公开的以太坊API的集合。 1494 //调试终结点。 1495 type PrivateDebugAPI struct { 1496 b Backend 1497 } 1498 1499 //new private debug api为专用调试方法创建新的API定义 1500 //以太坊服务。 1501 func NewPrivateDebugAPI(b Backend) *PrivateDebugAPI { 1502 return &PrivateDebugAPI{b: b} 1503 } 1504 1505 //chainedbproperty返回链数据库的leveldb属性。 1506 func (api *PrivateDebugAPI) ChaindbProperty(property string) (string, error) { 1507 ldb, ok := api.b.ChainDb().(interface { 1508 LDB() *leveldb.DB 1509 }) 1510 if !ok { 1511 return "", fmt.Errorf("chaindbProperty does not work for memory databases") 1512 } 1513 if property == "" { 1514 property = "leveldb.stats" 1515 } else if !strings.HasPrefix(property, "leveldb.") { 1516 property = "leveldb." + property 1517 } 1518 return ldb.LDB().GetProperty(property) 1519 } 1520 1521 func (api *PrivateDebugAPI) ChaindbCompact() error { 1522 ldb, ok := api.b.ChainDb().(interface { 1523 LDB() *leveldb.DB 1524 }) 1525 if !ok { 1526 return fmt.Errorf("chaindbCompact does not work for memory databases") 1527 } 1528 for b := byte(0); b < 255; b++ { 1529 log.Info("Compacting chain database", "range", fmt.Sprintf("0x%0.2X-0x%0.2X", b, b+1)) 1530 err := ldb.LDB().CompactRange(util.Range{Start: []byte{b}, Limit: []byte{b + 1}}) 1531 if err != nil { 1532 log.Error("Database compaction failed", "err", err) 1533 return err 1534 } 1535 } 1536 return nil 1537 } 1538 1539 //sethead将区块链的头倒回到上一个块。 1540 func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) { 1541 api.b.SetHead(uint64(number)) 1542 } 1543 1544 //PublicNetAPI提供与网络相关的RPC方法 1545 type PublicNetAPI struct { 1546 net *p2p.Server 1547 networkVersion uint64 1548 } 1549 1550 //NewPublicNetAPI创建新的NET API实例。 1551 func NewPublicNetAPI(net *p2p.Server, networkVersion uint64) *PublicNetAPI { 1552 return &PublicNetAPI{net, networkVersion} 1553 } 1554 1555 //侦听返回节点是否正在侦听网络连接的指示。 1556 func (s *PublicNetAPI) Listening() bool { 1557 return true //总是倾听 1558 } 1559 1560 //PeerCount返回连接的对等数 1561 func (s *PublicNetAPI) PeerCount() hexutil.Uint { 1562 return hexutil.Uint(s.net.PeerCount()) 1563 } 1564 1565 //version返回当前的以太坊协议版本。 1566 func (s *PublicNetAPI) Version() string { 1567 return fmt.Sprintf("%d", s.networkVersion) 1568 } 1569