mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	
						commit
						1376dd649c
					
				| @ -287,6 +287,18 @@ void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void checkLog(LogEntries _resultLogs, LogEntries _expectedLogs) | ||||||
|  | { | ||||||
|  | 	BOOST_REQUIRE_EQUAL(_resultLogs.size(), _expectedLogs.size()); | ||||||
|  | 
 | ||||||
|  | 	for (size_t i = 0; i < _resultLogs.size(); ++i) | ||||||
|  | 	{ | ||||||
|  | 		BOOST_CHECK_EQUAL(_resultLogs[i].address, _expectedLogs[i].address); | ||||||
|  | 		BOOST_CHECK_EQUAL(_resultLogs[i].topics, _expectedLogs[i].topics); | ||||||
|  | 		BOOST_CHECK(_resultLogs[i].data == _expectedLogs[i].data); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::string getTestPath() | std::string getTestPath() | ||||||
| { | { | ||||||
| 	string testPath; | 	string testPath; | ||||||
|  | |||||||
| @ -25,6 +25,7 @@ | |||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
| #include "JsonSpiritHeaders.h" | #include "JsonSpiritHeaders.h" | ||||||
| #include <libethereum/State.h> | #include <libethereum/State.h> | ||||||
|  | #include <libevm/ExtVMFace.h> | ||||||
| 
 | 
 | ||||||
| namespace dev | namespace dev | ||||||
| { | { | ||||||
| @ -69,6 +70,7 @@ bytes importCode(json_spirit::mObject& _o); | |||||||
| bytes importData(json_spirit::mObject& _o); | bytes importData(json_spirit::mObject& _o); | ||||||
| void checkOutput(bytes const& _output, json_spirit::mObject& _o); | void checkOutput(bytes const& _output, json_spirit::mObject& _o); | ||||||
| void checkStorage(std::map<u256, u256> _expectedStore, std::map<u256, u256> _resultStore, Address _expectedAddr); | void checkStorage(std::map<u256, u256> _expectedStore, std::map<u256, u256> _resultStore, Address _expectedAddr); | ||||||
|  | void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); | ||||||
| void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests); | void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests); | ||||||
| std::string getTestPath(); | std::string getTestPath(); | ||||||
| void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests); | void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests); | ||||||
|  | |||||||
| @ -33,6 +33,40 @@ | |||||||
|         } |         } | ||||||
|      }, |      }, | ||||||
| 
 | 
 | ||||||
|  |     "CallEcrecover0_completeReturnValue": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MLOAD 128) }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|     "CallEcrecover0_gas500": { |     "CallEcrecover0_gas500": { | ||||||
|          "env" : { |          "env" : { | ||||||
|              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
| @ -305,6 +339,40 @@ | |||||||
|         } |         } | ||||||
|      }, |      }, | ||||||
| 
 | 
 | ||||||
