Fabcoin Core  0.16.2
P2P Digital Currency
BlockChainInsert.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU 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  cpp-ethereum 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 General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
23 #include <boost/filesystem/operations.hpp>
24 #include <boost/test/unit_test.hpp>
25 #include <boost/filesystem.hpp>
26 #include <libdevcore/FileSystem.h>
28 #include <libethereum/BlockChain.h>
29 #include <libethereum/Block.h>
33 using namespace std;
34 using namespace json_spirit;
35 using namespace dev;
36 using namespace dev::eth;
37 
38 namespace dev {
39 
40 namespace test {
41 
42 BOOST_FIXTURE_TEST_SUITE(BlockChainInsertTests, TestOutputHelper)
43 
45 {
46 public:
47  TestClient(Secret const& _authority):
48  m_path(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()) + "-" + FixedHash<4>::random().hex()),
49  m_stateDB(State::openDB(m_path, h256())),
51  {
52  sealer()->setOption("authority", rlp(_authority.makeInsecure()));
53  sealer()->setOption("authorities", rlpList(toAddress(_authority)));
54  sealer()->onSealGenerated([&](bytes const& sealedHeader){
55  sealed = sealedHeader;
56  });
57  }
58 
59  void seal(Block& _block)
60  {
61  cdebug << "seal";
62  sealed = bytes();
63  cdebug << "commiting...";
64  _block.commitToSeal(m_bc);
65  cdebug << (void*)sealer();
66  sealer()->generateSeal(_block.info());
67  cdebug << toHex((bytes)sealed);
68  sealed.waitNot({});
69  cdebug << toHex((bytes)sealed);
70  _block.sealBlock(sealed);
71  }
72 
73  BlockChain& bc() { return m_bc; }
74  OverlayDB& db() { return m_stateDB; }
75 
76  void sealAndImport(Block& _block)
77  {
78  seal(_block);
79  cnote << "Importing sealed: " << sha3(sealed);
80  cdebug << "importing..." << RLP(_block.blockData());
81  m_bc.import(_block.blockData(), m_stateDB);
82 // cdebug << "done.";
83  }
84 
85  void import(Block const& _block)
86  {
87  m_bc.import(_block.blockData(), m_stateDB);
88  }
89 
90  void insert(Block const& _block, BlockChain const& _bcSource)
91  {
92  BlockHeader bi(&_block.blockData());
93  bytes receipts = _bcSource.receipts(bi.hash()).rlp();
94  m_bc.insert(_block.blockData(), &receipts);
95  assert(m_bc.isKnown(bi.hash(), false));
96  }
97 
98 private:
99  SealEngineFace* sealer() const { return m_bc.sealEngine(); }
100 
101  string m_path;
105 };
106 
108 {
109  h256s ret;
110  RLP r(_node);
111  if (r.itemCount() == 17)
112  // branch
113  {
114  for (RLP i: r)
115  if (i.size() == 32)
116  ret.push_back(i.toHash<h256>());
117  }
118  else if (r.itemCount() == 2)
119  // extension or terminal
120  if (r[1].size() == 32) // TODO: check whether it's really an extension node, or whether it's just an terminal-node with 32 bytes of data.
121  ret.push_back(r[1].toHash<h256>());
122  // TODO: include
123  return ret;
124 }
125 
126 void syncStateTrie(bytesConstRef _block, OverlayDB const& _dbSource, OverlayDB& _dbDest)
127 {
128  BlockHeader bi(_block);
129  cnote << "Root is " << bi.stateRoot();
130 
131  h256s todo = {bi.stateRoot()};
132  vector<bytes> data;
133  while (!todo.empty())
134  {
135  h256 h = todo.back();
136  todo.pop_back();
137  bytes d = asBytes(_dbSource.lookup(h));
138  cnote << h << ": " << RLP(&d);
139  auto s = subs(&d);
140  cnote << " More: " << s;
141  todo += s;
142  // push final value.
143  data.push_back(d);
144  }
145  for (auto const& d: data)
146  {
147  cnote << "Inserting " << sha3(d);
148  _dbDest.insert(sha3(d), &d);
149  }
150 }
151 
152 BOOST_AUTO_TEST_CASE(bcBasicInsert)
153 {
154  BasicAuthority::init();
155  BasicAuthority::init();
156 
157  if (g_logVerbosity != -1)
158  g_logVerbosity = 4;
159 
160  KeyPair me = Secret(sha3("Gav Wood"));
161  KeyPair myMiner = Secret(sha3("Gav's Miner"));
162 
163  TestClient tcFull(me.secret());
164  TestClient tcLight(me.secret());
165 
166  Block block = tcFull.bc().genesisBlock(tcFull.db());
167  block.setAuthor(myMiner.address());
168 
169  // Sync up - this won't do much until we use the last state.
170  block.sync(tcFull.bc());
171 
172  // Seal and import into full client.
173  cnote << "First seal and import";
174  tcFull.sealAndImport(block);
175 
176  // Insert into light client.
177  cnote << "Insert into light";
178  tcLight.insert(block, tcFull.bc());
179 
180  // Sync light client's state trie.
181  cnote << "Syncing light state";
182  syncStateTrie(&block.blockData(), tcFull.db(), tcLight.db());
183 
184  // Mine another block. Importing into both should work now.
185 
186  // Prep block for a transaction.
187  cnote << "Prep block";
188  block.sync(tcFull.bc());
189  cnote << block.state();
190  while (utcTime() < block.info().timestamp())
191  this_thread::sleep_for(chrono::milliseconds(100));
192 
193  // Inject a transaction to transfer funds from miner to me.
194  Transaction t(1000, 10000, 100000, me.address(), bytes(), block.transactionsFrom(myMiner.address()), myMiner.secret());
195  assert(t.sender() == myMiner.address());
196  cnote << "Execute transaction";
197  block.execute(tcFull.bc().lastHashes(), t);
198  cnote << block.state();
199 
200  // Seal and import into both.
201  cnote << "Seal and import";
202  tcFull.sealAndImport(block);
203  cnote << "Import into light";
204  tcLight.import(block);
205 
206  cnote << tcFull.bc();
207  cnote << tcLight.bc();
208  block.sync(tcFull.bc());
209 
210  cnote << block.state();
211  cnote << tcFull.bc().dumpDatabase();
212  cnote << tcLight.bc().dumpDatabase();
213  BOOST_REQUIRE_EQUAL(tcFull.bc().dumpDatabase(), tcLight.bc().dumpDatabase());
214 }
215 
217 
218 }
219 }
220 
bytes const & blockData() const
Get the complete current block, including valid nonce.
Definition: Block.h:276
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
h256s subs(bytesConstRef _node)
Definition: Log.h:35
Implements the blockchain database.
Definition: BlockChain.h:105
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
Definition: RLP.h:467
h256 const & stateRoot() const
Definition: BlockHeader.h:158
size_t itemCount() const
Definition: RLP.h:118
uint64_t utcTime()
Get the current time in seconds since the epoch in UTC.
Definition: Common.cpp:64
Encapsulation of a block header.
Definition: BlockHeader.h:95
#define h(i)
Definition: sha.cpp:736
Simple class that represents a "key pair".
Definition: Common.h:150
BlockReceipts receipts(h256 const &_hash) const
Get the transactions&#39; receipts of a block (or the most recent mined if none given).
Definition: BlockChain.h:165
size_t count
Definition: ExecStats.cpp:37
SealEngineFace * sealer() const
SecureFixedHash< 32 > Secret
Definition: Common.h:35
void commitToSeal(BlockChain const &_bc, bytes const &_extraData={})
Prepares the current state for mining.
Definition: Block.cpp:695
std::hash for asio::adress
Definition: Common.h:323
assert(len-trim+(2 *lenIndices)<=WIDTH)
void syncStateTrie(bytesConstRef _block, OverlayDB const &_dbSource, OverlayDB &_dbDest)
Secret const & secret() const
Definition: Common.h:167
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
Definition: CommonData.cpp:141
void sealAndImport(Block &_block)
Model of an Ethereum state, essentially a facade for the trie.
Definition: State.h:161
void seal(Block &_block)
std::string lookup(h256 const &_h) const
Definition: OverlayDB.cpp:120
#define cdebug
Definition: Log.h:302
Active model of a block within the block chain.
Definition: Block.h:73
_N toHash(int _flags=Strict) const
Definition: RLP.h:298
FixedHash< T > const & makeInsecure() const
Definition: FixedHash.h:253
void insert(Block const &_block, BlockChain const &_bcSource)
std::vector< byte > bytes
Definition: Common.h:75
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string&#39;s (byte) data.
Definition: CommonData.h:92
bool sealBlock(bytes const &_header)
Pass in a properly sealed header matching this block.
Definition: Block.h:268
void insert(h256 const &_h, bytesConstRef _v)
Definition: MemoryDB.cpp:85
Encodes a transaction, ready to be exported to or freshly imported from RLP.
Definition: Transaction.h:84
Address toAddress(Public const &_public)
Convert a public key to address.
Definition: Common.cpp:87
bytes rlpList()
Export a list of items in RLP format, returning a byte array.
Definition: RLP.h:470
Address const & address() const
Retrieve the associated address of the public key.
Definition: Common.h:173
int g_logVerbosity
The logging system&#39;s current verbosity.
Definition: Log.cpp:37
void setAuthor(Address const &_id)
Set the author address for any transactions we do and rewards we get.
Definition: Block.h:118
#define cnote
Definition: Log.h:303
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
uint8_t const size_t const size
Definition: sha3.h:20
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
Notified< bytes > sealed
#define d(i)
Definition: sha.cpp:732
std::vector< h256 > h256s
Definition: FixedHash.h:345
BOOST_AUTO_TEST_CASE(bcBasicInsert)
uint8_t const * data
Definition: sha3.h:19
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
std::string const c_genesisInfoTestBasicAuthority
Definition: GenesisInfo.cpp:29
BlockHeader const & info() const
Get the header information on the present block.
Definition: Block.h:279
TestClient(Secret const &_authority)
Helper functions to work with json::spirit and test files.