// Hash returns the SHA3 hash of the envelope, calculating it if not yet done. func (self *Envelope) Hash() common.Hash { if (self.hash == common.Hash{}) { enc, _ := rlp.EncodeToBytes(self) self.hash = crypto.Sha3Hash(enc) } return self.hash }
// GetRlp returns the RLP encoding of one receipt from the list. func (r Receipts) GetRlp(i int) []byte { bytes, err := rlp.EncodeToBytes(r[i]) if err != nil { panic(err) } return bytes }
// updateNode inserts - potentially overwriting - a node into the peer database. func (db *nodeDB) updateNode(node *Node) error { blob, err := rlp.EncodeToBytes(node) if err != nil { return err } return db.lvl.Put(makeKey(node.ID, nodeDBDiscoverRoot), blob, nil) }
// RlpEncode implements common.RlpEncode required for SHA3 derivation. func (r *Receipt) RlpEncode() []byte { bytes, err := rlp.EncodeToBytes(r) if err != nil { panic(err) } return bytes }
// ExpectMsg reads a message from r and verifies that its // code and encoded RLP content match the provided values. // If content is nil, the payload is discarded and not verified. func ExpectMsg(r MsgReader, code uint64, content interface{}) error { msg, err := r.ReadMsg() if err != nil { return err } if msg.Code != code { return fmt.Errorf("message code mismatch: got %d, expected %d", msg.Code, code) } if content == nil { return msg.Discard() } else { contentEnc, err := rlp.EncodeToBytes(content) if err != nil { panic("content encode error: " + err.Error()) } if int(msg.Size) != len(contentEnc) { return fmt.Errorf("message size mismatch: got %d, want %d", msg.Size, len(contentEnc)) } actualContent, err := ioutil.ReadAll(msg.Payload) if err != nil { return err } if !bytes.Equal(actualContent, contentEnc) { return fmt.Errorf("message payload mismatch:\ngot: %x\nwant: %x", actualContent, contentEnc) } } return nil }
func (c *StateObject) setAddr(addr []byte, value common.Hash) { v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) if err != nil { // if RLPing failed we better panic and not fail silently. This would be considered a consensus issue panic(err) } c.trie.Update(addr, v) }
// GetBlockRlp retrieves the RLP encoded for of a single block. func (api *PublicDebugAPI) GetBlockRlp(number uint64) (string, error) { block := api.eth.BlockChain().GetBlockByNumber(number) if block == nil { return "", fmt.Errorf("block #%d not found", number) } encoded, err := rlp.EncodeToBytes(block) if err != nil { return "", err } return fmt.Sprintf("%x", encoded), nil }
// Update the given state object and apply it to state trie func (self *StateDB) UpdateStateObject(stateObject *StateObject) { if len(stateObject.code) > 0 { self.db.Put(stateObject.codeHash, stateObject.code) } addr := stateObject.Address() data, err := rlp.EncodeToBytes(stateObject) if err != nil { panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err)) } self.trie.Update(addr[:], data) }
// WriteTd serializes the total difficulty of a block into the database. func WriteTd(db ethdb.Database, hash common.Hash, td *big.Int) error { data, err := rlp.EncodeToBytes(td) if err != nil { return err } key := append(append(blockPrefix, hash.Bytes()...), tdSuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store block total difficulty into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block total difficulty [%x…]: %v", hash.Bytes()[:4], td) return nil }
// WriteBody serializes the body of a block into the database. func WriteBody(db ethdb.Database, hash common.Hash, body *types.Body) error { data, err := rlp.EncodeToBytes(body) if err != nil { return err } key := append(append(blockPrefix, hash.Bytes()...), bodySuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store block body into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4]) return nil }
// WriteHeader serializes a block header into the database. func WriteHeader(db ethdb.Database, header *types.Header) error { data, err := rlp.EncodeToBytes(header) if err != nil { return err } key := append(append(blockPrefix, header.Hash().Bytes()...), headerSuffix...) if err := db.Put(key, data); err != nil { glog.Fatalf("failed to store header into database: %v", err) return err } glog.V(logger.Debug).Infof("stored header #%v [%x…]", header.Number, header.Hash().Bytes()[:4]) return nil }
// Prove constructs a merkle proof for key. The result contains all // encoded nodes on the path to the value at key. The value itself is // also included in the last node and can be retrieved by verifying // the proof. // // If the trie does not contain a value for key, the returned proof // contains all nodes of the longest existing prefix of the key // (at least the root node), ending with the node that proves the // absence of the key. func (t *Trie) Prove(key []byte) []rlp.RawValue { // Collect all nodes on the path to key. key = compactHexDecode(key) nodes := []node{} tn := t.root for len(key) > 0 && tn != nil { switch n := tn.(type) { case shortNode: if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { // The trie doesn't contain the key. tn = nil } else { tn = n.Val key = key[len(n.Key):] } nodes = append(nodes, n) case fullNode: tn = n[key[0]] key = key[1:] nodes = append(nodes, n) case hashNode: var err error tn, err = t.resolveHash(n, nil, nil) if err != nil { if glog.V(logger.Error) { glog.Errorf("Unhandled trie error: %v", err) } return nil } default: panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) } } if t.hasher == nil { t.hasher = newHasher() } proof := make([]rlp.RawValue, 0, len(nodes)) for i, n := range nodes { // Don't bother checking for errors here since hasher panics // if encoding doesn't work and we're not writing to any database. n, _ = t.hasher.replaceChildren(n, nil) hn, _ := t.hasher.store(n, nil, false) if _, ok := hn.(hashNode); ok || i == 0 { // If the node's database encoding is a hash (or is the // root node), it becomes a proof element. enc, _ := rlp.EncodeToBytes(n) proof = append(proof, enc) } } return proof }
// WriteTransactions stores the transactions associated with a specific block // into the given database. Beside writing the transaction, the function also // stores a metadata entry along with the transaction, detailing the position // of this within the blockchain. func WriteTransactions(db ethdb.Database, block *types.Block) error { batch := db.NewBatch() // Iterate over each transaction and encode it with its metadata for i, tx := range block.Transactions() { // Encode and queue up the transaction for storage data, err := rlp.EncodeToBytes(tx) if err != nil { return err } if err := batch.Put(tx.Hash().Bytes(), data); err != nil { return err } // Encode and queue up the transaction metadata for storage meta := struct { BlockHash common.Hash BlockIndex uint64 Index uint64 }{ BlockHash: block.Hash(), BlockIndex: block.NumberU64(), Index: uint64(i), } data, err = rlp.EncodeToBytes(meta) if err != nil { return err } if err := batch.Put(append(tx.Hash().Bytes(), txMetaSuffix...), data); err != nil { return err } } // Write the scheduled data into the database if err := batch.Write(); err != nil { glog.Fatalf("failed to store transactions into database: %v", err) return err } return nil }
// WriteBlockReceipts stores all the transaction receipts belonging to a block // as a single receipt slice. This is used during chain reorganisations for // rescheduling dropped transactions. func WriteBlockReceipts(db ethdb.Database, hash common.Hash, receipts types.Receipts) error { // Convert the receipts into their storage form and serialize them storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) for i, receipt := range receipts { storageReceipts[i] = (*types.ReceiptForStorage)(receipt) } bytes, err := rlp.EncodeToBytes(storageReceipts) if err != nil { return err } // Store the flattened receipt slice if err := db.Put(append(blockReceiptsPrefix, hash.Bytes()...), bytes); err != nil { glog.Fatalf("failed to store block receipts into database: %v", err) return err } glog.V(logger.Debug).Infof("stored block receipts [%x…]", hash.Bytes()[:4]) return nil }
func (tx *Transaction) String() string { var from, to string if f, err := tx.From(); err != nil { from = "[invalid sender]" } else { from = fmt.Sprintf("%x", f[:]) } if tx.data.Recipient == nil { to = "[contract creation]" } else { to = fmt.Sprintf("%x", tx.data.Recipient[:]) } enc, _ := rlp.EncodeToBytes(&tx.data) return fmt.Sprintf(` TX(%x) Contract: %v From: %s To: %s Nonce: %v GasPrice: %v GasLimit %v Value: %v Data: 0x%x V: 0x%x R: 0x%x S: 0x%x Hex: %x `, tx.Hash(), len(tx.data.Recipient) == 0, from, to, tx.data.AccountNonce, tx.data.Price, tx.data.GasLimit, tx.data.Amount, tx.data.Payload, tx.data.V, tx.data.R, tx.data.S, enc, ) }
func (rw *rlpxFrameRW) WriteMsg(msg Msg) error { ptype, _ := rlp.EncodeToBytes(msg.Code) // write header headbuf := make([]byte, 32) fsize := uint32(len(ptype)) + msg.Size if fsize > maxUint24 { return errors.New("message size overflows uint24") } putInt24(fsize, headbuf) // TODO: check overflow copy(headbuf[3:], zeroHeader) rw.enc.XORKeyStream(headbuf[:16], headbuf[:16]) // first half is now encrypted // write header MAC copy(headbuf[16:], updateMAC(rw.egressMAC, rw.macCipher, headbuf[:16])) if _, err := rw.conn.Write(headbuf); err != nil { return err } // write encrypted frame, updating the egress MAC hash with // the data written to conn. tee := cipher.StreamWriter{S: rw.enc, W: io.MultiWriter(rw.conn, rw.egressMAC)} if _, err := tee.Write(ptype); err != nil { return err } if _, err := io.Copy(tee, msg.Payload); err != nil { return err } if padding := fsize % 16; padding > 0 { if _, err := tee.Write(zero16[:16-padding]); err != nil { return err } } // write frame MAC. egress MAC hash is up to date because // frame content was written to it as well. fmacseed := rw.egressMAC.Sum(nil) mac := updateMAC(rw.egressMAC, rw.macCipher, fmacseed) _, err := rw.conn.Write(mac) return err }
func addMipmapBloomBins(db ethdb.Database) (err error) { const mipmapVersion uint = 2 // check if the version is set. We ignore data for now since there's // only one version so we can easily ignore it for now var data []byte data, _ = db.Get([]byte("setting-mipmap-version")) if len(data) > 0 { var version uint if err := rlp.DecodeBytes(data, &version); err == nil && version == mipmapVersion { return nil } } defer func() { if err == nil { var val []byte val, err = rlp.EncodeToBytes(mipmapVersion) if err == nil { err = db.Put([]byte("setting-mipmap-version"), val) } return } }() latestBlock := core.GetBlock(db, core.GetHeadBlockHash(db)) if latestBlock == nil { // clean database return } tstart := time.Now() glog.V(logger.Info).Infoln("upgrading db log bloom bins") for i := uint64(0); i <= latestBlock.NumberU64(); i++ { hash := core.GetCanonicalHash(db, i) if (hash == common.Hash{}) { return fmt.Errorf("chain db corrupted. Could not find block %d.", i) } core.WriteMipmapBloom(db, i, core.GetBlockReceipts(db, hash)) } glog.V(logger.Info).Infoln("upgrade completed in", time.Since(tstart)) return nil }
// WriteReceipts stores a batch of transaction receipts into the database. func WriteReceipts(db ethdb.Database, receipts types.Receipts) error { batch := db.NewBatch() // Iterate over all the receipts and queue them for database injection for _, receipt := range receipts { storageReceipt := (*types.ReceiptForStorage)(receipt) data, err := rlp.EncodeToBytes(storageReceipt) if err != nil { return err } if err := batch.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data); err != nil { return err } } // Write the scheduled data into the database if err := batch.Write(); err != nil { glog.Fatalf("failed to store receipts into database: %v", err) return err } return nil }
// SignTransaction will sign the given transaction with the from account. // The node needs to have the private key of the account corresponding with // the given from address and it needs to be unlocked. func (s *PublicTransactionPoolAPI) SignTransaction(args *SignTransactionArgs) (*SignTransactionResult, error) { if args.Gas == nil { args.Gas = rpc.NewHexNumber(defaultGas) } if args.GasPrice == nil { args.GasPrice = rpc.NewHexNumber(defaultGasPrice) } if args.Value == nil { args.Value = rpc.NewHexNumber(0) } s.txMu.Lock() defer s.txMu.Unlock() if args.Nonce == nil { args.Nonce = rpc.NewHexNumber(s.txPool.State().GetNonce(args.From)) } var tx *types.Transaction contractCreation := (args.To == common.Address{}) if contractCreation { tx = types.NewContractCreation(args.Nonce.Uint64(), args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data)) } else { tx = types.NewTransaction(args.Nonce.Uint64(), args.To, args.Value.BigInt(), args.Gas.BigInt(), args.GasPrice.BigInt(), common.FromHex(args.Data)) } signedTx, err := s.sign(args.From, tx) if err != nil { return nil, err } data, err := rlp.EncodeToBytes(signedTx) if err != nil { return nil, err } return &SignTransactionResult{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil }
// ReportBlock reports the block to the block reporting tool found at // badblocks.ethdev.com func ReportBlock(block *types.Block, err error) { if DisableBadBlockReporting { return } const url = "https://badblocks.ethdev.com" blockRlp, _ := rlp.EncodeToBytes(block) data := map[string]interface{}{ "block": common.Bytes2Hex(blockRlp), "errortype": err.Error(), "hints": map[string]interface{}{ "receipts": "NYI", "vmtrace": "NYI", }, } jsonStr, _ := json.Marshal(map[string]interface{}{"method": "eth_badBlock", "params": []interface{}{data}, "id": "1", "jsonrpc": "2.0"}) req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { glog.V(logger.Error).Infoln("POST err:", err) return } defer resp.Body.Close() if glog.V(logger.Debug) { glog.Infoln("response Status:", resp.Status) glog.Infoln("response Headers:", resp.Header) body, _ := ioutil.ReadAll(resp.Body) glog.Infoln("response Body:", string(body)) } }
// handleMsg is invoked whenever an inbound message is received from a remote // peer. The remote connection is torn down upon returning any error. func (pm *ProtocolManager) handleMsg(p *peer) error { // Read the next message from the remote peer, and ensure it's fully consumed msg, err := p.rw.ReadMsg() if err != nil { return err } if msg.Size > ProtocolMaxMsgSize { return errResp(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize) } defer msg.Discard() // Handle the message depending on its contents switch { case msg.Code == StatusMsg: // Status messages should never arrive after the handshake return errResp(ErrExtraStatusMsg, "uncontrolled status message") case p.version < eth62 && msg.Code == GetBlockHashesMsg: // Retrieve the number of hashes to return and from which origin hash var request getBlockHashesData if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } if request.Amount > uint64(downloader.MaxHashFetch) { request.Amount = uint64(downloader.MaxHashFetch) } // Retrieve the hashes from the block chain and return them hashes := pm.blockchain.GetBlockHashesFromHash(request.Hash, request.Amount) if len(hashes) == 0 { glog.V(logger.Debug).Infof("invalid block hash %x", request.Hash.Bytes()[:4]) } return p.SendBlockHashes(hashes) case p.version < eth62 && msg.Code == GetBlockHashesFromNumberMsg: // Retrieve and decode the number of hashes to return and from which origin number var request getBlockHashesFromNumberData if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } if request.Amount > uint64(downloader.MaxHashFetch) { request.Amount = uint64(downloader.MaxHashFetch) } // Calculate the last block that should be retrieved, and short circuit if unavailable last := pm.blockchain.GetBlockByNumber(request.Number + request.Amount - 1) if last == nil { last = pm.blockchain.CurrentBlock() request.Amount = last.NumberU64() - request.Number + 1 } if last.NumberU64() < request.Number { return p.SendBlockHashes(nil) } // Retrieve the hashes from the last block backwards, reverse and return hashes := []common.Hash{last.Hash()} hashes = append(hashes, pm.blockchain.GetBlockHashesFromHash(last.Hash(), request.Amount-1)...) for i := 0; i < len(hashes)/2; i++ { hashes[i], hashes[len(hashes)-1-i] = hashes[len(hashes)-1-i], hashes[i] } return p.SendBlockHashes(hashes) case p.version < eth62 && msg.Code == BlockHashesMsg: // A batch of hashes arrived to one of our previous requests var hashes []common.Hash if err := msg.Decode(&hashes); err != nil { break } // Deliver them all to the downloader for queuing err := pm.downloader.DeliverHashes(p.id, hashes) if err != nil { glog.V(logger.Debug).Infoln(err) } case p.version < eth62 && msg.Code == GetBlocksMsg: // Decode the retrieval message msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) if _, err := msgStream.List(); err != nil { return err } // Gather blocks until the fetch or network limits is reached var ( hash common.Hash bytes common.StorageSize blocks []*types.Block ) for len(blocks) < downloader.MaxBlockFetch && bytes < softResponseLimit { //Retrieve the hash of the next block err := msgStream.Decode(&hash) if err == rlp.EOL { break } else if err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Retrieve the requested block, stopping if enough was found if block := pm.blockchain.GetBlock(hash); block != nil { blocks = append(blocks, block) bytes += block.Size() } } return p.SendBlocks(blocks) case p.version < eth62 && msg.Code == BlocksMsg: // Decode the arrived block message var blocks []*types.Block if err := msg.Decode(&blocks); err != nil { glog.V(logger.Detail).Infoln("Decode error", err) blocks = nil } // Update the receive timestamp of each block for _, block := range blocks { block.ReceivedAt = msg.ReceivedAt } // Filter out any explicitly requested blocks, deliver the rest to the downloader if blocks := pm.fetcher.FilterBlocks(blocks); len(blocks) > 0 { pm.downloader.DeliverBlocks(p.id, blocks) } // Block header query, collect the requested headers and reply case p.version >= eth62 && msg.Code == GetBlockHeadersMsg: // Decode the complex header query var query getBlockHeadersData if err := msg.Decode(&query); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } hashMode := query.Origin.Hash != (common.Hash{}) // Gather headers until the fetch or network limits is reached var ( bytes common.StorageSize headers []*types.Header unknown bool ) for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit && len(headers) < downloader.MaxHeaderFetch { // Retrieve the next header satisfying the query var origin *types.Header if hashMode { origin = pm.blockchain.GetHeader(query.Origin.Hash) } else { origin = pm.blockchain.GetHeaderByNumber(query.Origin.Number) } if origin == nil { break } headers = append(headers, origin) bytes += estHeaderRlpSize // Advance to the next header of the query switch { case query.Origin.Hash != (common.Hash{}) && query.Reverse: // Hash based traversal towards the genesis block for i := 0; i < int(query.Skip)+1; i++ { if header := pm.blockchain.GetHeader(query.Origin.Hash); header != nil { query.Origin.Hash = header.ParentHash } else { unknown = true break } } case query.Origin.Hash != (common.Hash{}) && !query.Reverse: // Hash based traversal towards the leaf block if header := pm.blockchain.GetHeaderByNumber(origin.Number.Uint64() + query.Skip + 1); header != nil { if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash { query.Origin.Hash = header.Hash() } else { unknown = true } } else { unknown = true } case query.Reverse: // Number based traversal towards the genesis block if query.Origin.Number >= query.Skip+1 { query.Origin.Number -= (query.Skip + 1) } else { unknown = true } case !query.Reverse: // Number based traversal towards the leaf block query.Origin.Number += (query.Skip + 1) } } return p.SendBlockHeaders(headers) case p.version >= eth62 && msg.Code == BlockHeadersMsg: // A batch of headers arrived to one of our previous requests var headers []*types.Header if err := msg.Decode(&headers); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Filter out any explicitly requested headers, deliver the rest to the downloader filter := len(headers) == 1 if filter { headers = pm.fetcher.FilterHeaders(headers, time.Now()) } if len(headers) > 0 || !filter { err := pm.downloader.DeliverHeaders(p.id, headers) if err != nil { glog.V(logger.Debug).Infoln(err) } } case p.version >= eth62 && msg.Code == GetBlockBodiesMsg: // Decode the retrieval message msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) if _, err := msgStream.List(); err != nil { return err } // Gather blocks until the fetch or network limits is reached var ( hash common.Hash bytes int bodies []rlp.RawValue ) for bytes < softResponseLimit && len(bodies) < downloader.MaxBlockFetch { // Retrieve the hash of the next block if err := msgStream.Decode(&hash); err == rlp.EOL { break } else if err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Retrieve the requested block body, stopping if enough was found if data := pm.blockchain.GetBodyRLP(hash); len(data) != 0 { bodies = append(bodies, data) bytes += len(data) } } return p.SendBlockBodiesRLP(bodies) case p.version >= eth62 && msg.Code == BlockBodiesMsg: // A batch of block bodies arrived to one of our previous requests var request blockBodiesData if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Deliver them all to the downloader for queuing trasactions := make([][]*types.Transaction, len(request)) uncles := make([][]*types.Header, len(request)) for i, body := range request { trasactions[i] = body.Transactions uncles[i] = body.Uncles } // Filter out any explicitly requested bodies, deliver the rest to the downloader if trasactions, uncles := pm.fetcher.FilterBodies(trasactions, uncles, time.Now()); len(trasactions) > 0 || len(uncles) > 0 { err := pm.downloader.DeliverBodies(p.id, trasactions, uncles) if err != nil { glog.V(logger.Debug).Infoln(err) } } case p.version >= eth63 && msg.Code == GetNodeDataMsg: // Decode the retrieval message msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) if _, err := msgStream.List(); err != nil { return err } // Gather state data until the fetch or network limits is reached var ( hash common.Hash bytes int data [][]byte ) for bytes < softResponseLimit && len(data) < downloader.MaxStateFetch { // Retrieve the hash of the next state entry if err := msgStream.Decode(&hash); err == rlp.EOL { break } else if err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Retrieve the requested state entry, stopping if enough was found if entry, err := pm.chaindb.Get(hash.Bytes()); err == nil { data = append(data, entry) bytes += len(entry) } } return p.SendNodeData(data) case p.version >= eth63 && msg.Code == NodeDataMsg: // A batch of node state data arrived to one of our previous requests var data [][]byte if err := msg.Decode(&data); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Deliver all to the downloader if err := pm.downloader.DeliverNodeData(p.id, data); err != nil { glog.V(logger.Debug).Infof("failed to deliver node state data: %v", err) } case p.version >= eth63 && msg.Code == GetReceiptsMsg: // Decode the retrieval message msgStream := rlp.NewStream(msg.Payload, uint64(msg.Size)) if _, err := msgStream.List(); err != nil { return err } // Gather state data until the fetch or network limits is reached var ( hash common.Hash bytes int receipts []rlp.RawValue ) for bytes < softResponseLimit && len(receipts) < downloader.MaxReceiptFetch { // Retrieve the hash of the next block if err := msgStream.Decode(&hash); err == rlp.EOL { break } else if err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Retrieve the requested block's receipts, skipping if unknown to us results := core.GetBlockReceipts(pm.chaindb, hash) if results == nil { if header := pm.blockchain.GetHeader(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { continue } } // If known, encode and queue for response packet if encoded, err := rlp.EncodeToBytes(results); err != nil { glog.V(logger.Error).Infof("failed to encode receipt: %v", err) } else { receipts = append(receipts, encoded) bytes += len(encoded) } } return p.SendReceiptsRLP(receipts) case p.version >= eth63 && msg.Code == ReceiptsMsg: // A batch of receipts arrived to one of our previous requests var receipts [][]*types.Receipt if err := msg.Decode(&receipts); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } // Deliver all to the downloader if err := pm.downloader.DeliverReceipts(p.id, receipts); err != nil { glog.V(logger.Debug).Infof("failed to deliver receipts: %v", err) } case msg.Code == NewBlockHashesMsg: // Retrieve and deseralize the remote new block hashes notification type announce struct { Hash common.Hash Number uint64 } var announces = []announce{} if p.version < eth62 { // We're running the old protocol, make block number unknown (0) var hashes []common.Hash if err := msg.Decode(&hashes); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } for _, hash := range hashes { announces = append(announces, announce{hash, 0}) } } else { // Otherwise extract both block hash and number var request newBlockHashesData if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } for _, block := range request { announces = append(announces, announce{block.Hash, block.Number}) } } // Mark the hashes as present at the remote node for _, block := range announces { p.MarkBlock(block.Hash) p.SetHead(block.Hash) } // Schedule all the unknown hashes for retrieval unknown := make([]announce, 0, len(announces)) for _, block := range announces { if !pm.blockchain.HasBlock(block.Hash) { unknown = append(unknown, block) } } for _, block := range unknown { if p.version < eth62 { pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), p.RequestBlocks, nil, nil) } else { pm.fetcher.Notify(p.id, block.Hash, block.Number, time.Now(), nil, p.RequestOneHeader, p.RequestBodies) } } case msg.Code == NewBlockMsg: // Retrieve and decode the propagated block var request newBlockData if err := msg.Decode(&request); err != nil { return errResp(ErrDecode, "%v: %v", msg, err) } if err := request.Block.ValidateFields(); err != nil { return errResp(ErrDecode, "block validation %v: %v", msg, err) } request.Block.ReceivedAt = msg.ReceivedAt // Mark the peer as owning the block and schedule it for import p.MarkBlock(request.Block.Hash()) p.SetHead(request.Block.Hash()) pm.fetcher.Enqueue(p.id, request.Block) // Update the peers total difficulty if needed, schedule a download if gapped if request.TD.Cmp(p.Td()) > 0 { p.SetTd(request.TD) td := pm.blockchain.GetTd(pm.blockchain.CurrentBlock().Hash()) if request.TD.Cmp(new(big.Int).Add(td, request.Block.Difficulty())) > 0 { go pm.synchronise(p) } } case msg.Code == TxMsg: // Transactions arrived, parse all of them and deliver to the pool var txs []*types.Transaction if err := msg.Decode(&txs); err != nil { return errResp(ErrDecode, "msg %v: %v", msg, err) } for i, tx := range txs { // Validate and mark the remote transaction if tx == nil { return errResp(ErrDecode, "transaction %d is nil", i) } p.MarkTransaction(tx.Hash()) } pm.txpool.AddTransactions(txs) default: return errResp(ErrInvalidMsgCode, "%v", msg.Code) } return nil }
// GetRlp implements Rlpable and returns the i'th element of s in rlp func (s Transactions) GetRlp(i int) []byte { enc, _ := rlp.EncodeToBytes(s[i]) return enc }
// Creates an ethereum address given the bytes and the nonce func CreateAddress(b common.Address, nonce uint64) common.Address { data, _ := rlp.EncodeToBytes([]interface{}{b, nonce}) return common.BytesToAddress(Sha3(data)[12:]) //return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:] }
// rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce. func (self *Envelope) rlpWithoutNonce() []byte { enc, _ := rlp.EncodeToBytes([]interface{}{self.Expiry, self.TTL, self.Topics, self.Data}) return enc }
// WriteBlockChainVersion writes vsn as the version number to db. func WriteBlockChainVersion(db ethdb.Database, vsn int) { enc, _ := rlp.EncodeToBytes(uint(vsn)) db.Put([]byte("BlockchainVersion"), enc) }