1from .address import *
2from .script import *
3from .mininode import *
4from .util import *
5from .qtumconfig import *
6from .blocktools import *
7from .key import *
8from .segwit_addr import *
9import io
10import base64
11import math
12import pprint
13
14pp = pprint.PrettyPrinter()
15
16def generatesynchronized(node, numblocks, address=None, sync_with_nodes=[]):
17    if not address:
18        address = node.getnewaddress()
19
20    blockhashes = []
21    for i in range(0, max(numblocks//16, 0)):
22        blockhashes += node.generatetoaddress(16, address)
23        sync_blocks(sync_with_nodes, wait=0.001)
24
25    if numblocks % 16:
26        blockhashes += node.generatetoaddress(numblocks % 16, address)
27        sync_blocks(sync_with_nodes, wait=0.001)
28    return blockhashes
29
30def generateinitial(node, numblocks, address=None, sync_with_nodes=[]):
31    mocktime = node.getblock(node.getbestblockhash())['mocktime']
32    for n in [node] + sync_with_nodes:
33        n.setmocktime(mocktime)
34
35    blockhashes = node.generatetoaddress(numblocks, address)
36
37    for n in [node] + sync_with_nodes:
38        n.setmocktime(0)
39
40    return blockhashes
41
42def make_transaction(node, vin, vout):
43    tx = CTransaction()
44    tx.vin = vin
45    tx.vout = vout
46    tx.rehash()
47
48    unsigned_raw_tx = bytes_to_hex_str(tx.serialize_without_witness())
49    signed_raw_tx = node.signrawtransactionwithwallet(unsigned_raw_tx)['hex']
50    return signed_raw_tx
51
52def make_vin(node, value):
53    addr = node.getnewaddress()
54    txid_hex = node.sendtoaddress(addr, value/COIN)
55    txid = int(txid_hex, 16)
56    node.generate(1)
57    raw_tx = node.decoderawtransaction(node.gettransaction(txid_hex)['hex'])
58
59    for vout_index, txout in enumerate(raw_tx['vout']):
60        if txout['scriptPubKey']['addresses'] == [addr]:
61            break
62    else:
63        assert False
64
65    return CTxIn(COutPoint(txid, vout_index), nSequence=0)
66
67def make_op_create_output(node, value, version, gas_limit, gas_price, data):
68    scriptPubKey = CScript()
69    scriptPubKey += version
70    scriptPubKey += gas_limit
71    scriptPubKey += gas_price
72    scriptPubKey += data
73    scriptPubKey += OP_CREATE
74    return CTxOut(value, scriptPubKey)
75
76def make_op_call_output(value, version, gas_limit, gas_price, data, contract):
77    scriptPubKey = CScript()
78    scriptPubKey += version
79    scriptPubKey += gas_limit
80    scriptPubKey += gas_price
81    scriptPubKey += data
82    scriptPubKey += contract
83    scriptPubKey += OP_CALL
84    return CTxOut(value, scriptPubKey)
85
86def convert_btc_address_to_qtum(addr, main=False):
87    version, hsh, checksum = base58_to_byte(addr, 25)
88    if version == 111:
89        return keyhash_to_p2pkh(binascii.unhexlify(hsh), main)
90
91    if version == 196:
92        return scripthash_to_p2sh(binascii.unhexlify(hsh), main)
93    assert(False)
94
95def convert_btc_bech32_address_to_qtum(addr, main=False):
96    hdr, data = bech32_decode(addr)
97    return bech32_encode('qcrt', data)
98
99
100def p2pkh_to_hex_hash(address):
101    return str(base58_to_byte(address, 25)[1])[2:-1]
102
103def hex_hash_to_p2pkh(hex_hash):
104    return keyhash_to_p2pkh(hex_str_to_bytes(hex_hash))
105
106def assert_vin(tx, expected_vin):
107    assert_equal(len(tx['vin']), len(expected_vin))
108    matches = []
109    for expected in expected_vin:
110        for i in range(len(tx['vin'])):
111            if i not in matches and expected[0] == tx['vin'][i]['scriptSig']['asm']:
112                matches.append(i)
113                break
114    assert_equal(len(matches), len(expected_vin))
115
116def assert_vout(tx, expected_vout):
117    assert_equal(len(tx['vout']), len(expected_vout))
118    matches = []
119    for expected in expected_vout:
120        for i in range(len(tx['vout'])):
121            if i not in matches and expected[0] == tx['vout'][i]['value'] and expected[1] == tx['vout'][i]['scriptPubKey']['type']:
122                matches.append(i)
123                break
124    assert_equal(len(matches), len(expected_vout))
125
126def rpc_sign_transaction(node, tx):
127    ret = node.signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize()))
128    if not ret['complete']:
129        print(ret)
130        assert(ret['complete'])
131    tx_signed_raw_hex = ret['hex']
132    f = io.BytesIO(hex_str_to_bytes(tx_signed_raw_hex))
133    tx_signed = CTransaction()
134    tx_signed.deserialize(f)
135    return tx_signed
136
137def make_vin_from_unspent(node, unspents=None, value=2000000000000, address=None):
138    if not unspents:
139        unspents = node.listunspent()
140    for i in range(len(unspents)):
141        unspent = unspents[i]
142        if unspent['amount'] == value/COIN and (not address or address == unspent['address']):
143            unspents.pop(i)
144            return CTxIn(COutPoint(int(unspent['txid'], 16), unspent['vout']), nSequence=0)
145    return None
146
147def read_evm_array(node, address, abi, ignore_nulls=True):
148    arr = []
149    index = 0
150    ret = node.callcontract(address, abi + hex(index)[2:].zfill(64))
151    while ret['executionResult']['excepted'] == 'None':
152        if int(ret['executionResult']['output'], 16) != 0 or not ignore_nulls:
153            arr.append(ret['executionResult']['output'])
154        index += 1
155        ret = node.callcontract(address, abi + hex(index)[2:].zfill(64))
156    return arr
157
158class DGPState:
159    def __init__(self, node, contract_address):
160        self.last_state_assert_block_height = 0
161        self.node = node
162        self.contract_address = contract_address
163        self.param_count = 0
164        self.gov_keys = []
165        self.admin_keys = []
166        self.params_for_block = []
167        self.param_address_at_indices = []
168        self.required_votes = [0, 0, 0]
169        self.current_on_vote_statuses = [
170            [False, False, False],
171            [False, False, False],
172            [False, False]
173        ]
174        self.current_on_vote_address_proposals = [
175            ["0", "0", "0"],
176            ["0", "0"]
177        ]
178        self.abiAddAddressProposal = "bf5f1e83" #addAddressProposal(address,uint256)
179        self.abiRemoveAddressProposal = "4cc0e2bc" # removeAddressProposal(address,uint256)
180        self.abiChangeValueProposal = "19971cbd" # changeValueProposal(uint256,uint256)
181        self.abiAlreadyVoted = "e9944a81" # alreadyVoted(address,address[])
182        self.abiGetAddressesList = "850d9758" # getAddressesList(uint256)
183        self.abiGetArrayNonNullLength = "9b216626" # getArrayNonNullLenght(address[])
184        self.abiGetCurrentOnVoteAddressProposal = "0c83ebac" # getCurrentOnVoteAddressProposal(uint256,uint256)
185        self.abiGetCurrentOnVoteStatus = "5f302e8b" # getCurrentOnVoteStatus(uint256,uint256)
186        self.abiGetCurrentOnVoteValueProposal = "4364725c" # getCurrentOnVoteValueProposal(uint256)
187        self.abiGetCurrentOnVoteVotes = "f9f51401" # getCurrentOnVoteVotes(uint256,uint256)
188        self.abiGetParamAddressAtIndex = "15341747" # getParamAddressAtIndex(uint256)
189        self.abiGetParamCount = "27e35746" # getParamCount()
190        self.abiGetParamHeightAtIndex = "8a5a9d07" # getParamHeightAtIndex(uint256)
191        self.abiGetParamsForBlock = "f769ac48" # getParamsForBlock(uint256)
192        self.abiGetRequiredVotes = "1ec28e0f" # getRequiredVotes(uint256)
193        self.abiIsAdminKey = "6b102c49" # isAdminKey(address)
194        self.abiIsGovKey = "7b993bf3" # isGovKey(address)
195        self.abiSetInitialAdmin = "6fb81cbb" # setInitialAdmin()
196        self.abiTallyAdminVotes = "bec171e5" # tallyAdminVotes(address[])
197        self.abiTallyGovVotes = "4afb4f11" # tallyGovVotes(address[])
198        self.abiGovKeys = "30a79873" # govKeys(uint256)
199        self.abiAdminKeys = "aff125f6" # adminKeys(uint256)
200
201    def send_set_initial_admin(self, sender):
202        self.node.sendtoaddress(sender, 1)
203        self.node.sendtocontract(self.contract_address, self.abiSetInitialAdmin, 0, 2000000, QTUM_MIN_GAS_PRICE_STR, sender)
204
205    def send_add_address_proposal(self, proposal_address, type1, sender):
206        self.node.sendtoaddress(sender, 1)
207        txid = self.node.sendtocontract(self.contract_address, self.abiAddAddressProposal + proposal_address.zfill(64) + hex(type1)[2:].zfill(64), 0, 20000000, QTUM_MIN_GAS_PRICE_STR, sender)['txid']
208        return txid
209
210    def send_remove_address_proposal(self, proposal_address, type1, sender):
211        self.node.sendtoaddress(sender, 1)
212        txid = self.node.sendtocontract(self.contract_address, self.abiRemoveAddressProposal + proposal_address.zfill(64) + hex(type1)[2:].zfill(64), 0, 20000000, QTUM_MIN_GAS_PRICE_STR, sender)['txid']
213        return txid
214
215    def send_change_value_proposal(self, uint_proposal, type1, sender):
216        self.node.sendtoaddress(sender, 1)
217        txid = self.node.sendtocontract(self.contract_address, self.abiChangeValueProposal + hex(uint_proposal)[2:].zfill(64) + hex(type1)[2:].zfill(64), 0, 20000000, QTUM_MIN_GAS_PRICE_STR, sender)['txid']
218        return txid
219
220
221    def assert_state(self):
222        # This assertion is only to catch potential errors in the test code (if we forget to add a generate after an evm call)
223        assert(self.last_state_assert_block_height < self.node.getblockcount())
224        self.last_state_assert_block_height = self.node.getblockcount()
225
226        self._assert_param_count(self.param_count)
227        self._assert_gov_keys_equal(self.gov_keys)
228        self._assert_admin_keys_equal(self.admin_keys)
229        for block_height, param_for_block in self.params_for_block:
230            self._assert_params_for_block(block_height, param_for_block)
231        # Make sure that there are no subsequent params for blocks
232        if self.params_for_block:
233            ret = self.node.callcontract(self.contract_address, self.abiGetParamsForBlock + hex(0x2fff)[2:].zfill(64))
234            assert_equal(int(ret['executionResult']['output'], 16), int(param_for_block, 16))
235        else:
236            ret = self.node.callcontract(self.contract_address, self.abiGetParamsForBlock + hex(0x2fff)[2:].zfill(64))
237            assert_equal(int(ret['executionResult']['output'], 16), 0)
238
239
240        for index, param_address_at_index in enumerate(self.param_address_at_indices):
241            self._assert_param_address_at_index(index, param_address_at_index)
242        # Make sure that there are no subsequent params at the next index
243        if self.param_address_at_indices:
244            ret = self.node.callcontract(self.contract_address, self.abiGetParamAddressAtIndex + hex(index+1)[2:].zfill(64))
245            assert(ret['executionResult']['excepted'] != 'None')
246        else:
247            ret = self.node.callcontract(self.contract_address, self.abiGetParamAddressAtIndex + hex(0x0)[2:].zfill(64))
248            assert(ret['executionResult']['excepted'] != 'None')
249
250
251        for type1, required_votes in enumerate(self.required_votes):
252            self._assert_required_votes(type1, required_votes)
253        for type1, arr1 in enumerate(self.current_on_vote_statuses):
254            for type2, current_on_vote_status in enumerate(arr1):
255                self._assert_current_on_vote_status(type1, type2, current_on_vote_status)
256        for type1, arr1 in enumerate(self.current_on_vote_address_proposals):
257            for type2, current_on_vote_address_proposal in enumerate(arr1):
258                self._assert_current_on_vote_address_proposal(type1, type2, current_on_vote_address_proposal)
259
260    """
261    function getRequiredVotes(uint _type) constant returns (uint val){
262        // type 0: adminVotesForParams
263        // type 1: govVotesForParams
264        // type 2: adminVotesForManagement
265        if(_type>2) throw; // invalid type
266        if(_type==0)return activeVotesRequired.adminVotesForParams;
267        if(_type==1)return activeVotesRequired.govVotesForParams;
268        if(_type==2)return activeVotesRequired.adminVotesForManagement;
269    }
270    """
271    def _assert_required_votes(self, type1, expected_required_votes):
272        ret = self.node.callcontract(self.contract_address, self.abiGetRequiredVotes + str(type1).zfill(64))
273        assert_equal(int(ret['executionResult']['output'], 16), expected_required_votes)
274
275    """
276   function getCurrentOnVoteStatus(uint _type, uint _type2) constant returns (bool val){
277        // type 0: addAddress
278        // type 1: changeValue
279        // type 2: removeAddress
280
281        // type2 0: adminKey
282        // type2 1: govKey
283        // type2 2: paramsAddress
284
285        if(_type>2 || _type2>2) throw; // invalid type
286        if(_type==0)return currentProposals.keys[_type2].onVote;
287        if(_type==1)return currentProposals.uints[_type2].onVote;
288        if(_type==2)return currentProposals.removeKeys[_type2].onVote;
289    }
290    """
291    def _assert_current_on_vote_status(self, type1, type2, expected_current_on_vote_status):
292        ret = self.node.callcontract(self.contract_address, self.abiGetCurrentOnVoteStatus + str(type1).zfill(64) + str(type2).zfill(64))
293        assert_equal(int(ret['executionResult']['output'], 16), expected_current_on_vote_status)
294
295    """
296    function getCurrentOnVoteAddressProposal(uint _type, uint _type2) constant returns (address val){
297        // type 0: addAddress
298        // type 1: removeAddress
299
300        // type2 0: adminKey
301        // type2 1: govKey
302        // type2 2: paramsAddress
303
304        if(_type>1 || _type2>2) throw; // invalid type
305        if(_type==0)return currentProposals.keys[_type2].proposal;
306        if(_type==1)return currentProposals.removeKeys[_type2].proposal;
307    }
308    """
309    def _assert_current_on_vote_address_proposal(self, type1, type2, expected_address):
310        ret = self.node.callcontract(self.contract_address, self.abiGetCurrentOnVoteAddressProposal + hex(type1)[2:].zfill(64) + hex(type2)[2:].zfill(64))
311        assert_equal(int(ret['executionResult']['output'], 16), int(expected_address, 16))
312
313    """
314    function getCurrentOnVoteValueProposal(uint _type) constant returns (uint val){
315        // type 0: adminVotesForParams
316        // type 1: govVotesForParams
317        // type 2: adminVotesForManagement
318
319        if(_type>2) throw; // invalid type
320        return currentProposals.uints[_type].proposal;
321    }
322    """
323    def _assert_current_on_vote_value_proposal(self, type1, expected_proposal):
324        ret = self.node.callcontract(self.contract_address, self.abiGetCurrentOnVoteValueProposal + hex(type1)[2:].zfill(64))
325        assert_equal(int(ret['executionResult']['output'], 16), expected_proposal)
326
327    """
328    function getParamsForBlock(uint _reqBlockHeight) constant returns (address paramsAddress){
329        uint i;
330        for(i=paramsHistory.length-1;i>0;i--){
331            if(paramsHistory[i].blockHeight<=_reqBlockHeight)return paramsHistory[i].paramsAddress;
332        }
333        if(paramsHistory[0].blockHeight<=_reqBlockHeight)return paramsHistory[0].paramsAddress;
334        return 0;
335    }
336    """
337    def _assert_params_for_block(self, required_block_height, expected_param_address):
338        ret = self.node.callcontract(self.contract_address, self.abiGetParamsForBlock + hex(required_block_height)[2:].zfill(64))
339        assert_equal(int(ret['executionResult']['output'], 16), int(expected_param_address, 16))
340
341    """
342    function getParamAddressAtIndex(uint _paramIndex) constant returns (address paramsAddress){
343        return paramsHistory[_paramIndex].paramsAddress;
344    }
345    """
346    def _assert_param_address_at_index(self, param_index, expected_param_address):
347        ret = self.node.callcontract(self.contract_address, self.abiGetParamAddressAtIndex + hex(param_index)[2:].zfill(64))
348        assert_equal(int(ret['executionResult']['output'], 16), int(expected_param_address, 16))
349
350
351    """
352    function getParamHeightAtIndex(uint _paramIndex) constant returns (uint paramsHeight){
353        return paramsHistory[_paramIndex].blockHeight;
354    }
355    """
356    def _assert_param_block_height_at_index(self, param_index, expected_block_height):
357        ret = self.node.callcontract(self.contract_address, self.abiGetParamHeightAtIndex + hex(param_index)[2:].zfill(64))
358        assert_equal(int(ret['executionResult']['output'], 16), expected_block_height)
359
360    """
361    function getParamCount() constant returns (uint paramsCount){
362        return paramsHistory.length;
363    }
364    """
365    def _assert_param_count(self, expected_param_count):
366        ret = self.node.callcontract(self.contract_address, self.abiGetParamCount)
367        assert_equal(int(ret['executionResult']['output'], 16), expected_param_count)
368
369    def _assert_gov_keys_equal(self, expected_gov_keys):
370        real_gov_keys = read_evm_array(self.node, self.contract_address, self.abiGovKeys)
371        assert_equal(len(real_gov_keys), len(expected_gov_keys))
372        for real, expected in zip(real_gov_keys, expected_gov_keys):
373            assert_equal(int(real, 16), int(expected, 16))
374
375    def _assert_admin_keys_equal(self, expected_admin_keys):
376        real_admin_keys = read_evm_array(self.node, self.contract_address, self.abiAdminKeys)
377        assert_equal(len(real_admin_keys), len(expected_admin_keys))
378        for real, expected in zip(real_admin_keys, expected_admin_keys):
379            assert_equal(int(real, 16), int(expected, 16))
380
381
382def collect_prevouts(node, amount=None, address=None, min_confirmations=COINBASE_MATURITY, min_amount=0):
383    blocks = []
384    for block_no in range(1, node.getblockcount()+1):
385        blocks.append(node.getblock(node.getblockhash(block_no)))
386
387
388    staking_prevouts = []
389    for unspent in node.listunspent():
390        for block in blocks:
391            if unspent['txid'] in block['tx']:
392                tx_block_time = block['time']
393                break
394        else:
395            assert(False)
396        if unspent['confirmations'] > min_confirmations and (not amount or amount == unspent['amount']) and (not address or address == unspent['address']) and unspent['amount'] >= min_amount:
397            staking_prevouts.append((COutPoint(int(unspent['txid'], 16), unspent['vout']), int(unspent['amount']*COIN), tx_block_time))
398    return staking_prevouts
399
400
401def create_unsigned_pos_block(node, staking_prevouts, nTime=None):
402    tip = node.getblock(node.getbestblockhash())
403    if not nTime:
404        current_time = int(time.time()) + TIMESTAMP_MASK+1
405        nTime = current_time & (0xffffffff - TIMESTAMP_MASK)
406
407    parent_block_stake_modifier = int(tip['modifier'], 16)
408    coinbase = create_coinbase(tip['height']+1)
409    coinbase.vout[0].nValue = 0
410    coinbase.vout[0].scriptPubKey = b""
411    coinbase.rehash()
412    block = create_block(int(tip['hash'], 16), coinbase, nTime)
413    block.hashStateRoot = int(tip['hashStateRoot'], 16)
414    block.hashUTXORoot = int(tip['hashUTXORoot'], 16)
415
416    if not block.solve_stake(parent_block_stake_modifier, staking_prevouts):
417        return None
418
419    txout = node.gettxout(hex(block.prevoutStake.hash)[2:].zfill(64), block.prevoutStake.n)
420    # input value + block reward
421    out_value = int((float(str(txout['value'])) + INITIAL_BLOCK_REWARD_POS) * COIN) // 2
422
423    # create a new private key used for block signing.
424    block_sig_key = ECKey()
425    block_sig_key.set(hash256(struct.pack('<I', 0)), False)
426    pubkey = block_sig_key.get_pubkey().get_bytes()
427    scriptPubKey = CScript([pubkey, OP_CHECKSIG])
428    stake_tx_unsigned = CTransaction()
429
430    stake_tx_unsigned.vin.append(CTxIn(block.prevoutStake))
431    stake_tx_unsigned.vout.append(CTxOut())
432
433    # Split the output value into two separate txs
434    stake_tx_unsigned.vout.append(CTxOut(int(out_value), scriptPubKey))
435    stake_tx_unsigned.vout.append(CTxOut(int(out_value), scriptPubKey))
436
437    stake_tx_signed_raw_hex = node.signrawtransactionwithwallet(bytes_to_hex_str(stake_tx_unsigned.serialize()))['hex']
438    f = io.BytesIO(hex_str_to_bytes(stake_tx_signed_raw_hex))
439    stake_tx_signed = CTransaction()
440    stake_tx_signed.deserialize(f)
441    block.vtx.append(stake_tx_signed)
442    block.hashMerkleRoot = block.calc_merkle_root()
443    return (block, block_sig_key)
444
445
446def create_unsigned_mpos_block(node, staking_prevouts, nTime=None, block_fees=0):
447    mpos_block, block_sig_key = create_unsigned_pos_block(node, staking_prevouts, nTime)
448    tip = node.getblock(node.getbestblockhash())
449
450    # The block reward is constant for regtest
451    stake_per_participant = int(INITIAL_BLOCK_REWARD_POS*COIN+block_fees) // MPOS_PARTICIPANTS
452
453    for i in range(MPOS_PARTICIPANTS-1):
454        partipant_block = node.getblock(node.getblockhash(tip['height']-500-i))
455        participant_tx = node.decoderawtransaction(node.gettransaction(partipant_block['tx'][1])['hex'])
456        participant_pubkey = hex_str_to_bytes(participant_tx['vout'][1]['scriptPubKey']['asm'].split(' ')[0])
457        mpos_block.vtx[1].vout.append(CTxOut(stake_per_participant, CScript([OP_DUP, OP_HASH160, hash160(participant_pubkey), OP_EQUALVERIFY, OP_CHECKSIG])))
458
459    # the input value
460    txout = node.gettxout(hex(mpos_block.prevoutStake.hash)[2:], mpos_block.prevoutStake.n)
461
462    # Reward per output
463    main_staker_reward = (int(float(str(txout['value']))*COIN) + stake_per_participant)
464
465    mpos_block.vtx[1].vout[1].nValue = main_staker_reward // 2
466    mpos_block.vtx[1].vout[2].nValue = main_staker_reward // 2
467
468    stake_tx_signed_raw_hex = node.signrawtransactionwithwallet(bytes_to_hex_str(mpos_block.vtx[1].serialize()))['hex']
469    f = io.BytesIO(hex_str_to_bytes(stake_tx_signed_raw_hex))
470    stake_tx_signed = CTransaction()
471    stake_tx_signed.deserialize(f)
472    mpos_block.vtx[1] = stake_tx_signed
473    mpos_block.hashMerkleRoot = mpos_block.calc_merkle_root()
474    return mpos_block, block_sig_key
475
476# Generates 4490 - blockheight PoW blocks + 510 PoS blocks,
477# i.e. block height afterwards will be 5000 and we will have valid MPoS participants.
478def activate_mpos(node, use_cache=True):
479    if not node.getblockcount():
480        node.setmocktime(int(time.time()) - 1000000)
481    node.generatetoaddress(4990-COINBASE_MATURITY-node.getblockcount(), "qSrM9K6FMhZ29Vkp8Rdk8Jp66bbfpjFETq")
482    staking_prevouts = collect_prevouts(node, address="qSrM9K6FMhZ29Vkp8Rdk8Jp66bbfpjFETq")
483
484    for i in range(COINBASE_MATURITY+10):
485        time.sleep(0.05)
486        nTime = (node.getblock(node.getbestblockhash())['time']+45) & 0xfffffff0
487        node.setmocktime(nTime)
488        block, block_sig_key = create_unsigned_pos_block(node, staking_prevouts, nTime=nTime)
489        block.sign_block(block_sig_key)
490        block.rehash()
491        block_count = node.getblockcount()
492        assert_equal(node.submitblock(bytes_to_hex_str(block.serialize())), None)
493        assert_equal(node.getblockcount(), block_count+1)
494
495        # Remove the staking prevout so we don't accidently reuse it
496        for j in range(len(staking_prevouts)):
497            prevout = staking_prevouts[j]
498            if prevout[0].serialize() == block.prevoutStake.serialize():
499                staking_prevouts.pop(j)
500                break
501
502        if len(staking_prevouts) < 20:
503            staking_prevouts = collect_prevouts(node, address="qSrM9K6FMhZ29Vkp8Rdk8Jp66bbfpjFETq")
504
505
506def wif_to_ECKey(wif):
507    _, privkey, _ = base58_to_byte(wif, 38)
508    bytes_privkey = hex_str_to_bytes(str(privkey)[2:-1])
509    key = ECKey()
510    # Assume always compressed, ignore last byte which specifies compression
511    key.set(bytes_privkey[:-1], True)
512    return key
513
514def create_POD(delegator, delegator_address, staker_address):
515    hex_hash = p2pkh_to_hex_hash(staker_address)
516    b64_signature = delegator.signmessage(delegator_address, hex_hash)
517    bytes_signature = base64.b64decode(b64_signature)
518    return bytes_signature
519
520def assert_delegation_reverted_with_message(delegator, abi, sender, message, gas=2250000):
521    txid = delegator.sendtocontract(DELEGATION_CONTRACT_ADDRESS, abi, 0, gas, 0.00000040, sender)['txid']
522    delegator.generate(1)
523    receipt = delegator.gettransactionreceipt(txid)[0]
524    assert_equal(receipt['excepted'], 'Revert')
525    assert_equal(receipt['exceptedMessage'], message)
526    #print("[+] passed " + message)
527
528def assert_delegation_events_emitted(delegator, abi, sender, events=[], delegations={}, gas=2250000, expected_gas_consumed=0):
529    txid = delegator.sendtocontract(DELEGATION_CONTRACT_ADDRESS, abi, 0, gas, 0.00000040, sender)['txid']
530    delegator.generate(1)
531    receipt = delegator.gettransactionreceipt(txid)[0]
532
533    # Verify the fields of the log are as expected
534    for ret, expected in zip(receipt['log'], events):
535        for ret_indexed, expected_indexed in zip(ret['topics'], expected['topics']):
536            assert_equal(ret_indexed, expected_indexed)
537        assert_equal(ret['data'], expected['data'])
538
539    # Check the state of the delegation attribute
540    for delegate, delegate_data in delegations.items():
541        out = delegator.callcontract(DELEGATION_CONTRACT_ADDRESS, "bffe3486" + delegate.zfill(64))['executionResult']['output']
542        assert_equal(out[:64], delegate_data['staker'].zfill(64))
543        assert_equal(out[64:128], delegate_data['fee'].zfill(64))
544        assert_equal(out[128:192], delegate_data['blockHeight'].zfill(64))
545        assert_equal(out[192:], "80".zfill(64) + hex(65 if delegate_data['pod'] else 0)[2:].zfill(64) + delegate_data['pod'])
546
547    # Make sure we consume the minimum gas expected
548    assert(receipt['gasUsed'] > expected_gas_consumed)
549
550def get_delegate_abi(staker_address, fee, pod):
551    padded_hex_pod = bytes_to_hex_str(pod) + "00"*31
552    fee_hex = hex(fee)[2:]
553    staker_address_hex = p2pkh_to_hex_hash(staker_address)
554    abi = "4c0e968c"
555    abi += staker_address_hex.zfill(64)
556    abi += fee_hex.zfill(64)
557    abi += "60".zfill(64)
558    abi += hex(65)[2:].zfill(64)
559    abi += padded_hex_pod
560    return abi
561
562def delegate_to_staker(delegator, delegator_address, staker_address, fee, pod):
563    padded_hex_pod = bytes_to_hex_str(pod) + "00"*31
564    fee_hex = hex(fee)[2:]
565    expected_block_height = hex(delegator.getblockcount()+1)[2:]
566    staker_address_hex = p2pkh_to_hex_hash(staker_address)
567    delegator_address_hex = p2pkh_to_hex_hash(delegator_address)
568    abi = get_delegate_abi(staker_address, fee, pod)
569    assert_delegation_events_emitted(delegator, abi, delegator_address, events=[{
570        "topics": [
571            'a23803f3b2b56e71f2921c22b23c32ef596a439dbe03f7250e6b58a30eb910b5', # keccak256 of AddDelegation(...)
572            staker_address_hex.zfill(64), # staker
573            delegator_address_hex.zfill(64) # delegate
574        ],
575        # fee + block.number + offsetofpod + sizeofpod + pod
576        "data": fee_hex.zfill(64) + expected_block_height.zfill(64) + "60".zfill(64) + hex(65)[2:].zfill(64) + padded_hex_pod
577    }], delegations={
578        delegator_address_hex: {
579            "fee": fee_hex,
580            "staker": staker_address_hex,
581            "blockHeight": expected_block_height,
582            "pod": padded_hex_pod
583        }
584    }, expected_gas_consumed=2000000)
585
586
587def create_delegated_pos_block(staker, staker_eckey, staker_prevout, delegator_address_hex, pod, staking_fee_percentage, delegator_prevouts, nFees=0, nTime=None, use_pos_reward=False):
588    tmp = create_unsigned_pos_block(staker, delegator_prevouts, nTime=nTime)
589    if not tmp:
590        return None
591
592    block_subsidy = INITIAL_BLOCK_REWARD_POS if use_pos_reward else INITIAL_BLOCK_REWARD
593
594    block, k = tmp
595    # change the vin from the staker input to the delegator input
596    staker_nas_txout = staker.gettxout(hex(staker_prevout.hash)[2:].zfill(64), staker_prevout.n)
597    staker_nas_input_value = int(float(str(staker_nas_txout['value']))*COIN)
598
599    block.vtx[1].vin[0] = CTxIn(staker_prevout)
600    block.vtx[1].vout[1].scriptPubKey = CScript([staker_eckey.get_pubkey().get_bytes(), OP_CHECKSIG])
601    block.vtx[1].vout[1].nValue = int(((block_subsidy*COIN+nFees) * staking_fee_percentage) // 100)
602    block.vtx[1].vout[2].scriptPubKey = CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(delegator_address_hex), OP_EQUALVERIFY, OP_CHECKSIG])
603    block.vtx[1].vout[2].nValue = int(block_subsidy*COIN+nFees) - block.vtx[1].vout[1].nValue # subtract the staker's reward to get the delegator's reward (the delegator will ceil)
604    block.vtx[1].vout[1].nValue += staker_nas_input_value # add the input value for the staker
605    block.vtx[1] = rpc_sign_transaction(staker, block.vtx[1])
606    block.vtx[1].rehash()
607    block.hashMerkleRoot = block.calc_merkle_root()
608    block.rehash()
609    block.sign_block(staker_eckey, pod=pod)
610    block.vchBlockSig = block.vchBlockSig + pod
611    block.rehash()
612    return block
613
614
615