|  |     "CallSha256_1_nonzeroValue": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ [[ 2 ]] (CALL 500 2 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|     "CallSha256_2": { |     "CallSha256_2": { | ||||||
|          "env" : { |          "env" : { | ||||||
|              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								stSpecialTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								stSpecialTestFiller.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | { | ||||||
|  |    "makeMoney" : { | ||||||
|  |         "env" : { | ||||||
|  |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |             "currentNumber" : "0", | ||||||
|  |             "currentGasLimit" : "1000000", | ||||||
|  |             "currentDifficulty" : "256", | ||||||
|  |             "currentTimestamp" : 1, | ||||||
|  |             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |             "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) (CALL 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec 0xaaaaaaaaace5edbc8e2a8697c15331677e6ebf0b 23 0 0 0 0) }", | ||||||
|  |                 "storage": {} | ||||||
|  |             }, | ||||||
|  |             "aaaaaaaaace5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "0x600160015532600255", | ||||||
|  |                 "storage": {} | ||||||
|  |             }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "850", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "10", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -122,6 +122,11 @@ BOOST_AUTO_TEST_CASE(stPreCompiledContracts) | |||||||
| 	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); | 	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(stSpecialTest) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(stCreateTest) | BOOST_AUTO_TEST_CASE(stCreateTest) | ||||||
| { | { | ||||||
| 	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) | ||||||
|  | |||||||
							
								
								
									
										47
									
								
								vm.cpp
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								vm.cpp
									
									
									
									
									
								
							| @ -120,6 +120,41 @@ void FakeExtVM::importEnv(mObject& _o) | |||||||
| 	currentBlock.coinbaseAddress = Address(_o["currentCoinbase"].get_str()); | 	currentBlock.coinbaseAddress = Address(_o["currentCoinbase"].get_str()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | mObject FakeExtVM::exportLog() | ||||||
|  | { | ||||||
|  | 	mObject ret; | ||||||
|  | 	for (LogEntry const& l: sub.logs) | ||||||
|  | 	{ | ||||||
|  | 		mObject o; | ||||||
|  | 		o["address"] = toString(l.address); | ||||||
|  | 		mArray topics; | ||||||
|  | 		for (auto const& t: l.topics) | ||||||
|  | 			topics.push_back(toString(t)); | ||||||
|  | 		o["topics"] = topics; | ||||||
|  | 		o["data"] = "0x" + toHex(l.data); | ||||||
|  | 		ret[toString(l.bloom())] = o; | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FakeExtVM::importLog(mObject& _o) | ||||||
|  | { | ||||||
|  | 	for (auto const& l: _o) | ||||||
|  | 	{ | ||||||
|  | 		mObject o = l.second.get_obj(); | ||||||
|  | 		// cant use BOOST_REQUIRE, because this function is used outside boost test (createRandomTest)
 | ||||||
|  | 		assert(o.count("address") > 0); | ||||||
|  | 		assert(o.count("topics") > 0); | ||||||
|  | 		assert(o.count("data") > 0); | ||||||
|  | 		LogEntry log; | ||||||
|  | 		log.address = Address(o["address"].get_str()); | ||||||
|  | 		for (auto const& t: o["topics"].get_array()) | ||||||
|  | 			log.topics.insert(h256(t.get_str())); | ||||||
|  | 		log.data = importData(o); | ||||||
|  | 		sub.logs.push_back(log); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| mObject FakeExtVM::exportState() | mObject FakeExtVM::exportState() | ||||||
| { | { | ||||||
| 	mObject ret; | 	mObject ret; | ||||||
| @ -303,7 +338,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 		bool vmExceptionOccured = false; | 		bool vmExceptionOccured = false; | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			output = vm.go(fev, fev.simpleTrace()).toVector(); | 			output = vm.go(fev, fev.simpleTrace()).toBytes(); | ||||||
| 			gas = vm.gas(); | 			gas = vm.gas(); | ||||||
| 		} | 		} | ||||||
| 		catch (VMException const& _e) | 		catch (VMException const& _e) | ||||||
| @ -349,6 +384,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 				o["callcreates"] = fev.exportCallCreates(); | 				o["callcreates"] = fev.exportCallCreates(); | ||||||
| 				o["out"] = "0x" + toHex(output); | 				o["out"] = "0x" + toHex(output); | ||||||
| 				fev.push(o, "gas", gas); | 				fev.push(o, "gas", gas); | ||||||
|  | 				o["logs"] = mValue(fev.exportLog()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -361,10 +397,12 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 				BOOST_REQUIRE(o.count("callcreates") > 0); | 				BOOST_REQUIRE(o.count("callcreates") > 0); | ||||||
| 				BOOST_REQUIRE(o.count("out") > 0); | 				BOOST_REQUIRE(o.count("out") > 0); | ||||||
| 				BOOST_REQUIRE(o.count("gas") > 0); | 				BOOST_REQUIRE(o.count("gas") > 0); | ||||||
|  | 				BOOST_REQUIRE(o.count("logs") > 0); | ||||||
| 
 | 
 | ||||||
| 				dev::test::FakeExtVM test; | 				dev::test::FakeExtVM test; | ||||||
| 				test.importState(o["post"].get_obj()); | 				test.importState(o["post"].get_obj()); | ||||||
| 				test.importCallCreates(o["callcreates"].get_array()); | 				test.importCallCreates(o["callcreates"].get_array()); | ||||||
|  | 				test.importLog(o["logs"].get_obj()); | ||||||
| 
 | 
 | ||||||
| 				checkOutput(output, o); | 				checkOutput(output, o); | ||||||
| 
 | 
 | ||||||
| @ -392,6 +430,8 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 
 | 
 | ||||||
| 				checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses); | 				checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses); | ||||||
| 				BOOST_CHECK(test.callcreates == fev.callcreates); | 				BOOST_CHECK(test.callcreates == fev.callcreates); | ||||||
|  | 
 | ||||||
|  | 				checkLog(fev.sub.logs, test.sub.logs); | ||||||
| 			} | 			} | ||||||
| 			else	// Exception expected
 | 			else	// Exception expected
 | ||||||
| 				BOOST_CHECK(vmExceptionOccured); | 				BOOST_CHECK(vmExceptionOccured); | ||||||
| @ -443,6 +483,11 @@ BOOST_AUTO_TEST_CASE(vmPushDupSwapTest) | |||||||
| 	dev::test::executeTests("vmPushDupSwapTest", "/VMTests", dev::test::doVMTests); | 	dev::test::executeTests("vmPushDupSwapTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(vmLogTest) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("vmLogTest", "/VMTests", dev::test::doVMTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmRandom) | BOOST_AUTO_TEST_CASE(vmRandom) | ||||||
| { | { | ||||||
| 	string testPath = getTestPath(); | 	string testPath = getTestPath(); | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								vm.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								vm.h
									
									
									
									
									
								
							| @ -66,6 +66,8 @@ public: | |||||||
| 	u256 doPosts(); | 	u256 doPosts(); | ||||||
| 	json_spirit::mObject exportEnv(); | 	json_spirit::mObject exportEnv(); | ||||||
| 	void importEnv(json_spirit::mObject& _o); | 	void importEnv(json_spirit::mObject& _o); | ||||||
|  | 	json_spirit::mObject exportLog(); | ||||||
|  | 	void importLog(json_spirit::mObject& _o); | ||||||
| 	json_spirit::mObject exportState(); | 	json_spirit::mObject exportState(); | ||||||
| 	void importState(json_spirit::mObject& _object); | 	void importState(json_spirit::mObject& _object); | ||||||
| 	json_spirit::mObject exportExec(); | 	json_spirit::mObject exportExec(); | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     "dupAt51doesNotExistAnymore": { |     "dupAt51becameMload": { | ||||||
|         "env" : { |         "env" : { | ||||||
|         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|         "currentNumber" : "0", |         "currentNumber" : "0", | ||||||
| @ -83,7 +83,7 @@ | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     "swapAt52doesNotExistAnymore": { |     "swapAt52becameMstore": { | ||||||
|         "env" : { |         "env" : { | ||||||
|         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|         "currentNumber" : "0", |         "currentNumber" : "0", | ||||||
|  | |||||||
							
								
								
									
										1266
									
								
								vmLogTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1266
									
								
								vmLogTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -924,7 +924,7 @@ | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     "push32error": { |     "push32AndSuicide": { | ||||||
|         "env" : { |         "env" : { | ||||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|             "currentNumber" : "0", |             "currentNumber" : "0", | ||||||
| @ -952,6 +952,35 @@ | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     "push32FillUpInputWithZerosAtTheEnd": { | ||||||
|  |         "env" : { | ||||||
|  |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |             "currentNumber" : "0", | ||||||
|  |             "currentGasLimit" : "1000000", | ||||||
|  |             "currentDifficulty" : "256", | ||||||
|  |             "currentTimestamp" : 1, | ||||||
|  |             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "0x7fff10112233445566778899aabbccddeeff00112233445566778899aabbccdd", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|     "dup1": { |     "dup1": { | ||||||
|         "env" : { |         "env" : { | ||||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user