Skip to content

Commit

Permalink
Merge branch 'master' into evospork
Browse files Browse the repository at this point in the history
  • Loading branch information
a-bezrukov committed Dec 24, 2020
2 parents 717c368 + edee678 commit 6b8ab34
Show file tree
Hide file tree
Showing 26 changed files with 757 additions and 93 deletions.
3 changes: 3 additions & 0 deletions qa/pull-tester/rpc-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@

testScripts = [
'lelantus_mint.py',
'lelantus_setmintstatus_validation.py',
'lelantus_mintspend.py',
'lelantus_spend_gettransaction.py',
'elysium_create_denomination.py',
'elysium_property_creation_fee.py',
'elysium_sendmint.py',
Expand Down
138 changes: 138 additions & 0 deletions qa/rpc-tests/lelantus_mintspend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
from decimal import *

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *


class LelantusMintSpendTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 4
self.setup_clean_chain = False

def run_test(self):
# Decimal formating: 6 digits for balance will be enought 000.000
getcontext().prec = 6
self.nodes[0].generate(1001)
self.sync_all()

start_bal = self.nodes[0].getbalance()

mint_trans = list()
mint_trans.append(self.nodes[0].mintlelantus(1))
mint_trans.append(self.nodes[0].mintlelantus(2))

# Get last added transaction and fee for it
info = self.nodes[0].gettransaction(mint_trans[-1][0])

# fee in transaction is negative
fee = -(info['fee'] * 2)
cur_bal = self.nodes[0].getbalance()
start_bal = float(start_bal) - float(fee) - 3
start_bal = Decimal(format(start_bal, '.8f'))

assert start_bal == cur_bal, \
'Unexpected current balance: {}, should be minus two mints and two fee, ' \
'but start was {}'.format(cur_bal, start_bal)

# confirmations should be i due to less than 4 blocks was generated after transactions send
for i in range(5):
for tr in mint_trans:
info = self.nodes[0].gettransaction(tr[0])
confrms = info['confirmations']
assert confrms == i, \
'Confirmations should be {}, ' \
'due to {} blocks was generated after transaction was created,' \
'but was {}'.format(i, i, confrms)

tr_type = info['details'][0]['category']
assert tr_type == 'mint', 'Unexpected transaction type: {}'.format(tr_type)

res = False
args = {'THAYjKnnCsN5xspnEcb1Ztvw4mSPBuwxzU': 1}
try:
res = self.nodes[0].joinsplit(args)
except JSONRPCException as ex:
assert ex.error['message'] == 'Insufficient funds'

assert not res, 'Did not raise spend exception, but should be.'

self.nodes[0].generate(1)
self.sync_all()

# generate last confirmation block - now all transactions should be confimed
self.nodes[0].generate(1)
self.sync_all()

for tr in mint_trans:
info = self.nodes[0].gettransaction(tr[0])
confrms = info['confirmations']
assert confrms == 6, \
'Confirmations should be 6, ' \
'due to 6 blocks was generated after transaction was created,' \
'but was {}.'.format(confrms)
tr_type = info['details'][0]['category']
assert tr_type == 'mint', 'Unexpected transaction type'

spend_trans = list()
spend_total = Decimal(0)

self.sync_all()

start_bal = self.nodes[0].getbalance()
print(start_bal)
total_spend_fee = 0

myaddr = self.nodes[0].listreceivedbyaddress(0, True)[0]['address']
print(1)
args = {myaddr: 1}

spend_trans.append(self.nodes[0].joinsplit(args))

info = self.nodes[0].gettransaction(spend_trans[-1])
confrms = info['confirmations']
tr_type = info['details'][0]['category']
total_spend_fee += -info['fee']
print(info['fee'])
print(self.nodes[0].getbalance())
spend_total = float(spend_total) + 1
assert confrms == 0, \
'Confirmations should be 0, ' \
'due to 0 blocks was generated after transaction was created,' \
'but was {}.'.format(confrms)
assert tr_type == 'spend', 'Unexpected transaction type'
print(self.nodes[0].getbalance())

before_new = self.nodes[0].getbalance()
self.nodes[0].generate(2)
after_new = self.nodes[0].getbalance()
delta = after_new - before_new
self.sync_all()

# # Start balance increase on generated blocks to confirm
start_bal += delta
cur_bal = Decimal(format(self.nodes[0].getbalance(), '.1f'))
spend_total = Decimal(format(spend_total, '.8f'))

#TODO check why currently was not minused from total sum
start_bal = start_bal + spend_total

assert start_bal == cur_bal, \
'Unexpected current balance: {}, should increase on {}, ' \
'but start was {}'.format(cur_bal, spend_total, start_bal)

for tr in spend_trans:
info = self.nodes[0].gettransaction(tr)

confrms = info['confirmations']
tr_type = info['details'][0]['category']
assert confrms >= 1, \
'Confirmations should be 1 or more, ' \
'due to 1 blocks was generated after transaction was created,' \
'but was {}.'.format(confrms)
assert tr_type == 'spend', 'Unexpected transaction type'


if __name__ == '__main__':
LelantusMintSpendTest().main()
66 changes: 66 additions & 0 deletions qa/rpc-tests/lelantus_setmintstatus_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *

class SetLelantusMintSatusValidationWithFundsTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 4
self.setup_clean_chain = False

def setup_nodes(self):
# This test requires mocktime
enable_mocktime()
return start_nodes(self.num_nodes, self.options.tmpdir)

def run_test(self):
self.nodes[0].generate(1000)
self.sync_all()

txid = self.nodes[0].mintlelantus(10)

lelantus_mint = self.nodes[0].listlelantusmints()

assert len(lelantus_mint) == len(txid), 'Should be same number.'

mint_info = lelantus_mint[0]

assert not mint_info['isUsed'], \
'This mint with txid: {} should not be Used.'.format(txid)

print('Set mint status from False to True.')

self.nodes[0].setlelantusmintstatus(mint_info['serialNumber'], True)

lelantus_mint = self.nodes[0].listlelantusmints()

assert len(lelantus_mint) == len(txid), 'Should be same number.'

mint_info = lelantus_mint[0]

assert mint_info['isUsed'], \
'This mint with txid: {} should be Used.'.format(txid)

print('Set mint status from True to False back.')

self.nodes[0].setlelantusmintstatus(mint_info['serialNumber'], False)

lelantus_mint = self.nodes[0].listlelantusmints()

assert len(lelantus_mint) == len(txid), 'Should be same number.'

mint_info = lelantus_mint[0]

assert not mint_info['isUsed'], \
'This mint with txid: {} should not be Used.'.format(txid)


assert_raises(JSONRPCException, self.nodes[0].setlelantusmintstatus, [(mint_info['serialNumber'], "sometext")])
assert_raises(JSONRPCException, self.nodes[0].setlelantusmintstatus, [mint_info['serialNumber']])
assert_raises(JSONRPCException, self.nodes[0].setlelantusmintstatus, [])
assert_raises(JSONRPCException, self.nodes[0].setlelantusmintstatus, ["sometext"])
assert_raises(JSONRPCException, self.nodes[0].setlelantusmintstatus, [123])


if __name__ == '__main__':
SetLelantusMintSatusValidationWithFundsTest().main()
67 changes: 67 additions & 0 deletions qa/rpc-tests/lelantus_spend_gettransaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
from decimal import *

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *

class JoinSplitGettransactionTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 4
self.setup_clean_chain = True

def setup_nodes(self):
# This test requires mocktime
enable_mocktime()
return start_nodes(self.num_nodes, self.options.tmpdir)

def run_test(self):
self.nodes[0].generate(1001)
self.sync_all()

# get a watch only address
watchonly_address = self.nodes[3].getnewaddress()
watchonly_pubkey = self.nodes[3].validateaddress(watchonly_address)["pubkey"]
self.nodes[0].importpubkey(watchonly_pubkey, "", True)

valid_address = self.nodes[0].getnewaddress()

for _ in range(10):
self.nodes[0].mintlelantus(1)

self.nodes[0].generate(10)
self.sync_all()

# case 1: Spend many with watchonly address
spendto_wo_id = self.nodes[0].joinsplit({watchonly_address: 1})
spendto_wo_tx = self.nodes[0].gettransaction(spendto_wo_id)

assert spendto_wo_tx['amount'] == Decimal('-1')
assert spendto_wo_tx['fee'] < Decimal('0')
assert isinstance(spendto_wo_tx['details'], list)
assert len(spendto_wo_tx['details']) == 1
assert spendto_wo_tx['details'][0]['involvesWatchonly']

# case 2: Spend many with watchonly address and valid address
spendto_wo_and_valid_id = self.nodes[0].joinsplit({watchonly_address: 1, valid_address: 2})
spendto_wo_and_valid_tx = self.nodes[0].gettransaction(spendto_wo_and_valid_id)

assert spendto_wo_and_valid_tx['amount'] == Decimal('-1')
assert spendto_wo_and_valid_tx['fee'] < Decimal('0')
assert isinstance(spendto_wo_and_valid_tx['details'], list)
assert len(spendto_wo_and_valid_tx['details']) == 3

involves_watch_only_count = 0
for detial in spendto_wo_and_valid_tx['details']:
if 'involvesWatchonly' in detial and bool(detial['involvesWatchonly']):
involves_watch_only_count += 1

assert involves_watch_only_count == 1

# case 3: spend many with watchonly address and invalid address
assert_raises(JSONRPCException, self.nodes[0].joinsplit, [{watchonly_address: 1, 'invalidaddress': 2}])

if __name__ == '__main__':
JoinSplitGettransactionTest().main()


6 changes: 4 additions & 2 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ BITCOIN_TESTS = \
test/hash_tests.cpp \
test/key_tests.cpp \
test/dbwrapper_tests.cpp \
# test/lelantus_tests.cpp \
# test/lelantus_state_tests.cpp \
test/lelantus_tests.cpp \
test/lelantus_mintspend_test.cpp \
test/lelantus_state_tests.cpp \
test/sigma_lelantus_transition.cpp \
test/limitedmap_tests.cpp \
test/main_tests.cpp \
test/mbstring_tests.cpp \
Expand Down
24 changes: 19 additions & 5 deletions src/hdmint/tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,19 @@ void CHDMintTracker::SetPubcoinNotUsed(const uint256& hashPubcoin)
UpdateState(meta);
}

