mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	blockchain tests
Conflicts: test/block.cpp
This commit is contained in:
		
							parent
							
								
									bdab1475d6
								
							
						
					
					
						commit
						298919844b
					
				
							
								
								
									
										45
									
								
								bcBlockChainTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								bcBlockChainTestFiller.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | { | ||||||
|  |     "minDifficulty" : { | ||||||
|  |         "genesisBlockHeader" : { | ||||||
|  |             "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", | ||||||
|  |             "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", | ||||||
|  |             "difficulty" : "1023", | ||||||
|  |             "extraData" : "42", | ||||||
|  |             "gasLimit" : "100000000", | ||||||
|  |             "gasUsed" : "0", | ||||||
|  |             "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", | ||||||
|  |             "number" : "0", | ||||||
|  |             "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", | ||||||
|  |             "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", | ||||||
|  |             "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", | ||||||
|  |             "timestamp" : "0x54c98c81", | ||||||
|  |             "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", | ||||||
|  |             "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "10000000000000", | ||||||
|  |                 "nonce" : "0", | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "blocks" : [ | ||||||
|  |             { | ||||||
|  |                 "transactions" : [ | ||||||
|  |                     { | ||||||
|  |                         "data" : "", | ||||||
|  |                         "gasLimit" : "80000050", | ||||||
|  |                         "gasPrice" : "1", | ||||||
|  |                         "nonce" : "0", | ||||||
|  |                         "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |                         "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |                         "value" : "10" | ||||||
|  |                     } | ||||||
|  |                 ], | ||||||
|  |                 "uncleHeaders" : [ | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										595
									
								
								block.cpp
									
									
									
									
									
								
							
							
						
						
									
										595
									
								
								block.cpp
									
									
									
									
									
								
							| @ -1,595 +0,0 @@ | |||||||
| /*
 |  | ||||||
| 	This file is part of cpp-ethereum. |  | ||||||
| 
 |  | ||||||
| 	cpp-ethereum is free software: you can redistribute it and/or modify |  | ||||||
| 	it under the terms of the GNU General Public License as published by |  | ||||||
| 	the Free Software Foundation, either version 3 of the License, or |  | ||||||
| 	(at your option) any later version. |  | ||||||
| 
 |  | ||||||
| 	cpp-ethereum is distributed in the hope that it will be useful, |  | ||||||
| 	but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| 	GNU General Public License for more details. |  | ||||||
| 
 |  | ||||||
| 	You should have received a copy of the GNU General Public License |  | ||||||
| 	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 |  | ||||||
| */ |  | ||||||
| /** @file block.cpp
 |  | ||||||
|  * @author Christoph Jentzsch <cj@ethdev.com> |  | ||||||
|  * @date 2015 |  | ||||||
|  * block test functions. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <libdevcrypto/FileSystem.h> |  | ||||||
| #include <libethereum/CanonBlockChain.h> |  | ||||||
| #include "TestHelper.h" |  | ||||||
| 
 |  | ||||||
| using namespace std; |  | ||||||
| using namespace json_spirit; |  | ||||||
| using namespace dev; |  | ||||||
| using namespace dev::eth; |  | ||||||
| 
 |  | ||||||
| namespace dev {  namespace test { |  | ||||||
| 
 |  | ||||||
| bytes createBlockRLPFromFields(mObject& _tObj) |  | ||||||
| { |  | ||||||
| 	RLPStream rlpStream; |  | ||||||
| 	rlpStream.appendList(_tObj.size()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("parentHash")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["parentHash"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("uncleHash")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["uncleHash"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("coinbase")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["coinbase"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("stateRoot")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["stateRoot"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("transactionsTrie")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["transactionsTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("receiptTrie")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["receiptTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("bloom")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["bloom"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("difficulty")) |  | ||||||
| 		rlpStream << bigint(_tObj["difficulty"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("number")) |  | ||||||
| 		rlpStream << bigint(_tObj["number"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("gasLimit")) |  | ||||||
| 		rlpStream << bigint(_tObj["gasLimit"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("gasUsed")) |  | ||||||
| 		rlpStream << bigint(_tObj["gasUsed"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("timestamp")) |  | ||||||
| 		rlpStream << bigint(_tObj["timestamp"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("extraData")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["extraData"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	if (_tObj.count("nonce")) |  | ||||||
| 		rlpStream << importByteArray(_tObj["nonce"].get_str()); |  | ||||||
| 
 |  | ||||||
| 	return rlpStream.out(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void overwriteBlockHeader(mObject& _o, BlockInfo _current_BlockHeader) |  | ||||||
| { |  | ||||||
|     if (_o.count("blockHeader")) |  | ||||||
|     { |  | ||||||
|         if (_o["blockHeader"].get_obj().size() != 14) |  | ||||||
|         { |  | ||||||
| 
 |  | ||||||
|             BlockInfo tmp = _current_BlockHeader; |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("parentHash")) |  | ||||||
|                 tmp.parentHash = h256(_o["blockHeader"].get_obj()["parentHash"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("uncleHash")) |  | ||||||
|                 tmp.sha3Uncles = h256(_o["blockHeader"].get_obj()["uncleHash"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("coinbase")) |  | ||||||
|                 tmp.coinbaseAddress = Address(_o["blockHeader"].get_obj()["coinbase"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("stateRoot")) |  | ||||||
|                 tmp.stateRoot = h256(_o["blockHeader"].get_obj()["stateRoot"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("transactionsTrie")) |  | ||||||
|                 tmp.transactionsRoot = h256(_o["blockHeader"].get_obj()["transactionsTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("receiptTrie")) |  | ||||||
|                 tmp.receiptsRoot = h256(_o["blockHeader"].get_obj()["receiptTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("bloom")) |  | ||||||
|                 tmp.logBloom = LogBloom(_o["blockHeader"].get_obj()["bloom"].get_str()); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("difficulty")) |  | ||||||
|                 tmp.difficulty = toInt(_o["blockHeader"].get_obj()["difficulty"]); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("number")) |  | ||||||
|                 tmp.number = toInt(_o["blockHeader"].get_obj()["number"]); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("gasLimit")) |  | ||||||
|                 tmp.gasLimit = toInt(_o["blockHeader"].get_obj()["gasLimit"]); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("gasUsed")) |  | ||||||
|                 tmp.gasUsed = toInt(_o["blockHeader"].get_obj()["gasUsed"]); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("timestamp")) |  | ||||||
|                 tmp.timestamp = toInt(_o["blockHeader"].get_obj()["timestamp"]); |  | ||||||
| 
 |  | ||||||
|             if (_o["blockHeader"].get_obj().count("extraData")) |  | ||||||
|                 tmp.extraData = importByteArray(_o["blockHeader"].get_obj()["extraData"].get_str()); |  | ||||||
| 
 |  | ||||||
|             // find new valid nonce
 |  | ||||||
| 
 |  | ||||||
|             if (tmp != _current_BlockHeader) |  | ||||||
|             { |  | ||||||
|                 _current_BlockHeader = tmp; |  | ||||||
|                 cout << "new header!\n"; |  | ||||||
|                 ProofOfWork pow; |  | ||||||
|                 MineInfo ret; |  | ||||||
|                 while (!ProofOfWork::verify(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.nonce, _current_BlockHeader.difficulty)) |  | ||||||
|                     tie(ret, _current_BlockHeader.nonce) = pow.mine(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.difficulty, 10000, true, true); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             // take the blockheader as is
 |  | ||||||
|             const bytes c_blockRLP = createBlockRLPFromFields(_o["blockHeader"].get_obj()); |  | ||||||
|             const RLP c_bRLP(c_blockRLP); |  | ||||||
|             _current_BlockHeader.populateFromHeader(c_bRLP, false); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void doBlockTests(json_spirit::mValue& _v, bool _fillin) |  | ||||||
| { |  | ||||||
| 	for (auto& i: _v.get_obj()) |  | ||||||
| 	{ |  | ||||||
| 		cerr << i.first << endl; |  | ||||||
| 		mObject& o = i.second.get_obj(); |  | ||||||
| 
 |  | ||||||
| 		BOOST_REQUIRE(o.count("genesisBlockHeader")); |  | ||||||
| 		BlockInfo blockFromFields; |  | ||||||
| 		try |  | ||||||
| 		{ |  | ||||||
| 			// construct genesis block
 |  | ||||||
| 			const bytes c_blockRLP = createBlockRLPFromFields(o["genesisBlockHeader"].get_obj()); |  | ||||||
| 			const RLP c_bRLP(c_blockRLP); |  | ||||||
| 			blockFromFields.populateFromHeader(c_bRLP, false); |  | ||||||
| 		} |  | ||||||
| 		catch (Exception const& _e) |  | ||||||
| 		{ |  | ||||||
| 			cnote << "block population did throw an exception: " << diagnostic_information(_e); |  | ||||||
| 			BOOST_ERROR("Failed block population with Exception: " << _e.what()); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 		catch (std::exception const& _e) |  | ||||||
| 		{ |  | ||||||
| 			BOOST_ERROR("Failed block population with Exception: " << _e.what()); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 		catch(...) |  | ||||||
| 		{ |  | ||||||
| 			cnote << "block population did throw an unknown exception\n"; |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		BOOST_REQUIRE(o.count("pre")); |  | ||||||
| 
 |  | ||||||
| 		ImportTest importer(o["pre"].get_obj()); |  | ||||||
| 		State state(Address(), OverlayDB(), BaseState::Empty); |  | ||||||
| 		importer.importState(o["pre"].get_obj(), state); |  | ||||||
| 		state.commit(); |  | ||||||
| 
 |  | ||||||
| 		if (_fillin) |  | ||||||
| 			blockFromFields.stateRoot = state.rootHash(); |  | ||||||
| 		else |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockFromFields.stateRoot == state.rootHash(), "root hash does not match"); |  | ||||||
| 
 |  | ||||||
| 		if (_fillin) |  | ||||||
| 		{ |  | ||||||
| 			// find new valid nonce
 |  | ||||||
| 			ProofOfWork pow; |  | ||||||
| 			MineInfo ret; |  | ||||||
| 			ProofOfWork::Proof proof; |  | ||||||
| 			while (!ProofOfWork::verify(blockFromFields)) |  | ||||||
| 			{ |  | ||||||
| 				tie(ret, proof) = pow.mine(blockFromFields, 1000, true, true); |  | ||||||
| 				ProofOfWork::assignResult(proof, blockFromFields); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			//update genesis block in json file
 |  | ||||||
| 			o["genesisBlockHeader"].get_obj()["stateRoot"] = toString(blockFromFields.stateRoot); |  | ||||||
| 			o["genesisBlockHeader"].get_obj()["nonce"] = toString(blockFromFields.nonce); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// create new "genesis" block
 |  | ||||||
| 		RLPStream rlpStream; |  | ||||||
| 		blockFromFields.streamRLP(rlpStream, WithNonce); |  | ||||||
| 
 |  | ||||||
| 		RLPStream block(3); |  | ||||||
| 		block.appendRaw(rlpStream.out()); |  | ||||||
| 		block.appendRaw(RLPEmptyList); |  | ||||||
| 		block.appendRaw(RLPEmptyList); |  | ||||||
| 
 |  | ||||||
| 		blockFromFields.verifyInternals(&block.out()); |  | ||||||
| 
 |  | ||||||
| 		// construct blockchain
 |  | ||||||
| 		BlockChain bc(block.out(), string(), true); |  | ||||||
| 
 |  | ||||||
| 		if (_fillin) |  | ||||||
| 		{ |  | ||||||
| 			BOOST_REQUIRE(o.count("transactions")); |  | ||||||
| 
 |  | ||||||
| 			TransactionQueue txs; |  | ||||||
| 
 |  | ||||||
| 			for (auto const& txObj: o["transactions"].get_array()) |  | ||||||
| 			{ |  | ||||||
| 				mObject tx = txObj.get_obj(); |  | ||||||
| 				importer.importTransaction(tx); |  | ||||||
| 				if (!txs.attemptImport(importer.m_transaction.rlp())) |  | ||||||
| 					cnote << "failed importing transaction\n"; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			try |  | ||||||
| 			{ |  | ||||||
| 				state.sync(bc); |  | ||||||
| 				state.sync(bc,txs); |  | ||||||
| 				state.commitToMine(bc); |  | ||||||
| 				MineInfo info; |  | ||||||
| 				for (info.completed = false; !info.completed; info = state.mine()) {} |  | ||||||
| 				state.completeMine(); |  | ||||||
| 			} |  | ||||||
| 			catch (Exception const& _e) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "state sync or mining did throw an exception: " << diagnostic_information(_e); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 			catch (std::exception const& _e) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "state sync or mining did throw an exception: " << _e.what(); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// write valid txs
 |  | ||||||
| 			mArray txArray; |  | ||||||
| 			Transactions txList; |  | ||||||
| 			for (auto const& txi: txs.transactions()) |  | ||||||
| 			{ |  | ||||||
| 				Transaction tx(txi.second, CheckSignature::Sender); |  | ||||||
| 				txList.push_back(tx); |  | ||||||
| 				mObject txObject; |  | ||||||
| 				txObject["nonce"] = toString(tx.nonce()); |  | ||||||
| 				txObject["data"] = toHex(tx.data()); |  | ||||||
| 				txObject["gasLimit"] = toString(tx.gas()); |  | ||||||
| 				txObject["gasPrice"] = toString(tx.gasPrice()); |  | ||||||
| 				txObject["r"] = "0x" + toString(tx.signature().r); |  | ||||||
| 				txObject["s"] = "0x" + toString(tx.signature().s); |  | ||||||
| 				txObject["v"] = to_string(tx.signature().v + 27); |  | ||||||
| 				txObject["to"] = toString(tx.receiveAddress()); |  | ||||||
| 				txObject["value"] = toString(tx.value()); |  | ||||||
| 
 |  | ||||||
| 				txArray.push_back(txObject); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			o["transactions"] = txArray; |  | ||||||
| 			o["rlp"] = "0x" + toHex(state.blockData()); |  | ||||||
| 
 |  | ||||||
| 			BlockInfo currentBlockHeader = state.info(); |  | ||||||
| 
 |  | ||||||
| 			// overwrite blockheader with (possible wrong) data from "blockheader" in filler;
 |  | ||||||
| 
 |  | ||||||
| 			if (o.count("blockHeader")) |  | ||||||
| 			{ |  | ||||||
| 				if (o["blockHeader"].get_obj().size() != 14) |  | ||||||
| 				{ |  | ||||||
| 
 |  | ||||||
| 					BlockInfo tmp = currentBlockHeader; |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("parentHash")) |  | ||||||
| 						tmp.parentHash = h256(o["blockHeader"].get_obj()["parentHash"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("uncleHash")) |  | ||||||
| 						tmp.sha3Uncles = h256(o["blockHeader"].get_obj()["uncleHash"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("coinbase")) |  | ||||||
| 						tmp.coinbaseAddress = Address(o["blockHeader"].get_obj()["coinbase"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("stateRoot")) |  | ||||||
| 						tmp.stateRoot = h256(o["blockHeader"].get_obj()["stateRoot"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("transactionsTrie")) |  | ||||||
| 						tmp.transactionsRoot = h256(o["blockHeader"].get_obj()["transactionsTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("receiptTrie")) |  | ||||||
| 						tmp.receiptsRoot = h256(o["blockHeader"].get_obj()["receiptTrie"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("bloom")) |  | ||||||
| 						tmp.logBloom = LogBloom(o["blockHeader"].get_obj()["bloom"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("difficulty")) |  | ||||||
| 						tmp.difficulty = toInt(o["blockHeader"].get_obj()["difficulty"]); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("number")) |  | ||||||
| 						tmp.number = toInt(o["blockHeader"].get_obj()["number"]); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("gasLimit")) |  | ||||||
| 						tmp.gasLimit = toInt(o["blockHeader"].get_obj()["gasLimit"]); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("gasUsed")) |  | ||||||
| 						tmp.gasUsed = toInt(o["blockHeader"].get_obj()["gasUsed"]); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("timestamp")) |  | ||||||
| 						tmp.timestamp = toInt(o["blockHeader"].get_obj()["timestamp"]); |  | ||||||
| 
 |  | ||||||
| 					if (o["blockHeader"].get_obj().count("extraData")) |  | ||||||
| 						tmp.extraData = importByteArray(o["blockHeader"].get_obj()["extraData"].get_str()); |  | ||||||
| 
 |  | ||||||
| 					// find new valid nonce
 |  | ||||||
| 
 |  | ||||||
| 					if (tmp != currentBlockHeader) |  | ||||||
| 					{ |  | ||||||
| 						currentBlockHeader = tmp; |  | ||||||
| 						cout << "new header!\n"; |  | ||||||
| 						ProofOfWork pow; |  | ||||||
| 						MineInfo ret; |  | ||||||
| 						ProofOfWork::Proof proof; |  | ||||||
| 						while (!ProofOfWork::verify(currentBlockHeader)) |  | ||||||
| 						{ |  | ||||||
| 							tie(ret, proof) = pow.mine(currentBlockHeader, 10000, true, true); |  | ||||||
| 							ProofOfWork::assignResult(proof, currentBlockHeader); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				else |  | ||||||
| 				{ |  | ||||||
| 					// take the blockheader as is
 |  | ||||||
| 					const bytes c_blockRLP = createBlockRLPFromFields(o["blockHeader"].get_obj()); |  | ||||||
| 					const RLP c_bRLP(c_blockRLP); |  | ||||||
| 					currentBlockHeader.populateFromHeader(c_bRLP, false); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// write block header
 |  | ||||||
| 			mObject oBlockHeader; |  | ||||||
| 			oBlockHeader["parentHash"] = toString(currentBlockHeader.parentHash); |  | ||||||
| 			oBlockHeader["uncleHash"] = toString(currentBlockHeader.sha3Uncles); |  | ||||||
| 			oBlockHeader["coinbase"] = toString(currentBlockHeader.coinbaseAddress); |  | ||||||
| 			oBlockHeader["stateRoot"] = toString(currentBlockHeader.stateRoot); |  | ||||||
| 			oBlockHeader["transactionsTrie"] = toString(currentBlockHeader.transactionsRoot); |  | ||||||
| 			oBlockHeader["receiptTrie"] = toString(currentBlockHeader.receiptsRoot); |  | ||||||
| 			oBlockHeader["bloom"] = toString(currentBlockHeader.logBloom); |  | ||||||
| 			oBlockHeader["difficulty"] = toString(currentBlockHeader.difficulty); |  | ||||||
| 			oBlockHeader["number"] = toString(currentBlockHeader.number); |  | ||||||
| 			oBlockHeader["gasLimit"] = toString(currentBlockHeader.gasLimit); |  | ||||||
| 			oBlockHeader["gasUsed"] = toString(currentBlockHeader.gasUsed); |  | ||||||
| 			oBlockHeader["timestamp"] = toString(currentBlockHeader.timestamp); |  | ||||||
| 			oBlockHeader["extraData"] = toHex(currentBlockHeader.extraData); |  | ||||||
| 			oBlockHeader["nonce"] = toString(currentBlockHeader.nonce); |  | ||||||
| 
 |  | ||||||
| 			o["blockHeader"] = oBlockHeader; |  | ||||||
| 
 |  | ||||||
| 			// write uncle list
 |  | ||||||
| 			mArray aUncleList; // as of now, our parent is always the genesis block, so we can not have uncles.
 |  | ||||||
| 			o["uncleHeaders"] = aUncleList; |  | ||||||
| 
 |  | ||||||
| 			//txs:
 |  | ||||||
| 
 |  | ||||||
| 			RLPStream txStream; |  | ||||||
| 			txStream.appendList(txList.size()); |  | ||||||
| 			for (unsigned i = 0; i < txList.size(); ++i) |  | ||||||
| 			{ |  | ||||||
| 				RLPStream txrlp; |  | ||||||
| 				txList[i].streamRLP(txrlp); |  | ||||||
| 				txStream.appendRaw(txrlp.out()); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			RLPStream rlpStream2; |  | ||||||
| 			currentBlockHeader.streamRLP(rlpStream2, WithNonce); |  | ||||||
| 
 |  | ||||||
| 			RLPStream block2(3); |  | ||||||
| 			block2.appendRaw(rlpStream2.out()); |  | ||||||
| 			block2.appendRaw(txStream.out()); |  | ||||||
| 			block2.appendRaw(RLPEmptyList); |  | ||||||
| 
 |  | ||||||
| 			o["rlp"] = "0x" + toHex(block2.out()); |  | ||||||
| 
 |  | ||||||
| 			if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data())) |  | ||||||
| 				cnote << "block header mismatch\n"; |  | ||||||
| 
 |  | ||||||
| 			if (sha3(RLP(state.blockData())[1].data()) != sha3(RLP(block2.out())[1].data())) |  | ||||||
| 				cnote << "txs mismatch\n"; |  | ||||||
| 
 |  | ||||||
| 			if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data())) |  | ||||||
| 				cnote << "uncle list mismatch\n"; |  | ||||||
| 
 |  | ||||||
| 			try |  | ||||||
| 			{ |  | ||||||
| 				ImportTest importerTmp(o["pre"].get_obj()); |  | ||||||
| 				State stateTmp(Address(), OverlayDB(), BaseState::Empty); |  | ||||||
| 				importerTmp.importState(o["pre"].get_obj(), stateTmp); |  | ||||||
| 				stateTmp.commit(); |  | ||||||
| 				BlockChain bcTmp(block.out(), getDataDir() + "/tmpBlockChain.bc", true); |  | ||||||
| 				stateTmp.sync(bcTmp); |  | ||||||
| 				bc.import(block2.out(), stateTmp.db()); |  | ||||||
| 				stateTmp.sync(bcTmp); |  | ||||||
| 			} |  | ||||||
| 			// if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given
 |  | ||||||
| 			catch (...) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "block is invalid!\n"; |  | ||||||
| 				o.erase(o.find("blockHeader")); |  | ||||||
| 				o.erase(o.find("uncleHeaders")); |  | ||||||
| 				o.erase(o.find("transactions")); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			bytes blockRLP; |  | ||||||
| 			try |  | ||||||
| 			{ |  | ||||||
| 				state.sync(bc); |  | ||||||
| 				blockRLP = importByteArray(o["rlp"].get_str()); |  | ||||||
| 				bc.import(blockRLP, state.db()); |  | ||||||
| 				state.sync(bc); |  | ||||||
| 			} |  | ||||||
| 			// if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given
 |  | ||||||
| 			catch (Exception const& _e) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "state sync or block import did throw an exception: " << diagnostic_information(_e); |  | ||||||
| 				BOOST_CHECK(o.count("blockHeader") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("transactions") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("uncleHeaders") == 0); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			catch (std::exception const& _e) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "state sync or block import did throw an exception: " << _e.what(); |  | ||||||
| 				BOOST_CHECK(o.count("blockHeader") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("transactions") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("uncleHeaders") == 0); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			catch(...) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "state sync or block import did throw an exception\n"; |  | ||||||
| 				BOOST_CHECK(o.count("blockHeader") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("transactions") == 0); |  | ||||||
| 				BOOST_CHECK(o.count("uncleHeaders") == 0); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			BOOST_REQUIRE(o.count("blockHeader")); |  | ||||||
| 
 |  | ||||||
| 			mObject tObj = o["blockHeader"].get_obj(); |  | ||||||
| 			BlockInfo blockHeaderFromFields; |  | ||||||
| 			const bytes c_rlpBytesBlockHeader = createBlockRLPFromFields(tObj); |  | ||||||
| 			const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader); |  | ||||||
| 			blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, false); |  | ||||||
| 
 |  | ||||||
| 			BlockInfo blockFromRlp = bc.info(); |  | ||||||
| 
 |  | ||||||
| 			//Check the fields restored from RLP to original fields
 |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); |  | ||||||
| 
 |  | ||||||
| 			BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); |  | ||||||
| 
 |  | ||||||
| 			//Check transaction list
 |  | ||||||
| 			Transactions txsFromField; |  | ||||||
| 
 |  | ||||||
| 			for (auto const& txObj: o["transactions"].get_array()) |  | ||||||
| 			{ |  | ||||||
| 				mObject tx = txObj.get_obj(); |  | ||||||
| 
 |  | ||||||
| 				BOOST_REQUIRE(tx.count("nonce")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("gasPrice")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("gasLimit")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("to")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("value")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("v")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("r")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("s")); |  | ||||||
| 				BOOST_REQUIRE(tx.count("data")); |  | ||||||
| 
 |  | ||||||
| 				try |  | ||||||
| 				{ |  | ||||||
| 					Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckSignature::Sender); |  | ||||||
| 					txsFromField.push_back(t); |  | ||||||
| 				} |  | ||||||
| 				catch (Exception const& _e) |  | ||||||
| 				{ |  | ||||||
| 					BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); |  | ||||||
| 				} |  | ||||||
| 				catch (exception const& _e) |  | ||||||
| 				{ |  | ||||||
| 					cnote << _e.what(); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Transactions txsFromRlp; |  | ||||||
| 			RLP root(blockRLP); |  | ||||||
| 			for (auto const& tr: root[1]) |  | ||||||
| 			{ |  | ||||||
| 				Transaction tx(tr.data(), CheckSignature::Sender); |  | ||||||
| 				txsFromRlp.push_back(tx); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); |  | ||||||
| 
 |  | ||||||
| 			for (size_t i = 0; i < txsFromField.size(); ++i) |  | ||||||
| 			{ |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); |  | ||||||
| 
 |  | ||||||
| 				BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions in rlp and in transaction field do not match"); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// check uncle list
 |  | ||||||
| 			BOOST_CHECK_MESSAGE((o["uncleList"].type() == json_spirit::null_type ? 0 : o["uncleList"].get_array().size()) == 0, "Uncle list is not empty, but the genesis block can not have uncles"); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } }// Namespace Close
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_SUITE(BlockTests) |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(blValidBlockTest) |  | ||||||
| { |  | ||||||
| 	dev::test::executeTests("blValidBlockTest", "/BlockTests", dev::test::doBlockTests); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(blInvalidTransactionRLP) |  | ||||||
| { |  | ||||||
| 	dev::test::executeTests("blInvalidTransactionRLP", "/BlockTests", dev::test::doBlockTests); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(blInvalidHeaderTest) |  | ||||||
| { |  | ||||||
| 	dev::test::executeTests("blInvalidHeaderTest", "/BlockTests", dev::test::doBlockTests); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(blForkBlocks) |  | ||||||
| { |  | ||||||
| 	dev::test::executeTests("blForkBlocks", "/BlockTests", dev::test::doBlockTests); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(userDefinedFile) |  | ||||||
| { |  | ||||||
| 	dev::test::userDefinedTest("--singletest", dev::test::doBlockTests); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_SUITE_END() |  | ||||||
							
								
								
									
										537
									
								
								blockchain.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										537
									
								
								blockchain.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,537 @@ | |||||||
|  | /*
 | ||||||
|  | 	This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  | 	cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  | 	it under the terms of the GNU General Public License as published by | ||||||
|  | 	the Free Software Foundation, either version 3 of the License, or | ||||||
|  | 	(at your option) any later version. | ||||||
|  | 
 | ||||||
|  | 	cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | 	GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | 	You should have received a copy of the GNU General Public License | ||||||
|  | 	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file block.cpp
 | ||||||
|  |  * @author Christoph Jentzsch <cj@ethdev.com> | ||||||
|  |  * @date 2015 | ||||||
|  |  * block test functions. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <libdevcrypto/FileSystem.h> | ||||||
|  | #include <libethereum/CanonBlockChain.h> | ||||||
|  | #include "TestHelper.h" | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace json_spirit; | ||||||
|  | using namespace dev; | ||||||
|  | using namespace dev::eth; | ||||||
|  | 
 | ||||||
|  | namespace dev {  namespace test { | ||||||
|  | 
 | ||||||
|  | bytes createBlockRLPFromFields(mObject& _tObj) | ||||||
|  | { | ||||||
|  | 	RLPStream rlpStream; | ||||||
|  | 	rlpStream.appendList(_tObj.size()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("parentHash")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["parentHash"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("uncleHash")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["uncleHash"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("coinbase")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["coinbase"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("stateRoot")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["stateRoot"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("transactionsTrie")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["transactionsTrie"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("receiptTrie")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["receiptTrie"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("bloom")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["bloom"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("difficulty")) | ||||||
|  | 		rlpStream << bigint(_tObj["difficulty"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("number")) | ||||||
|  | 		rlpStream << bigint(_tObj["number"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("gasLimit")) | ||||||
|  | 		rlpStream << bigint(_tObj["gasLimit"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("gasUsed")) | ||||||
|  | 		rlpStream << bigint(_tObj["gasUsed"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("timestamp")) | ||||||
|  | 		rlpStream << bigint(_tObj["timestamp"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("extraData")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["extraData"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	if (_tObj.count("nonce")) | ||||||
|  | 		rlpStream << importByteArray(_tObj["nonce"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	return rlpStream.out(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void doBlockTests(json_spirit::mValue& _v, bool _fillin) | ||||||
|  | { | ||||||
|  | 	for (auto& i: _v.get_obj()) | ||||||
|  | 	{ | ||||||
|  | 		cerr << i.first << endl; | ||||||
|  | 		mObject& o = i.second.get_obj(); | ||||||
|  | 
 | ||||||
|  | 		BOOST_REQUIRE(o.count("genesisBlockHeader")); | ||||||
|  | 		BlockInfo blockFromFields; | ||||||
|  | 		try | ||||||
|  | 		{ | ||||||
|  | 			// construct genesis block
 | ||||||
|  | 			const bytes c_blockRLP = createBlockRLPFromFields(o["genesisBlockHeader"].get_obj()); | ||||||
|  | 			const RLP c_bRLP(c_blockRLP); | ||||||
|  | 			blockFromFields.populateFromHeader(c_bRLP, false); | ||||||
|  | 		} | ||||||
|  | 		catch (Exception const& _e) | ||||||
|  | 		{ | ||||||
|  | 			cnote << "block population did throw an exception: " << diagnostic_information(_e); | ||||||
|  | 			BOOST_ERROR("Failed block population with Exception: " << _e.what()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		catch (std::exception const& _e) | ||||||
|  | 		{ | ||||||
|  | 			BOOST_ERROR("Failed block population with Exception: " << _e.what()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		catch(...) | ||||||
|  | 		{ | ||||||
|  | 			cnote << "block population did throw an unknown exception\n"; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		BOOST_REQUIRE(o.count("pre")); | ||||||
|  | 
 | ||||||
|  | 		ImportTest importer(o["pre"].get_obj()); | ||||||
|  | 		State state(Address(), OverlayDB(), BaseState::Empty); | ||||||
|  | 		importer.importState(o["pre"].get_obj(), state); | ||||||
|  | 		state.commit(); | ||||||
|  | 
 | ||||||
|  | 		if (_fillin) | ||||||
|  | 			blockFromFields.stateRoot = state.rootHash(); | ||||||
|  | 		else | ||||||
|  | 			BOOST_CHECK_MESSAGE(blockFromFields.stateRoot == state.rootHash(), "root hash does not match"); | ||||||
|  | 
 | ||||||
|  | 		if (_fillin) | ||||||
|  | 		{ | ||||||
|  | 			// find new valid nonce
 | ||||||
|  | 			ProofOfWork pow; | ||||||
|  | 			MineInfo ret; | ||||||
|  | 			while (!ProofOfWork::verify(blockFromFields.headerHash(WithoutNonce), blockFromFields.nonce, blockFromFields.difficulty)) | ||||||
|  | 				tie(ret, blockFromFields.nonce) = pow.mine(blockFromFields.headerHash(WithoutNonce), blockFromFields.difficulty, 1000, true, true); | ||||||
|  | 
 | ||||||
|  | 			//update genesis block in json file
 | ||||||
|  | 			o["genesisBlockHeader"].get_obj()["stateRoot"] = toString(blockFromFields.stateRoot); | ||||||
|  | 			o["genesisBlockHeader"].get_obj()["nonce"] = toString(blockFromFields.nonce); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// create new "genesis" block
 | ||||||
|  | 		RLPStream rlpStream; | ||||||
|  | 		blockFromFields.streamRLP(rlpStream, WithNonce); | ||||||
|  | 
 | ||||||
|  | 		RLPStream block(3); | ||||||
|  | 		block.appendRaw(rlpStream.out()); | ||||||
|  | 		block.appendRaw(RLPEmptyList); | ||||||
|  | 		block.appendRaw(RLPEmptyList); | ||||||
|  | 
 | ||||||
|  | 		blockFromFields.verifyInternals(&block.out()); | ||||||
|  | 
 | ||||||
|  | 		// construct blockchain
 | ||||||
|  | 		BlockChain bc(block.out(), string(), true); | ||||||
|  | 
 | ||||||
|  | 		if (_fillin) | ||||||
|  | 		{ | ||||||
|  | 			BOOST_REQUIRE(o.count("blocks")); | ||||||
|  | 			mArray blArray; | ||||||
|  | 			for (auto const& bl: o["blocks"].get_array()) | ||||||
|  | 			{ | ||||||
|  | 				mObject blObj = bl.get_obj(); | ||||||
|  | 				BOOST_REQUIRE(blObj.count("transactions")); | ||||||
|  | 
 | ||||||
|  | 				TransactionQueue txs; | ||||||
|  | 
 | ||||||
|  | 				for (auto const& txObj: blObj["transactions"].get_array()) | ||||||
|  | 				{ | ||||||
|  | 					mObject tx = txObj.get_obj(); | ||||||
|  | 					importer.importTransaction(tx); | ||||||
|  | 					if (!txs.attemptImport(importer.m_transaction.rlp())) | ||||||
|  | 						cnote << "failed importing transaction\n"; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					state.sync(bc); | ||||||
|  | 					state.sync(bc,txs); | ||||||
|  | 					state.commitToMine(bc); | ||||||
|  | 					MineInfo info; | ||||||
|  | 					for (info.completed = false; !info.completed; info = state.mine()) {} | ||||||
|  | 					state.completeMine(); | ||||||
|  | 				} | ||||||
|  | 				catch (Exception const& _e) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "state sync or mining did throw an exception: " << diagnostic_information(_e); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 				catch (std::exception const& _e) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "state sync or mining did throw an exception: " << _e.what(); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// write valid txs
 | ||||||
|  | 				mArray txArray; | ||||||
|  | 				Transactions txList; | ||||||
|  | 				for (auto const& txi: txs.transactions()) | ||||||
|  | 				{ | ||||||
|  | 					Transaction tx(txi.second, CheckSignature::Sender); | ||||||
|  | 					txList.push_back(tx); | ||||||
|  | 					mObject txObject; | ||||||
|  | 					txObject["nonce"] = toString(tx.nonce()); | ||||||
|  | 					txObject["data"] = toHex(tx.data()); | ||||||
|  | 					txObject["gasLimit"] = toString(tx.gas()); | ||||||
|  | 					txObject["gasPrice"] = toString(tx.gasPrice()); | ||||||
|  | 					txObject["r"] = "0x" + toString(tx.signature().r); | ||||||
|  | 					txObject["s"] = "0x" + toString(tx.signature().s); | ||||||
|  | 					txObject["v"] = to_string(tx.signature().v + 27); | ||||||
|  | 					txObject["to"] = toString(tx.receiveAddress()); | ||||||
|  | 					txObject["value"] = toString(tx.value()); | ||||||
|  | 
 | ||||||
|  | 					txArray.push_back(txObject); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				blObj["transactions"] = txArray; | ||||||
|  | 				blObj["rlp"] = "0x" + toHex(state.blockData()); | ||||||
|  | 
 | ||||||
|  | 				BlockInfo current_BlockHeader = state.info(); | ||||||
|  | 
 | ||||||
|  | 				// overwrite blockheader with (possible wrong) data from "blockheader" in filler;
 | ||||||
|  | 
 | ||||||
|  | 				if (blObj.count("blockHeader")) | ||||||
|  | 				{ | ||||||
|  | 					if (blObj["blockHeader"].get_obj().size() != 14) | ||||||
|  | 					{ | ||||||
|  | 
 | ||||||
|  | 						BlockInfo tmp = current_BlockHeader; | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("parentHash")) | ||||||
|  | 							tmp.parentHash = h256(blObj["blockHeader"].get_obj()["parentHash"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("uncleHash")) | ||||||
|  | 							tmp.sha3Uncles = h256(blObj["blockHeader"].get_obj()["uncleHash"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("coinbase")) | ||||||
|  | 							tmp.coinbaseAddress = Address(blObj["blockHeader"].get_obj()["coinbase"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("stateRoot")) | ||||||
|  | 							tmp.stateRoot = h256(blObj["blockHeader"].get_obj()["stateRoot"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("transactionsTrie")) | ||||||
|  | 							tmp.transactionsRoot = h256(blObj["blockHeader"].get_obj()["transactionsTrie"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("receiptTrie")) | ||||||
|  | 							tmp.receiptsRoot = h256(blObj["blockHeader"].get_obj()["receiptTrie"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("bloom")) | ||||||
|  | 							tmp.logBloom = LogBloom(blObj["blockHeader"].get_obj()["bloom"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("difficulty")) | ||||||
|  | 							tmp.difficulty = toInt(blObj["blockHeader"].get_obj()["difficulty"]); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("number")) | ||||||
|  | 							tmp.number = toInt(blObj["blockHeader"].get_obj()["number"]); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("gasLimit")) | ||||||
|  | 							tmp.gasLimit = toInt(blObj["blockHeader"].get_obj()["gasLimit"]); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("gasUsed")) | ||||||
|  | 							tmp.gasUsed = toInt(blObj["blockHeader"].get_obj()["gasUsed"]); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("timestamp")) | ||||||
|  | 							tmp.timestamp = toInt(blObj["blockHeader"].get_obj()["timestamp"]); | ||||||
|  | 
 | ||||||
|  | 						if (blObj["blockHeader"].get_obj().count("extraData")) | ||||||
|  | 							tmp.extraData = importByteArray(blObj["blockHeader"].get_obj()["extraData"].get_str()); | ||||||
|  | 
 | ||||||
|  | 						// find new valid nonce
 | ||||||
|  | 
 | ||||||
|  | 						if (tmp != current_BlockHeader) | ||||||
|  | 						{ | ||||||
|  | 							current_BlockHeader = tmp; | ||||||
|  | 							cout << "new header!\n"; | ||||||
|  | 							ProofOfWork pow; | ||||||
|  | 							MineInfo ret; | ||||||
|  | 							while (!ProofOfWork::verify(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.nonce, current_BlockHeader.difficulty)) | ||||||
|  | 								tie(ret, current_BlockHeader.nonce) = pow.mine(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.difficulty, 10000, true, true); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						// take the blockheader as is
 | ||||||
|  | 						const bytes c_blockRLP = createBlockRLPFromFields(blObj["blockHeader"].get_obj()); | ||||||
|  | 						const RLP c_bRLP(c_blockRLP); | ||||||
|  | 						current_BlockHeader.populateFromHeader(c_bRLP, false); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// write block header
 | ||||||
|  | 
 | ||||||
|  | 				mObject oBlockHeader; | ||||||
|  | 				oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash); | ||||||
|  | 				oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles); | ||||||
|  | 				oBlockHeader["coinbase"] = toString(current_BlockHeader.coinbaseAddress); | ||||||
|  | 				oBlockHeader["stateRoot"] = toString(current_BlockHeader.stateRoot); | ||||||
|  | 				oBlockHeader["transactionsTrie"] = toString(current_BlockHeader.transactionsRoot); | ||||||
|  | 				oBlockHeader["receiptTrie"] = toString(current_BlockHeader.receiptsRoot); | ||||||
|  | 				oBlockHeader["bloom"] = toString(current_BlockHeader.logBloom); | ||||||
|  | 				oBlockHeader["difficulty"] = toString(current_BlockHeader.difficulty); | ||||||
|  | 				oBlockHeader["number"] = toString(current_BlockHeader.number); | ||||||
|  | 				oBlockHeader["gasLimit"] = toString(current_BlockHeader.gasLimit); | ||||||
|  | 				oBlockHeader["gasUsed"] = toString(current_BlockHeader.gasUsed); | ||||||
|  | 				oBlockHeader["timestamp"] = toString(current_BlockHeader.timestamp); | ||||||
|  | 				oBlockHeader["extraData"] = toHex(current_BlockHeader.extraData); | ||||||
|  | 				oBlockHeader["nonce"] = toString(current_BlockHeader.nonce); | ||||||
|  | 
 | ||||||
|  | 				blObj["blockHeader"] = oBlockHeader; | ||||||
|  | 
 | ||||||
|  | 				// write uncle list
 | ||||||
|  | 				mArray aUncleList; // as of now, our parent is always the genesis block, so we can not have uncles.
 | ||||||
|  | 				blObj["uncleHeaders"] = aUncleList; | ||||||
|  | 
 | ||||||
|  | 				//txs:
 | ||||||
|  | 
 | ||||||
|  | 				RLPStream txStream; | ||||||
|  | 				txStream.appendList(txList.size()); | ||||||
|  | 				for (unsigned i = 0; i < txList.size(); ++i) | ||||||
|  | 				{ | ||||||
|  | 					RLPStream txrlp; | ||||||
|  | 					txList[i].streamRLP(txrlp); | ||||||
|  | 					txStream.appendRaw(txrlp.out()); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				RLPStream rlpStream2; | ||||||
|  | 				current_BlockHeader.streamRLP(rlpStream2, WithNonce); | ||||||
|  | 
 | ||||||
|  | 				RLPStream block2(3); | ||||||
|  | 				block2.appendRaw(rlpStream2.out()); | ||||||
|  | 				block2.appendRaw(txStream.out()); | ||||||
|  | 				block2.appendRaw(RLPEmptyList); | ||||||
|  | 
 | ||||||
|  | 				blObj["rlp"] = "0x" + toHex(block2.out()); | ||||||
|  | 
 | ||||||
|  | 				if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data())) | ||||||
|  | 					cnote << "block header mismatch\n"; | ||||||
|  | 
 | ||||||
|  | 				if (sha3(RLP(state.blockData())[1].data()) != sha3(RLP(block2.out())[1].data())) | ||||||
|  | 					cnote << "txs mismatch\n"; | ||||||
|  | 
 | ||||||
|  | 				if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data())) | ||||||
|  | 					cnote << "uncle list mismatch\n"; | ||||||
|  | 
 | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					ImportTest importerTmp(o["pre"].get_obj()); | ||||||
|  | 					State stateTmp(Address(), OverlayDB(), BaseState::Empty); | ||||||
|  | 					importerTmp.importState(o["pre"].get_obj(), stateTmp); | ||||||
|  | 					stateTmp.commit(); | ||||||
|  | 					BlockChain bcTmp(block.out(), getDataDir() + "/tmpBlockChain.bc", true); | ||||||
|  | 					stateTmp.sync(bcTmp); | ||||||
|  | 					bc.import(block2.out(), stateTmp.db()); | ||||||
|  | 					stateTmp.sync(bcTmp); | ||||||
|  | 				} | ||||||
|  | 				// if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given
 | ||||||
|  | 				catch (...) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "block is invalid!\n"; | ||||||
|  | 					blObj.erase(blObj.find("blockHeader")); | ||||||
|  | 					blObj.erase(blObj.find("uncleHeaders")); | ||||||
|  | 					blObj.erase(blObj.find("transactions")); | ||||||
|  | 				} | ||||||
|  | 				blArray.push_back(blObj); | ||||||
|  | 			} | ||||||
|  | 			o["blocks"] = blArray; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			for (auto const& bl: o["blocks"].get_array()) | ||||||
|  | 			{ | ||||||
|  | 				mObject blObj = bl.get_obj(); | ||||||
|  | 				bytes blockRLP; | ||||||
|  | 				try | ||||||
|  | 				{ | ||||||
|  | 					state.sync(bc); | ||||||
|  | 					blockRLP = importByteArray(blObj["rlp"].get_str()); | ||||||
|  | 					bc.import(blockRLP, state.db()); | ||||||
|  | 					state.sync(bc); | ||||||
|  | 				} | ||||||
|  | 				// if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given
 | ||||||
|  | 				catch (Exception const& _e) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "state sync or block import did throw an exception: " << diagnostic_information(_e); | ||||||
|  | 					BOOST_CHECK(blObj.count("blockHeader") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("transactions") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("uncleHeaders") == 0); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				catch (std::exception const& _e) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "state sync or block import did throw an exception: " << _e.what(); | ||||||
|  | 					BOOST_CHECK(blObj.count("blockHeader") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("transactions") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("uncleHeaders") == 0); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				catch(...) | ||||||
|  | 				{ | ||||||
|  | 					cnote << "state sync or block import did throw an exception\n"; | ||||||
|  | 					BOOST_CHECK(blObj.count("blockHeader") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("transactions") == 0); | ||||||
|  | 					BOOST_CHECK(blObj.count("uncleHeaders") == 0); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				BOOST_REQUIRE(blObj.count("blockHeader")); | ||||||
|  | 
 | ||||||
|  | 				mObject tObj = blObj["blockHeader"].get_obj(); | ||||||
|  | 				BlockInfo blockHeaderFromFields; | ||||||
|  | 				const bytes c_rlpBytesBlockHeader = createBlockRLPFromFields(tObj); | ||||||
|  | 				const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader); | ||||||
|  | 				blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, false); | ||||||
|  | 
 | ||||||
|  | 				BlockInfo blockFromRlp = bc.info(); | ||||||
|  | 
 | ||||||
|  | 				//Check the fields restored from RLP to original fields
 | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); | ||||||
|  | 
 | ||||||
|  | 				BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); | ||||||
|  | 
 | ||||||
|  | 				//Check transaction list
 | ||||||
|  | 
 | ||||||
|  | 				Transactions txsFromField; | ||||||
|  | 
 | ||||||
|  | 				for (auto const& txObj: blObj["transactions"].get_array()) | ||||||
|  | 				{ | ||||||
|  | 					mObject tx = txObj.get_obj(); | ||||||
|  | 
 | ||||||
|  | 					BOOST_REQUIRE(tx.count("nonce")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("gasPrice")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("gasLimit")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("to")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("value")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("v")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("r")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("s")); | ||||||
|  | 					BOOST_REQUIRE(tx.count("data")); | ||||||
|  | 
 | ||||||
|  | 					try | ||||||
|  | 					{ | ||||||
|  | 						Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckSignature::Sender); | ||||||
|  | 						txsFromField.push_back(t); | ||||||
|  | 					} | ||||||
|  | 					catch (Exception const& _e) | ||||||
|  | 					{ | ||||||
|  | 						BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); | ||||||
|  | 					} | ||||||
|  | 					catch (exception const& _e) | ||||||
|  | 					{ | ||||||
|  | 						cnote << _e.what(); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				Transactions txsFromRlp; | ||||||
|  | 				RLP root(blockRLP); | ||||||
|  | 				for (auto const& tr: root[1]) | ||||||
|  | 				{ | ||||||
|  | 					Transaction tx(tr.data(), CheckSignature::Sender); | ||||||
|  | 					txsFromRlp.push_back(tx); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); | ||||||
|  | 
 | ||||||
|  | 				for (size_t i = 0; i < txsFromField.size(); ++i) | ||||||
|  | 				{ | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); | ||||||
|  | 
 | ||||||
|  | 					BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions in rlp and in transaction field do not match"); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// check uncle list
 | ||||||
|  | 				BOOST_CHECK_MESSAGE((blObj["uncleList"].type() == json_spirit::null_type ? 0 : blObj["uncleList"].get_array().size()) == 0, "Uncle list is not empty, but the genesis block can not have uncles"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } }// Namespace Close
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(BlockChainTests) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(bcBlockChainTest) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("bcBlockChainTest", "/BlockTests", dev::test::doBlockTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //BOOST_AUTO_TEST_CASE(blValidBlockTest)
 | ||||||
|  | //{
 | ||||||
|  | //	dev::test::executeTests("blValidBlockTest", "/BlockTests", dev::test::doBlockTests);
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | //BOOST_AUTO_TEST_CASE(blInvalidTransactionRLP)
 | ||||||
|  | //{
 | ||||||
|  | //	dev::test::executeTests("blInvalidTransactionRLP", "/BlockTests", dev::test::doBlockTests);
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | //BOOST_AUTO_TEST_CASE(blInvalidHeaderTest)
 | ||||||
|  | //{
 | ||||||
|  | //	dev::test::executeTests("blInvalidHeaderTest", "/BlockTests", dev::test::doBlockTests);
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | //BOOST_AUTO_TEST_CASE(blForkBlocks)
 | ||||||
|  | //{
 | ||||||
|  | //	dev::test::executeTests("blForkBlocks", "/BlockTests", dev::test::doBlockTests);
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(userDefinedFileBl) | ||||||
|  | { | ||||||
|  | 	dev::test::userDefinedTest("--bltest", dev::test::doBlockTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
							
								
								
									
										48
									
								
								vm.cpp
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								vm.cpp
									
									
									
									
									
								
							| @ -533,33 +533,33 @@ BOOST_AUTO_TEST_CASE(vmPerformanceTest) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmInputLimitsTest1) | //BOOST_AUTO_TEST_CASE(vmInputLimitsTest1)
 | ||||||
| { | //{
 | ||||||
| 	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) | //	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
 | ||||||
| 	{ | //	{
 | ||||||
| 		string arg = boost::unit_test::framework::master_test_suite().argv[i]; | //		string arg = boost::unit_test::framework::master_test_suite().argv[i];
 | ||||||
| 		if (arg == "--inputlimits" || arg == "--all") | //		if (arg == "--inputlimits" || arg == "--all")
 | ||||||
| 		{ | //		{
 | ||||||
| 			auto start = chrono::steady_clock::now(); | //			auto start = chrono::steady_clock::now();
 | ||||||
| 
 | 
 | ||||||
| 			dev::test::executeTests("vmInputLimitsTest1", "/VMTests", dev::test::doVMTests); | //			dev::test::executeTests("vmInputLimitsTest1", "/VMTests", dev::test::doVMTests);
 | ||||||
| 
 | 
 | ||||||
| 			auto end = chrono::steady_clock::now(); | //			auto end = chrono::steady_clock::now();
 | ||||||
| 			auto duration(chrono::duration_cast<chrono::milliseconds>(end - start)); | //			auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
 | ||||||
| 			cnote << "test duration: " << duration.count() << " milliseconds.\n"; | //			cnote << "test duration: " << duration.count() << " milliseconds.\n";
 | ||||||
| 		} | //		}
 | ||||||
| 	} | //	}
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmInputLimitsTest2) | //BOOST_AUTO_TEST_CASE(vmInputLimitsTest2)
 | ||||||
| { | //{
 | ||||||
| 	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) | //	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
 | ||||||
| 	{ | //	{
 | ||||||
| 		string arg = boost::unit_test::framework::master_test_suite().argv[i]; | //		string arg = boost::unit_test::framework::master_test_suite().argv[i];
 | ||||||
| 		if (arg == "--inputlimits" || arg == "--all") | //		if (arg == "--inputlimits" || arg == "--all")
 | ||||||
| 			dev::test::executeTests("vmInputLimitsTest2", "/VMTests", dev::test::doVMTests); | //			dev::test::executeTests("vmInputLimitsTest2", "/VMTests", dev::test::doVMTests);
 | ||||||
| 	} | //	}
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmRandom) | BOOST_AUTO_TEST_CASE(vmRandom) | ||||||
| { | { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user