MineInfo State::mine(uint _msTimeout) { // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); // TODO: Miner class that keeps dagger between mine calls (or just non-polling mining). MineInfo ret = m_dagger.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout); if (ret.completed) { // Got it! // Commit to disk. m_db.commit(); // Compile block: RLPStream ret; ret.appendList(3); m_currentBlock.fillStream(ret, true); ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentUncles); ret.swapOut(m_currentBytes); m_currentBlock.hash = sha3(m_currentBytes); cnote << "Mined " << m_currentBlock.hash << "(parent: " << m_currentBlock.parentHash << ")"; } else m_currentBytes.clear(); return ret; }
void Raft::voteBlockEnd() { uint64_t now = utcTime(); if(m_idUnVoted.size() >= (nodeCount()+1)/2 || now > m_consensusTimeOut){ LOG(TRACE) << "m_idUnVoted.size()=" << m_idUnVoted.size() << ",m_idVoted.size()=" << m_idVoted.size() << ",nodeCount()=" << nodeCount(); reSet(); return; } if(raftFinished != m_consensusState && m_idVoted.size() > nodeCount()/2){ LOG(TRACE) << "Vote succed, m_blockBytes.size() = " << m_blockBytes.size(); try{ if(m_onSealGenerated){ std::vector<std::pair<u256, Signature>> sig_list; for(size_t i = 0; i < m_miner_list.size(); i++){ if(m_idVoted.count(m_miner_list[i])){ sig_list.push_back(std::make_pair(u256(i), m_idVoted[m_miner_list[i]])); } } BlockHeader header(m_blockBytes); RLP r(m_blockBytes); RLPStream rs; rs.appendList(5); rs.appendRaw(r[0].data()); // header rs.appendRaw(r[1].data()); // tx rs.appendRaw(r[2].data()); // uncles rs.append(header.hash()); // hash rs.appendVector(sig_list); // sign_list bytes blockBytes; rs.swapOut(blockBytes); LOG(TRACE) << "Vote_succed: idx.count blockBytes.size() = " << blockBytes.size() << ",header.number()=" << header.number() << ",header.hash()=" << header.hash(WithoutSeal) << ",generl_id = " << (m_votedId == NodeID() ? id() : m_votedId) << ",m_node_idx=" << static_cast<uint64_t>(m_node_idx); m_onSealGenerated(blockBytes, m_votedId == NodeID()); } }catch(...){ LOG(ERROR) << "m_consensusFinishedFunc run err"; } m_consensusState = raftFinished; m_consensusTimeOut = utcTime() + m_consensusTimeInterval; return;
h256 RLPXDatagramFace::sign(Secret const& _k) { assert(packetType()); RLPStream rlpxstream; // rlpxstream.appendRaw(toPublic(_k).asBytes()); // for mdc-based signature rlpxstream.appendRaw(bytes(1, packetType())); // prefix by 1 byte for type streamRLP(rlpxstream); bytes rlpxBytes(rlpxstream.out()); bytesConstRef rlpx(&rlpxBytes); h256 sighash(dev::sha3(rlpx)); // H(type||data) Signature sig = dev::sign(_k, sighash); // S(H(type||data)) data.resize(h256::size + Signature::size + rlpx.size()); bytesRef rlpxHash(&data[0], h256::size); bytesRef rlpxSig(&data[h256::size], Signature::size); bytesRef rlpxPayload(&data[h256::size + Signature::size], rlpx.size()); sig.ref().copyTo(rlpxSig); rlpx.copyTo(rlpxPayload); bytesConstRef signedRLPx(&data[h256::size], data.size() - h256::size); h256 hash(dev::sha3(signedRLPx)); hash.ref().copyTo(rlpxHash); return hash; }
void WhisperPeer::sendMessages() { RLPStream amalg; unsigned n = 0; Guard l(x_unseen); while (m_unseen.size()) { auto p = *m_unseen.begin(); m_unseen.erase(m_unseen.begin()); host()->streamMessage(p.second, amalg); n++; } if (n) { RLPStream s; prep(s); s.appendList(n + 1) << MessagesPacket; s.appendRaw(amalg.out(), n); sealAndSend(s); } else // just pause if no messages to send this_thread::sleep_for(chrono::milliseconds(100)); }
void BlockHeader::streamRLP(RLPStream &_s, IncludeSeal _i) const { if (_i != OnlySeal) { _s.appendList(BlockHeader::BasicFields + (_i == WithoutSeal ? 0 : m_seal.size())); BlockHeader::streamRLPFields(_s); } if (_i != WithoutSeal) for (unsigned i = 0; i < m_seal.size(); ++i) _s.appendRaw(m_seal[i]); }
void State::completeMine() { cdebug << "Completing mine!"; // Got it! // Compile block: RLPStream ret; ret.appendList(3); m_currentBlock.streamRLP(ret, WithNonce); ret.appendRaw(m_currentTxs); ret.appendRaw(m_currentUncles); ret.swapOut(m_currentBytes); m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; // Quickly reset the transactions. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. m_transactions.clear(); m_receipts.clear(); m_transactionSet.clear(); m_lastTx = m_db; }
bool State::amIJustParanoid(BlockChain const& _bc) { commitToMine(_bc); // Update difficulty according to timestamp. m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); // Compile block: RLPStream block; block.appendList(3); m_currentBlock.streamRLP(block, WithNonce); block.appendRaw(m_currentTxs); block.appendRaw(m_currentUncles); State s(*this); s.resetCurrent(); try { cnote << "PARANOIA root:" << s.rootHash(); // s.m_currentBlock.populate(&block.out(), false); // s.m_currentBlock.verifyInternals(&block.out()); s.enact(&block.out(), _bc, false); // don't check nonce for this since we haven't mined it yet. s.cleanup(false); return true; } catch (Exception const& _e) { cwarn << "Bad block: " << diagnostic_information(_e); } catch (std::exception const& _e) { cwarn << "Bad block: " << _e.what(); } return false; }
bool PeerServer::sync(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o) { bool ret = ensureInitialised(_bc, _tq); if (sync()) ret = true; if (m_mode == NodeMode::Full) { for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it) if (_tq.import(*it)) {}//ret = true; // just putting a transaction in the queue isn't enough to change the state - it might have an invalid nonce... else m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on. m_incomingTransactions.clear(); auto h = _bc.currentHash(); bool resendAll = (h != m_latestBlockSent); // Send any new transactions. for (auto j: m_peers) if (auto p = j.second.lock()) { bytes b; uint n = 0; for (auto const& i: _tq.transactions()) if ((!m_transactionsSent.count(i.first) && !p->m_knownTransactions.count(i.first)) || p->m_requireTransactions || resendAll) { b += i.second; ++n; m_transactionsSent.insert(i.first); } if (n) { RLPStream ts; PeerSession::prep(ts); ts.appendList(n + 1) << TransactionsPacket; ts.appendRaw(b, n).swapOut(b); seal(b); p->send(&b); } p->m_knownTransactions.clear(); p->m_requireTransactions = false; } // Send any new blocks. if (h != m_latestBlockSent) { // TODO: find where they diverge and send complete new branch. RLPStream ts; PeerSession::prep(ts); ts.appendList(2) << BlocksPacket; bytes b; ts.appendRaw(_bc.block(_bc.currentHash())).swapOut(b); seal(b); for (auto j: m_peers) if (auto p = j.second.lock()) { if (!p->m_knownBlocks.count(_bc.currentHash())) p->send(&b); p->m_knownBlocks.clear(); } } m_latestBlockSent = h; for (int accepted = 1, n = 0; accepted; ++n) { accepted = 0; if (m_incomingBlocks.size()) for (auto it = prev(m_incomingBlocks.end());; --it) { try { _bc.import(*it, _o); it = m_incomingBlocks.erase(it); ++accepted; ret = true; } catch (UnknownParent) { // Don't (yet) know its parent. Leave it for later. m_unknownParentBlocks.push_back(*it); it = m_incomingBlocks.erase(it); } catch (...) { // Some other error - erase it. it = m_incomingBlocks.erase(it); } if (it == m_incomingBlocks.begin()) break; } if (!n && accepted) { for (auto i: m_unknownParentBlocks) m_incomingBlocks.push_back(i); m_unknownParentBlocks.clear(); } } // Connect to additional peers while (m_peers.size() < m_idealPeerCount) { if (m_freePeers.empty()) { if (chrono::steady_clock::now() > m_lastPeersRequest + chrono::seconds(10)) { RLPStream s; bytes b; (PeerSession::prep(s).appendList(1) << GetPeersPacket).swapOut(b); seal(b); for (auto const& i: m_peers) if (auto p = i.second.lock()) if (p->isOpen()) p->send(&b); m_lastPeersRequest = chrono::steady_clock::now(); } if (!m_accepting) ensureAccepting(); break; } auto x = time(0) % m_freePeers.size(); m_incomingPeers[m_freePeers[x]].second++; connect(m_incomingPeers[m_freePeers[x]].first); m_freePeers.erase(m_freePeers.begin() + x); } } // platform for consensus of social contract. // restricts your freedom but does so fairly. and that's the value proposition. // guarantees that everyone else respect the rules of the system. (i.e. obeys laws). // We'll keep at most twice as many as is ideal, halfing what counts as "too young to kill" until we get there. for (uint old = 15000; m_peers.size() > m_idealPeerCount * 2 && old > 100; old /= 2) while (m_peers.size() > m_idealPeerCount) { // look for worst peer to kick off // first work out how many are old enough to kick off. shared_ptr<PeerSession> worst; unsigned agedPeers = 0; for (auto i: m_peers) if (auto p = i.second.lock()) if ((m_mode != NodeMode::PeerServer || p->m_caps != 0x01) && chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers. { ++agedPeers; if ((!worst || p->m_rating < worst->m_rating || (p->m_rating == worst->m_rating && p->m_connect > worst->m_connect))) // kill older ones worst = p; } if (!worst || agedPeers <= m_idealPeerCount) break; worst->disconnect(TooManyPeers); } return ret; }
void State::commitToMine(BlockChain const& _bc) { uncommitToMine(); // cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); #ifdef ETH_PARANOIA commit(); cnote << "Pre-reward stateRoot:" << m_state.root(); #endif m_lastTx = m_db; Addresses uncleAddresses; RLPStream unclesData; unsigned unclesCount = 0; if (m_previousBlock.number != 0) { // Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations. // cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl; set<h256> knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); auto p = m_previousBlock.parentHash; for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash(); ++gen, p = _bc.details(p).parent) { auto us = _bc.details(p).children; assert(us.size() >= 1); // must be at least 1 child of our grandparent - it's our own parent! for (auto const& u: us) if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about. { BlockInfo ubi(_bc.block(u)); ubi.streamRLP(unclesData, WithNonce); ++unclesCount; uncleAddresses.push_back(ubi.coinbaseAddress); } } } MemoryDB tm; GenericTrieDB<MemoryDB> transactionsTrie(&tm); transactionsTrie.init(); MemoryDB rm; GenericTrieDB<MemoryDB> receiptsTrie(&rm); receiptsTrie.init(); RLPStream txs; txs.appendList(m_transactions.size()); for (unsigned i = 0; i < m_transactions.size(); ++i) { RLPStream k; k << i; RLPStream receiptrlp; m_receipts[i].streamRLP(receiptrlp); receiptsTrie.insert(&k.out(), &receiptrlp.out()); RLPStream txrlp; m_transactions[i].streamRLP(txrlp); transactionsTrie.insert(&k.out(), &txrlp.out()); txs.appendRaw(txrlp.out()); } txs.swapOut(m_currentTxs); RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); m_currentBlock.transactionsRoot = transactionsTrie.root(); m_currentBlock.receiptsRoot = receiptsTrie.root(); m_currentBlock.logBloom = logBloom(); m_currentBlock.sha3Uncles = sha3(m_currentUncles); // Apply rewards last of all. applyRewards(uncleAddresses); // Commit any and all changes to the trie that are in the cache, then update the state root accordingly. commit(); // cnote << "Post-reward stateRoot:" << m_state.root().abridged(); // cnote << m_state; // cnote << *this; m_currentBlock.gasUsed = gasUsed(); m_currentBlock.stateRoot = m_state.root(); m_currentBlock.parentHash = m_previousBlock.hash; }