1 #include <boost/test/unit_test.hpp>
2 #include <qtumtests/test_utils.h>
3 #include <script/standard.h>
4 #include <chainparams.h>
5
6 namespace BtcEcrecoverTest{
7
8 const dev::u256 GASLIMIT = dev::u256(500000);
9 const dev::h256 HASHTX = dev::h256(ParseHex("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
10
11 // Contract for btc_ecrecover check
12 const std::vector<valtype> CODE = {
13 /*
14 pragma solidity ^0.4.0;
15 library Crypto
16 {
17 function btc_ecrecover(bytes32 msgh, uint8 v, bytes32 r, bytes32 s) public view returns(bytes addr)
18 {
19 uint256[4] memory input;
20 input[0] = uint256(msgh);
21 input[1] = v;
22 input[2] = uint256(r);
23 input[3] = uint256(s);
24
25 uint256[2] memory p;
26 assembly
27 {
28 if iszero(call(not(0), 0x85, 0, input, 0x80, p, 0x40))
29 {
30 revert(0, 0)
31 }
32 }
33 addr = toBytes(p[0]);
34 }
35
36 function toBytes(uint256 x) internal pure returns (bytes b)
37 {
38 b = new bytes(32);
39 assembly { mstore(add(b, 32), x) }
40 }
41 }
42 */
43 // Contract that call btc_ecrecover
44 valtype(ParseHex("61029e610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3007300000000000000000000000000000000000000003014608060405260043610610058576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806369bc09631461005d575b600080fd5b6100a86004803603810190808035600019169060200190929190803560ff16906020019092919080356000191690602001909291908035600019169060200190929190505050610123565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100e85780820151818401526020810190506100cd565b50505050905090810190601f1680156101155780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b606061012d61022d565b610135610250565b866001900482600060048110151561014957fe5b6020020181815250508560ff1682600160048110151561016557fe5b602002018181525050846001900482600260048110151561018257fe5b602002018181525050836001900482600360048110151561019f57fe5b60200201818152505060408160808460006085600019f115156101c157600080fd5b6101dd8160006002811015156101d357fe5b60200201516101e9565b92505050949350505050565b606060206040519080825280601f01601f19166020018201604052801561021f5781602001602082028038833980820191505090505b509050816020820152919050565b608060405190810160405280600490602082028038833980820191505090505090565b60408051908101604052806002906020820280388339808201915050905050905600a165627a7a723058202c030fcf0261d136398030f4a0109ecc4c041333bf65bcbd4995b2f8332926890029")),
45
46 // btc_ecrecover(bytes32 msgh, uint8 v, bytes32 r, bytes32 s) v=27
47 valtype(ParseHex("69bc09631476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750000000000000000000000000000000000000000000000000000000000000001be6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce")),
48
49 // btc_ecrecover(bytes32 msgh, uint8 v, bytes32 r, bytes32 s) v=28
50 valtype(ParseHex("69bc09631476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750000000000000000000000000000000000000000000000000000000000000001ce6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce")),
51
52 // btc_ecrecover(bytes32 msgh, uint8 v, bytes32 r, bytes32 s) v=31
53 valtype(ParseHex("69bc09631476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750000000000000000000000000000000000000000000000000000000000000001fe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce")),
54
55 // btc_ecrecover(bytes32 msgh, uint8 v, bytes32 r, bytes32 s) v=32
56 valtype(ParseHex("69bc09631476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f7500000000000000000000000000000000000000000000000000000000000000020e6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce")),
57
58 // Valid address result v=27
59 valtype(ParseHex("00000000000000000000000011f50cfcb40d4e0bcdb4c728664d26bd969c8661")),
60
61 // Valid address result v=28
62 valtype(ParseHex("0000000000000000000000005b0bf163d8d62090d634bc5c20bb47602cc686fe")),
63
64 // Valid address result v=31
65 valtype(ParseHex("000000000000000000000000931c1f36709cd3aa8623a38db7a905d31ddf97e3")),
66
67 // Valid address result v=32
68 valtype(ParseHex("000000000000000000000000575e154116a125cee7053db093d94c6fb522144f")),
69
70 // Not valid address result
71 valtype(ParseHex("0000000000000000000000000000000000000000000000000000000000000000"))
72 };
73
parseOutput(const dev::bytes & output)74 dev::bytes parseOutput(const dev::bytes& output)
75 {
76 return dev::bytes(output.begin() + 64, output.end());
77 }
78
genesisLoading()79 void genesisLoading(){
80 const CChainParams& chainparams = Params();
81 dev::eth::ChainParams cp(chainparams.EVMGenesisInfo());
82 globalState->populateFrom(cp.genesisState);
83 globalSealEngine = std::unique_ptr<dev::eth::SealEngineFace>(cp.createSealEngine());
84 globalState->db().commit();
85 }
86
createNewBlocks(TestChain100Setup * testChain100Setup,size_t n)87 void createNewBlocks(TestChain100Setup* testChain100Setup, size_t n){
88 std::function<void(size_t n)> generateBlocks = [&](size_t n){
89 dev::h256 oldHashStateRoot = globalState->rootHash();
90 dev::h256 oldHashUTXORoot = globalState->rootHashUTXO();
91 for(size_t i = 0; i < n; i++){
92 testChain100Setup->CreateAndProcessBlock({}, GetScriptForRawPubKey(testChain100Setup->coinbaseKey.GetPubKey()));
93 }
94 globalState->setRoot(oldHashStateRoot);
95 globalState->setRootUTXO(oldHashUTXORoot);
96 };
97
98 generateBlocks(n);
99 }
BOOST_FIXTURE_TEST_SUITE(btcecrecoverfork_tests,TestChain100Setup)100 BOOST_FIXTURE_TEST_SUITE(btcecrecoverfork_tests, TestChain100Setup)
101
102 BOOST_AUTO_TEST_CASE(checking_btcecrecover_after_fork){
103 // Initialize
104 // initState();
105 genesisLoading();
106 createNewBlocks(this, 499);
107 dev::h256 hashTx(HASHTX);
108
109 // Create contract
110 std::vector<QtumTransaction> txs;
111 txs.push_back(createQtumTransaction(CODE[0], 0, GASLIMIT, dev::u256(1), hashTx, dev::Address()));
112 executeBC(txs);
113
114 // Call btc_ecrecover
115 dev::Address proxy = createQtumAddress(txs[0].getHashWith(), txs[0].getNVout());
116 std::vector<QtumTransaction> txBtcEcrecover;
117 txBtcEcrecover.push_back(createQtumTransaction(CODE[1], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
118 txBtcEcrecover.push_back(createQtumTransaction(CODE[2], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
119 txBtcEcrecover.push_back(createQtumTransaction(CODE[3], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
120 txBtcEcrecover.push_back(createQtumTransaction(CODE[4], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
121
122 // Execute contracts
123 auto result = executeBC(txBtcEcrecover);
124
125 // Check results
126 dev::bytes output = parseOutput(result.first[0].execRes.output);
127 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[5]));
128 output = parseOutput(result.first[1].execRes.output);
129 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[6]));
130 output = parseOutput(result.first[2].execRes.output);
131 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[7]));
132 output = parseOutput(result.first[3].execRes.output);
133 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[8]));
134 }
135
BOOST_AUTO_TEST_CASE(checking_btcecrecover_before_fork)136 BOOST_AUTO_TEST_CASE(checking_btcecrecover_before_fork){
137 // Initialize
138 // initState();
139 genesisLoading();
140 createNewBlocks(this, 498);
141 dev::h256 hashTx(HASHTX);
142
143 // Create contract
144 std::vector<QtumTransaction> txs;
145 txs.push_back(createQtumTransaction(CODE[0], 0, GASLIMIT, dev::u256(1), hashTx, dev::Address()));
146 executeBC(txs);
147
148 // Call btc_ecrecover
149 dev::Address proxy = createQtumAddress(txs[0].getHashWith(), txs[0].getNVout());
150 std::vector<QtumTransaction> txBtcEcrecover;
151 txBtcEcrecover.push_back(createQtumTransaction(CODE[1], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
152 txBtcEcrecover.push_back(createQtumTransaction(CODE[2], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
153 txBtcEcrecover.push_back(createQtumTransaction(CODE[3], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
154 txBtcEcrecover.push_back(createQtumTransaction(CODE[4], 0, GASLIMIT, dev::u256(1), ++hashTx, proxy));
155
156 // Execute contracts
157 auto result = executeBC(txBtcEcrecover);
158
159 // Check results
160 dev::bytes output = parseOutput(result.first[0].execRes.output);
161 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[9]));
162 output = parseOutput(result.first[1].execRes.output);
163 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[9]));
164 output = parseOutput(result.first[2].execRes.output);
165 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[9]));
166 output = parseOutput(result.first[3].execRes.output);
167 BOOST_CHECK(dev::h256(output) == dev::h256(CODE[9]));
168 }
169
170 BOOST_AUTO_TEST_SUITE_END()
171
172 }
173