Skip to content

Commit

Permalink
Don't count spent outputs in GetRemoteStakingBalance
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitry Saveliev <dima@thirdhash.com>
  • Loading branch information
dsaveliev committed Apr 16, 2019
1 parent 1cb0b13 commit 4ff26fc
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/esperanza/walletextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ CAmount WalletExtension::GetRemoteStakingBalance() const {

for (size_t i = 0; i < tx->tx->vout.size(); ++i) {
const CTxOut &txout = tx->tx->vout[i];
if (m_enclosing_wallet.IsSpent(hashTx, i)) {
continue;
if (m_enclosing_wallet.IsSpent(hashTx, i)) {
continue;
}
if (::IsStakedRemotely(m_enclosing_wallet, txout.scriptPubKey)) {
balance += txout.nValue;
Expand Down
94 changes: 83 additions & 11 deletions test/functional/feature_remote_staking.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,38 @@
# Copyright (c) 2019 The Unit-e Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.mininode import sha256
from test_framework.regtest_mnemonics import regtest_mnemonics
from test_framework.script import CScript, OP_2, hash160
from test_framework.test_framework import UnitETestFramework, STAKE_SPLIT_THRESHOLD
from test_framework.util import assert_equal, assert_greater_than, bytes_to_hex_str, hex_str_to_bytes, wait_until
from test_framework.blocktools import (
create_block,
create_coinbase,
get_tip_snapshot_meta,
sign_coinbase,
)
from test_framework.mininode import (
msg_witness_block,
network_thread_start,
P2PInterface,
sha256,
)
from test_framework.regtest_mnemonics import (
regtest_mnemonics,
)
from test_framework.script import (
CScript,
OP_2,
hash160,
)
from test_framework.test_framework import (
UnitETestFramework,
PROPOSER_REWARD,
STAKE_SPLIT_THRESHOLD,
)
from test_framework.util import (
assert_equal,
assert_greater_than,
bytes_to_hex_str,
hex_str_to_bytes,
wait_until,
)


def stake_p2wsh(node, staking_node, amount):
Expand All @@ -18,33 +45,68 @@ def stake_p2wsh(node, staking_node, amount):
staking_node: the node which will be able to stake nodes
amount: the amount to send
"""
multisig = node.addmultisigaddress(2, [node.getnewaddress(), node.getnewaddress()])
multisig = node.addmultisigaddress(
2, [node.getnewaddress(), node.getnewaddress()])
bare = CScript(hex_str_to_bytes(multisig['redeemScript']))
spending_script_hash = sha256(bare)

addr_info = staking_node.validateaddress(staking_node.getnewaddress('', 'legacy'))
addr_info = staking_node.validateaddress(
staking_node.getnewaddress('', 'legacy'))
staking_key_hash = hash160(hex_str_to_bytes(addr_info['pubkey']))

rs_p2wsh = CScript([OP_2, staking_key_hash, spending_script_hash])
outputs = [{'address': 'script', 'amount': amount, 'script': bytes_to_hex_str(rs_p2wsh)}]
outputs = [{'address': 'script', 'amount': amount,
'script': bytes_to_hex_str(rs_p2wsh)}]
node.sendtypeto('unite', 'unite', outputs)


def build_block_with_remote_stake(node):
height = node.getblockcount()
snapshot_meta = get_tip_snapshot_meta(node)
stakes = node.liststakeablecoins()

coin = stakes['stakeable_coins'][0]['coin']
pubkey = hex_str_to_bytes(coin['script_pub_key']['hex'])
stake = {
'txid': coin['out_point']['txid'],
'vout': coin['out_point']['n'],
'amount': coin['amount'],
}

tip = int(node.getbestblockhash(), 16)
block_time = node.getblock(
node.getbestblockhash())['time'] + 1
coinbase = sign_coinbase(
node, create_coinbase(
height, stake, snapshot_meta.hash, raw_pubkey=pubkey))

return create_block(tip, coinbase, block_time)


class RemoteStakingTest(UnitETestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
self.extra_args=[
self.extra_args = [
[],
['-minimumchainwork=0', '-maxtipage=1000000000']
]
self.customchainparams = [
{"stake_maturity": 1, "stake_maturity_activation_height": 2}] * 2

def run_test(self):
alice, bob = self.nodes
alice.importmasterkey(regtest_mnemonics[0]['mnemonics'])

bob.add_p2p_connection(P2PInterface())
network_thread_start()

self.log.info("Waiting untill the P2P connection is fully up...")
bob.p2p.wait_for_verack()

alice.generate(1)
assert_equal(len(alice.listunspent()), regtest_mnemonics[0]['balance'] / STAKE_SPLIT_THRESHOLD)
assert_equal(len(alice.listunspent()),
regtest_mnemonics[0]['balance'] / STAKE_SPLIT_THRESHOLD)

alices_addr = alice.getnewaddress()

Expand Down Expand Up @@ -73,8 +135,18 @@ def bob_is_staking_the_new_coin():
return ps['wallets'][0]['stakeable_balance'] == 2
wait_until(bob_is_staking_the_new_coin, timeout=10)

# Generate block with remote stake
block = build_block_with_remote_stake(bob)
bob.p2p.send_and_ping(msg_witness_block(block))
self.sync_all()

# Stake vout must be ignored in 'remote_staking_balance'
wi = alice.getwalletinfo()
assert_equal(wi['remote_staking_balance'], 2 + PROPOSER_REWARD)

# Change outputs for both staked coins, and the balance staked remotely
assert_equal(len(alice.listunspent()), 2 + (regtest_mnemonics[0]['balance'] // STAKE_SPLIT_THRESHOLD))
assert_equal(len(alice.listunspent()), 2 +
(regtest_mnemonics[0]['balance'] // STAKE_SPLIT_THRESHOLD))


if __name__ == '__main__':
Expand Down
4 changes: 3 additions & 1 deletion test/functional/test_framework/blocktools.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def serialize_script_num(value):
# If pubkey is passed in, the coinbase outputs will be P2PK outputs;
# otherwise anyone-can-spend outputs. The first output is the reward,
# which is not spendable for COINBASE_MATURITY blocks.
def create_coinbase(height, stake, snapshot_hash, pubkey = None, n_pieces = 1):
def create_coinbase(height, stake, snapshot_hash, pubkey = None, raw_pubkey = None, n_pieces = 1):
assert n_pieces > 0
stake_in = COutPoint(int(stake['txid'], 16), stake['vout'])
coinbase = CTransaction()
Expand All @@ -81,6 +81,8 @@ def create_coinbase(height, stake, snapshot_hash, pubkey = None, n_pieces = 1):
output_script = None
if (pubkey != None):
output_script = CScript([pubkey, OP_CHECKSIG])
elif (raw_pubkey != None):
output_script = CScript(raw_pubkey)
else:
output_script = CScript([OP_TRUE])

Expand Down

0 comments on commit 4ff26fc

Please sign in to comment.