void CHDMintTracker::SetLelantusPubcoinNotUsed(const uint256& hashPubcoin)
{
CLelantusMintMeta meta;
if(!GetLelantusMetaFromPubcoin(hashPubcoin, meta))
return;
meta.isUsed = false;

if (mapPendingSpends.count(meta.hashSerial))
mapPendingSpends.erase(meta.hashSerial);

UpdateState(meta);
}


/**
* Check mempool for the spend associated with the mint serial hash passed
Expand Down Expand Up @@ -1209,20 +1222,21 @@ std::vector<CMintMeta> CHDMintTracker::ListMints(bool fUnusedOnly, bool fMatureO

std::vector<CLelantusMintMeta> CHDMintTracker::ListLelantusMints(bool fUnusedOnly, bool fMatureOnly, bool fUpdateStatus, bool fLoad, bool fWrongSeed)
{
std::vector<CLelantusMintMeta> vOverWrite;
std::set<uint256> setMempool = GetMempoolTxids();

std::vector<CLelantusMintMeta> setMints;
LOCK2(cs_main, pwalletMain->cs_wallet);
CWalletDB walletdb(strWalletFile);
if (fLoad) {
LOCK2(cs_main, pwalletMain->cs_wallet);
CWalletDB walletdb(strWalletFile);

std::list<CHDMint> listDeterministicDB = walletdb.ListHDMints(true);
for (auto& dMint : listDeterministicDB) {
AddLelantus(walletdb, dMint, false, false);
}
LogPrint("zero", "%s: added %d lelantus hdmint from DB\n", __func__, listDeterministicDB.size());
}

std::vector<CLelantusMintMeta> vOverWrite;
std::set<uint256> setMempool = GetMempoolTxids();

for (auto& it : mapLelantusSerialHashes) {
CLelantusMintMeta mint = it.second;

Expand Down
1 change: 0 additions & 1 deletion src/hdmint/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ void CHDMintWallet::SetWalletTransactionBlock(CWalletTx &wtx, const CBlockIndex
*/
void CHDMintWallet::SyncWithChain(bool fGenerateMintPool, boost::optional<std::list<std::pair<uint256, MintPoolEntry>>> listMints)
{
LOCK(pwalletMain->cs_wallet);
CWalletDB walletdb(strWalletFile);
bool found = true;

Expand Down
12 changes: 8 additions & 4 deletions src/lelantus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,11 @@ bool CheckLelantusJMintTransaction(
"CheckLelantusMintTransaction: double mint");
}

uint64_t amount;
if(!pwalletMain->DecryptMintAmount(encryptedValue, pubCoinValue, amount))
amount = 0;
uint64_t amount = 0;
if (pwalletMain) {
if (!pwalletMain->DecryptMintAmount(encryptedValue, pubCoinValue, amount))
amount = 0;
}
if (lelantusTxInfo != NULL && !lelantusTxInfo->fInfoIsComplete) {

// Update public coin list in the info
Expand Down Expand Up @@ -1017,7 +1019,9 @@ CLelantusState::CLelantusState(
:containers(surgeCondition),
maxCoinInGroup(maxCoinInGroup),
startGroupSize(startGroupSize)
{}
{
Reset();
}

void CLelantusState::AddMintsToStateAndBlockIndex(
CBlockIndex *index,
Expand Down
Loading

0 comments on commit 6b8ab34

Please sign in to comment.