From 75dd7c08f61eb5ab02692bbf321a2022473be09e Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 5 Feb 2020 16:35:38 +0530 Subject: [PATCH 01/67] Hard fork changes --- .gitignore | 1 + requirements.txt | 3 +- setup.cfg | 1 + src/qrl/cli.py | 175 +- src/qrl/core/AddressState.py | 40 + src/qrl/core/Block.py | 172 +- src/qrl/core/BlockHeader.py | 95 +- src/qrl/core/BlockMetadata.py | 20 + src/qrl/core/ChainManager.py | 849 ++- src/qrl/core/DifficultyTracker.py | 16 +- src/qrl/core/Indexer.py | 53 + src/qrl/core/LastTransactions.py | 63 + src/qrl/core/Miner.py | 247 +- src/qrl/core/MultiSigAddressState.py | 195 + src/qrl/core/OptimizedAddressState.py | 256 + src/qrl/core/PaginatedBitfield.py | 118 + src/qrl/core/PaginatedData.py | 154 + src/qrl/core/PoWValidator.py | 27 +- src/qrl/core/ProposalRecord.py | 75 + src/qrl/core/State.py | 693 +- src/qrl/core/StateContainer.py | 150 + src/qrl/core/StateMigration.py | 49 + src/qrl/core/TokenMetadata.py | 43 + src/qrl/core/TransactionInfo.py | 24 +- src/qrl/core/TransactionMetadata.py | 73 + src/qrl/core/TransactionPool.py | 4 +- src/qrl/core/VoteStats.py | 328 + src/qrl/core/config.py | 318 +- src/qrl/core/formulas.py | 30 +- src/qrl/core/messagereceipt.py | 9 +- src/qrl/core/miners/__init__.py | 0 src/qrl/core/miners/qrandomx/QRXMiner.py | 100 + .../core/miners/qrandomx/QRXPoWValidator.py | 23 + src/qrl/core/miners/qrandomx/__init__.py | 0 src/qrl/core/miners/qryptonight7/CNv1Miner.py | 84 + .../miners/qryptonight7/CNv1PoWValidator.py | 22 + src/qrl/core/miners/qryptonight7/__init__.py | 0 src/qrl/core/misc/db.py | 126 +- src/qrl/core/misc/helper.py | 17 +- src/qrl/core/misc/logger.py | 1 + src/qrl/core/misc/set_logger.py | 51 + src/qrl/core/node.py | 29 +- src/qrl/core/p2p/p2pTxManagement.py | 63 + src/qrl/core/p2p/p2pfactory.py | 16 + src/qrl/core/processors/TxnProcessor.py | 24 +- src/qrl/core/qrlnode.py | 370 +- src/qrl/core/txs/CoinBase.py | 75 +- src/qrl/core/txs/LatticeTransaction.py | 132 + src/qrl/core/txs/MessageTransaction.py | 92 +- src/qrl/core/txs/SlaveTransaction.py | 92 +- src/qrl/core/txs/TokenTransaction.py | 163 +- src/qrl/core/txs/Transaction.py | 127 +- src/qrl/core/txs/TransferTokenTransaction.py | 100 +- src/qrl/core/txs/TransferTransaction.py | 129 +- src/qrl/core/txs/__init__.py | 27 +- src/qrl/core/txs/multisig/MultiSigCreate.py | 185 + src/qrl/core/txs/multisig/MultiSigSpend.py | 242 + src/qrl/core/txs/multisig/MultiSigVote.py | 160 + src/qrl/core/txs/multisig/__init__.py | 0 src/qrl/crypto/QRandomX.py | 22 + src/qrl/crypto/Qryptonight.py | 23 +- src/qrl/crypto/Qryptonight7.py | 18 + src/qrl/daemon/walletd.py | 284 +- src/qrl/generated/qrl_pb2.py | 5663 +++++++++++++---- src/qrl/generated/qrl_pb2_grpc.py | 252 +- src/qrl/generated/qrllegacy_pb2.py | 89 +- src/qrl/generated/qrlmining_pb2.py | 25 +- src/qrl/generated/qrlwallet_pb2.py | 206 +- src/qrl/generated/qrlwallet_pb2_grpc.py | 18 +- src/qrl/grpcProxy.py | 2 + src/qrl/main.py | 39 +- src/qrl/protos/qrl.proto | 529 +- src/qrl/protos/qrllegacy.proto | 8 +- src/qrl/protos/qrlmining.proto | 1 + src/qrl/protos/qrlwallet.proto | 11 +- src/qrl/services/MiningAPIService.py | 4 + src/qrl/services/PublicAPIService.py | 176 +- src/qrl/services/WalletAPIService.py | 28 +- src/qrl/tools/generate_genesis.py | 14 +- tests/blockchain/MockedBlockchain.py | 17 +- tests/core/p2p/test_p2pTxManagement.py | 1 + tests/core/processors/test_TxnProcessor.py | 45 +- tests/core/test_AddressState.py | 48 +- tests/core/test_BlockMetadata.py | 50 + tests/core/test_ChainManager.py | 4513 ++++++++++++- tests/core/test_GenesisBlock.py | 1 + tests/core/test_LastTransactions.py | 106 + tests/core/test_Miner.py | 84 +- tests/core/test_MultiSigAddressState.py | 87 + tests/core/test_OptimizedAddressState.py | 175 + tests/core/test_PaginatedBitfield.py | 309 + tests/core/test_PaginatedData.py | 216 + tests/core/test_Qryptominer.py | 11 +- tests/core/test_State.py | 619 +- tests/core/test_State_Measurements.py | 62 +- tests/core/test_TokenMetadata.py | 101 + tests/core/test_TransactionMetadata.py | 115 + tests/core/test_TransactionPool.py | 25 +- tests/core/test_VoteStats.py | 920 +++ tests/core/test_block.py | 196 +- tests/core/test_blockheader.py | 73 +- tests/core/test_formulas.py | 7 +- tests/core/test_messagereceipt.py | 5 +- tests/core/test_node.py | 5 +- tests/core/test_qrlnode.py | 155 +- tests/core/txs/multisig/__init__.py | 0 .../core/txs/multisig/test_MultiSigCreate.py | 328 + tests/core/txs/multisig/test_MultiSigSpend.py | 329 + tests/core/txs/multisig/test_MultiSigVote.py | 394 ++ tests/core/txs/test_CoinBase.py | 108 +- tests/core/txs/test_MessageTransaction.py | 59 +- .../test_MessageTransactionStateChanges.py | 102 +- tests/core/txs/test_SimpleTransaction.py | 472 +- tests/core/txs/test_SlaveTransaction.py | 83 +- .../txs/test_SlaveTransactionStateChanges.py | 118 +- tests/core/txs/test_TokenTransaction.py | 197 +- .../txs/test_TokenTransactionStateChanges.py | 384 +- .../core/txs/test_TransactionValidateSlave.py | 62 +- .../core/txs/test_TransferTokenTransaction.py | 105 +- ...st_TransferTokenTransactionStateChanges.py | 311 +- tests/core/txs/testdata.py | 38 + tests/daemon/test_walletd.py | 333 +- tests/misc/MockHelper/mock_get_tx_metadata.py | 2 +- tests/misc/helper.py | 91 +- tests/services/test_MiningAPIService.py | 10 +- tests/services/test_PublicAPIService.py | 1037 +-- tests/services/test_WalletAPIService.py | 115 +- 127 files changed, 21635 insertions(+), 5132 deletions(-) create mode 100644 src/qrl/core/Indexer.py create mode 100644 src/qrl/core/MultiSigAddressState.py create mode 100644 src/qrl/core/OptimizedAddressState.py create mode 100644 src/qrl/core/PaginatedBitfield.py create mode 100644 src/qrl/core/PaginatedData.py create mode 100644 src/qrl/core/ProposalRecord.py create mode 100644 src/qrl/core/StateContainer.py create mode 100644 src/qrl/core/StateMigration.py create mode 100644 src/qrl/core/VoteStats.py create mode 100644 src/qrl/core/miners/__init__.py create mode 100644 src/qrl/core/miners/qrandomx/QRXMiner.py create mode 100644 src/qrl/core/miners/qrandomx/QRXPoWValidator.py create mode 100644 src/qrl/core/miners/qrandomx/__init__.py create mode 100644 src/qrl/core/miners/qryptonight7/CNv1Miner.py create mode 100644 src/qrl/core/miners/qryptonight7/CNv1PoWValidator.py create mode 100644 src/qrl/core/miners/qryptonight7/__init__.py create mode 100644 src/qrl/core/misc/set_logger.py create mode 100644 src/qrl/core/txs/LatticeTransaction.py create mode 100644 src/qrl/core/txs/multisig/MultiSigCreate.py create mode 100644 src/qrl/core/txs/multisig/MultiSigSpend.py create mode 100644 src/qrl/core/txs/multisig/MultiSigVote.py create mode 100644 src/qrl/core/txs/multisig/__init__.py create mode 100644 src/qrl/crypto/QRandomX.py create mode 100644 src/qrl/crypto/Qryptonight7.py create mode 100644 tests/core/test_BlockMetadata.py create mode 100644 tests/core/test_LastTransactions.py create mode 100644 tests/core/test_MultiSigAddressState.py create mode 100644 tests/core/test_OptimizedAddressState.py create mode 100644 tests/core/test_PaginatedBitfield.py create mode 100644 tests/core/test_PaginatedData.py create mode 100644 tests/core/test_TokenMetadata.py create mode 100644 tests/core/test_TransactionMetadata.py create mode 100644 tests/core/test_VoteStats.py create mode 100644 tests/core/txs/multisig/__init__.py create mode 100644 tests/core/txs/multisig/test_MultiSigCreate.py create mode 100644 tests/core/txs/multisig/test_MultiSigSpend.py create mode 100644 tests/core/txs/multisig/test_MultiSigVote.py diff --git a/.gitignore b/.gitignore index 93a5dd4b5..d83921082 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ __pycache__/* .DS_Store .*.swp */.ipynb_checkpoints/* +*_trial_temp # Project files .ropeproject diff --git a/requirements.txt b/requirements.txt index a26bf6ff6..0fe213021 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,8 +15,9 @@ six==1.11 click==6.7 pyqrllib>=0.99.3,<1.1.0 pyqryptonight>=0.99.3,<1.1.0 +pyqrandomx>=0.0.0,<1.0.0 Flask==0.12.3 json-rpc==1.10.8 cryptography==2.3 mock==2.0.0 -daemonize==2.4.7 +daemonize==2.4.7 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index b4a301775..b50bdb1fb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,6 +41,7 @@ install_requires = click==6.7 pyqrllib>=0.99.3,<1.1.0 pyqryptonight>=0.99.3,<1.1.0 + pyqrandomx>=0.0.0,<1.0.0 Flask==0.12.3 json-rpc==1.10.8 cryptography==2.3 diff --git a/src/qrl/cli.py b/src/qrl/cli.py index 3c1f92978..b1e875034 100755 --- a/src/qrl/cli.py +++ b/src/qrl/cli.py @@ -14,12 +14,15 @@ from qrl.core import config from qrl.core.Wallet import Wallet, WalletDecryptionError from qrl.core.misc.helper import parse_hexblob, parse_qaddress +from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.core.txs.SlaveTransaction import SlaveTransaction from qrl.core.txs.TokenTransaction import TokenTransaction from qrl.core.txs.Transaction import Transaction from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction from qrl.core.txs.TransferTransaction import TransferTransaction +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend from qrl.crypto.xmss import XMSS, hash_functions from qrl.generated import qrl_pb2_grpc, qrl_pb2 @@ -181,7 +184,7 @@ def _quanta_to_shor(x: Decimal, base=Decimal(config.dev.shor_per_quanta)) -> int return int(Decimal(x * base).to_integral_value()) -def _parse_dsts_amounts(addresses: str, amounts: str, token_decimals: int = 0): +def _parse_dsts_amounts(addresses: str, amounts: str, token_decimals: int = 0, check_multi_sig_address=False): """ 'Qaddr1 Qaddr2...' -> [\\xcx3\\xc2, \\xc2d\\xc3] '10 10' -> [10e9, 10e9] (in shor) @@ -189,7 +192,7 @@ def _parse_dsts_amounts(addresses: str, amounts: str, token_decimals: int = 0): :param amounts: :return: """ - addresses_split = [parse_qaddress(addr) for addr in addresses.split(' ')] + addresses_split = [parse_qaddress(addr, check_multi_sig_address) for addr in addresses.split(' ')] if token_decimals != 0: multiplier = Decimal(10 ** int(token_decimals)) @@ -471,11 +474,12 @@ def tx_push(ctx, txblob): @qrl.command() @click.option('--src', type=str, default='', prompt=True, help='signer QRL address') @click.option('--master', type=str, default='', prompt=True, help='master QRL address') +@click.option('--addr_to', type=str, default='', prompt=True, help='QRL Address receiving this message (optional)') @click.option('--message', type=str, prompt=True, help='Message (max 80 bytes)') @click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta') @click.option('--ots_key_index', default=1, prompt=True, help='OTS key Index (1..XMSS num signatures)') @click.pass_context -def tx_message(ctx, src, master, message, fee, ots_key_index): +def tx_message(ctx, src, master, addr_to, message, fee, ots_key_index): """ Message Transaction """ @@ -491,6 +495,7 @@ def tx_message(ctx, src, master, message, fee, ots_key_index): src_xmss.set_ots_index(ots_key_index) message = message.encode() + addr_to = parse_qaddress(addr_to, False) master_addr = None if master: @@ -503,6 +508,7 @@ def tx_message(ctx, src, master, message, fee, ots_key_index): try: stub = ctx.obj.get_stub_public_api() tx = MessageTransaction.create(message_hash=message, + addr_to=addr_to, fee=fee_shor, xmss_pk=address_src_pk, master_addr=master_addr) @@ -516,6 +522,159 @@ def tx_message(ctx, src, master, message, fee, ots_key_index): print("Error {}".format(str(e))) +@qrl.command() +@click.option('--src', type=str, default='', prompt=True, help='source QRL address') +@click.option('--master', type=str, default='', prompt=True, help='master QRL address') +@click.option('--threshold', default=0, prompt=True, help='Threshold') +@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta') +@click.option('--ots_key_index', default=1, prompt=True, help='OTS key Index (1..XMSS num signatures)') +@click.pass_context +def tx_multi_sig_create(ctx, src, master, threshold, fee, ots_key_index): + """ + Creates Multi Sig Create Transaction, that results into the formation of new multi_sig_address if accepted. + """ + signatories = [] + weights = [] + while True: + address = click.prompt('Address of Signatory ', default='') + if address == '': + break + weight = int(click.prompt('Weight ')) + signatories.append(parse_qaddress(address)) + weights.append(weight) + + try: + _, src_xmss = _select_wallet(ctx, src) + if not src_xmss: + click.echo("A local wallet is required to sign the transaction") + quit(1) + + address_src_pk = src_xmss.pk + + ots_key_index = validate_ots_index(ots_key_index, src_xmss) + src_xmss.set_ots_index(ots_key_index) + + master_addr = None + if master_addr: + master_addr = parse_qaddress(master) + # FIXME: This could be problematic. Check + fee_shor = _quanta_to_shor(fee) + + except KeyboardInterrupt: + click.echo("Terminated by user") + quit(1) + except Exception as e: + click.echo("Error validating arguments: {}".format(e)) + quit(1) + + try: + stub = ctx.obj.get_stub_public_api() + tx = MultiSigCreate.create(signatories=signatories, + weights=weights, + threshold=threshold, + fee=fee_shor, + xmss_pk=address_src_pk, + master_addr=master_addr) + + tx.sign(src_xmss) + + push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata) + push_transaction_resp = stub.PushTransaction(push_transaction_req, timeout=CONNECTION_TIMEOUT) + + print(push_transaction_resp.error_code) + print('Multi sig Address Q{}'.format(bin2hstr(MultiSigAddressState.generate_multi_sig_address(tx.txhash)))) + except Exception as e: + print("Error {}".format(str(e))) + + +@qrl.command() +@click.option('--src', type=str, default='', prompt=True, help='signer QRL address') +@click.option('--master', type=str, default='', help='master QRL address') +@click.option('--multi_sig_address', type=str, default='', prompt=True, help='signer Multi Sig Address') +@click.option('--dsts', type=str, prompt=True, help='List of destination addresses') +@click.option('--amounts', type=str, prompt=True, help='List of amounts to transfer (Quanta)') +@click.option('--expiry_block_number', type=int, prompt=True, help='Expiry Blocknumber') +@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta') +@click.option('--ots_key_index', default=1, help='OTS key Index (1..XMSS num signatures)') +@click.pass_context +def tx_multi_sig_spend(ctx, src, master, multi_sig_address, dsts, amounts, expiry_block_number, fee, ots_key_index): + """ + Transfer coins from src to dsts + """ + address_src_pk = None + master_addr = None + + addresses_dst = [] + shor_amounts = [] + fee_shor = [] + + signing_object = None + + try: + # Retrieve signing object + selected_wallet = _select_wallet(ctx, src) + if selected_wallet is None or len(selected_wallet) != 2: + click.echo("A wallet was not found") + quit(1) + + _, src_xmss = selected_wallet + + if not src_xmss: + click.echo("A local wallet is required to sign the transaction") + quit(1) + + address_src_pk = src_xmss.pk + + ots_key_index = validate_ots_index(ots_key_index, src_xmss) + src_xmss.set_ots_index(ots_key_index) + + signing_object = src_xmss + + # Get and validate other inputs + if master: + master_addr = parse_qaddress(master) + + addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts, check_multi_sig_address=True) + fee_shor = _quanta_to_shor(fee) + except Exception as e: + click.echo("Error validating arguments: {}".format(e)) + quit(1) + multi_sig_address = bytes(hstr2bin(multi_sig_address[1:])) + try: + # MultiSigSpend transaction + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=addresses_dst, + amounts=shor_amounts, + expiry_block_number=expiry_block_number, + fee=fee_shor, + xmss_pk=address_src_pk, + master_addr=master_addr) + + # Sign transaction + tx.sign(signing_object) + + if not tx.validate(): + print("It was not possible to validate the signature") + quit(1) + + print("\nTransaction Blob (signed): \n") + txblob = tx.pbdata.SerializeToString() + txblobhex = hexlify(txblob).decode() + print(txblobhex) + + # Push transaction + print() + print("Sending to a QRL Node...") + stub = ctx.obj.get_stub_public_api() + push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata) + push_transaction_resp = stub.PushTransaction(push_transaction_req, timeout=CONNECTION_TIMEOUT) + + # Print result + print(push_transaction_resp) + except Exception as e: + print("Error {}".format(str(e))) + + def base64tohex(data): return hexlify(a2b_base64(data)) @@ -534,10 +693,11 @@ def tx_unbase64(tx_json_str): @click.option('--master', type=str, default='', help='master QRL address') @click.option('--dsts', type=str, prompt=True, help='List of destination addresses') @click.option('--amounts', type=str, prompt=True, help='List of amounts to transfer (Quanta)') +@click.option('--message_data', type=str, prompt=True, help='Message (Optional)') @click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta') @click.option('--ots_key_index', default=1, help='OTS key Index (1..XMSS num signatures)') @click.pass_context -def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index): +def tx_transfer(ctx, src, master, dsts, amounts, message_data, fee, ots_key_index): """ Transfer coins from src to dsts """ @@ -549,6 +709,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index): fee_shor = [] signing_object = None + message_data = message_data.encode() try: # Retrieve signing object @@ -573,8 +734,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index): # Get and validate other inputs if master: master_addr = parse_qaddress(master) - - addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts) + addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts, check_multi_sig_address=True) fee_shor = _quanta_to_shor(fee) except Exception as e: click.echo("Error validating arguments: {}".format(e)) @@ -584,6 +744,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index): # Create transaction tx = TransferTransaction.create(addrs_to=addresses_dst, amounts=shor_amounts, + message_data=message_data, fee=fee_shor, xmss_pk=address_src_pk, master_addr=master_addr) @@ -605,7 +766,6 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index): print(txblobhex) # Push transaction - print() print("Sending to a QRL Node...") stub = ctx.obj.get_stub_public_api() push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata) @@ -877,3 +1037,4 @@ def main(): if __name__ == '__main__': main() + diff --git a/src/qrl/core/AddressState.py b/src/qrl/core/AddressState.py index 9cc01e38a..dad7e3c76 100644 --- a/src/qrl/core/AddressState.py +++ b/src/qrl/core/AddressState.py @@ -5,6 +5,7 @@ from pyqrllib.pyqrllib import QRLHelper, bin2hstr from qrl.core import config +from qrl.core.State import State from qrl.generated import qrl_pb2 @@ -234,3 +235,42 @@ def address_is_valid(address: bytes) -> bool: def serialize(self): return self._data.SerializeToString() + + @staticmethod + def put_addresses_state(state: State, addresses_state: dict, batch=None): + """ + :param addresses_state: + :param batch: + :return: + """ + for address in addresses_state: + address_state = addresses_state[address] + AddressState.put_address_state(state, address_state, batch) + + @staticmethod + def put_address_state(state: State, address_state, batch=None): + data = address_state.pbdata.SerializeToString() + state._db.put_raw(address_state.address, data, batch) + + @staticmethod + def get_address_state(state: State, address: bytes): + try: + data = state._db.get_raw(address) + pbdata = qrl_pb2.AddressState() + pbdata.ParseFromString(bytes(data)) + address_state = AddressState(pbdata) + return address_state + except KeyError: + return AddressState.get_default(address) + + @staticmethod + def return_all_addresses(state: State) -> list: + addresses = [] + for key, data in state._db.db: + if key[0] != b'Q': + continue + pbdata = qrl_pb2.AddressState() + pbdata.ParseFromString(bytes(data)) + address_state = AddressState(pbdata) + addresses.append(address_state) + return addresses diff --git a/src/qrl/core/Block.py b/src/qrl/core/Block.py index afe2ea740..10931b6e1 100644 --- a/src/qrl/core/Block.py +++ b/src/qrl/core/Block.py @@ -2,16 +2,20 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from collections import OrderedDict +from statistics import median +from typing import Optional from google.protobuf.json_format import MessageToJson, Parse from pyqrllib.pyqrllib import bin2hstr -from qrl.core import config +from qrl.core.config import DevConfig from qrl.core.misc import logger, ntp +from qrl.core.State import State from qrl.core.txs.Transaction import Transaction from qrl.core.txs.CoinBase import CoinBase from qrl.core.BlockHeader import BlockHeader from qrl.crypto.misc import merkle_tx_hash +from qrl.crypto.Qryptonight import Qryptonight from qrl.generated import qrl_pb2 @@ -46,10 +50,6 @@ def pbdata(self): def block_number(self): return self.blockheader.block_number - @property - def epoch(self): - return int(self.block_number // config.dev.blocks_per_epoch) - @property def headerhash(self): return self.blockheader.headerhash @@ -78,13 +78,11 @@ def fee_reward(self): def timestamp(self): return self.blockheader.timestamp - @property - def mining_blob(self) -> bytes: - return self.blockheader.mining_blob + def mining_blob(self, dev_config: DevConfig) -> bytes: + return self.blockheader.mining_blob(dev_config) - @property - def mining_nonce_offset(self) -> bytes: - return self.blockheader.nonce_offset + def mining_nonce_offset(self, dev_config: DevConfig) -> bytes: + return self.blockheader.nonce_offset(dev_config) @staticmethod def from_json(json_data): @@ -92,11 +90,11 @@ def from_json(json_data): Parse(json_data, pbdata) return Block(pbdata) - def verify_blob(self, blob: bytes) -> bool: - return self.blockheader.verify_blob(blob) + def verify_blob(self, blob: bytes, dev_config: DevConfig) -> bool: + return self.blockheader.verify_blob(blob, dev_config) - def set_nonces(self, mining_nonce, extra_nonce=0): - self.blockheader.set_nonces(mining_nonce, extra_nonce) + def set_nonces(self, dev_config: DevConfig, mining_nonce: int, extra_nonce: int = 0): + self.blockheader.set_nonces(dev_config, mining_nonce, extra_nonce) self._data.header.MergeFrom(self.blockheader.pbdata) def to_json(self) -> str: @@ -118,11 +116,14 @@ def _copy_tx_pbdata_into_block(block, tx): block._data.transactions.extend([tx.pbdata]) @staticmethod - def create(block_number: int, + def create(dev_config: DevConfig, + block_number: int, prev_headerhash: bytes, prev_timestamp: int, transactions: list, - miner_address: bytes): + miner_address: bytes, + seed_height: Optional[int], + seed_hash: Optional[bytes]): block = Block() @@ -134,8 +135,8 @@ def create(block_number: int, fee_reward += tx.fee # Prepare coinbase tx - total_reward_amount = BlockHeader.block_reward_calc(block_number) + fee_reward - coinbase_tx = CoinBase.create(total_reward_amount, miner_address, block_number) + total_reward_amount = BlockHeader.block_reward_calc(block_number, dev_config) + fee_reward + coinbase_tx = CoinBase.create(dev_config, total_reward_amount, miner_address, block_number) hashedtransactions.append(coinbase_tx.txhash) Block._copy_tx_pbdata_into_block(block, coinbase_tx) # copy memory rather than sym link @@ -145,21 +146,24 @@ def create(block_number: int, txs_hash = merkle_tx_hash(hashedtransactions) # FIXME: Find a better name, type changes - tmp_blockheader = BlockHeader.create(blocknumber=block_number, + tmp_blockheader = BlockHeader.create(dev_config=dev_config, + blocknumber=block_number, prev_headerhash=prev_headerhash, prev_timestamp=prev_timestamp, hashedtransactions=txs_hash, - fee_reward=fee_reward) + fee_reward=fee_reward, + seed_height=seed_height, + seed_hash=seed_hash) block.blockheader = tmp_blockheader block._data.header.MergeFrom(tmp_blockheader.pbdata) - block.set_nonces(0, 0) + block.set_nonces(dev_config, 0, 0) return block - def update_mining_address(self, mining_address: bytes): + def update_mining_address(self, dev_config: DevConfig, mining_address: bytes): coinbase_tx = Transaction.from_pbdata(self.transactions[0]) coinbase_tx.update_mining_address(mining_address) hashedtransactions = [] @@ -167,7 +171,7 @@ def update_mining_address(self, mining_address: bytes): for tx in self.transactions: hashedtransactions.append(tx.transaction_hash) - self.blockheader.update_merkle_root(merkle_tx_hash(hashedtransactions)) + self.blockheader.update_merkle_root(dev_config, merkle_tx_hash(hashedtransactions)) self._data.header.MergeFrom(self.blockheader.pbdata) @@ -177,6 +181,7 @@ def validate(self, chain_manager, future_blocks: OrderedDict) -> bool: return False parent_block = chain_manager.get_block(self.prev_headerhash) + dev_config = chain_manager.get_config_by_block_number(self.block_number) # If parent block not found in state, then check if its in the future block list if not parent_block: @@ -191,7 +196,7 @@ def validate(self, chain_manager, future_blocks: OrderedDict) -> bool: logger.warning('Failed to validate blocks parent child relation') return False - if not chain_manager.validate_mining_nonce(self.blockheader): + if not chain_manager.validate_mining_nonce(self.blockheader, dev_config): logger.warning('Failed PoW Validation') return False @@ -202,7 +207,7 @@ def validate(self, chain_manager, future_blocks: OrderedDict) -> bool: coinbase_txn = Transaction.from_pbdata(self.transactions[0]) coinbase_amount = coinbase_txn.amount - if not coinbase_txn.validate_extended(self.block_number): + if not coinbase_txn.validate_extended(self.block_number, dev_config): return False except Exception as e: @@ -220,61 +225,94 @@ def validate(self, chain_manager, future_blocks: OrderedDict) -> bool: for index in range(1, len(self.transactions)): fee_reward += self.transactions[index].fee - if not self.blockheader.validate(fee_reward, coinbase_amount, merkle_tx_hash(hashedtransactions)): - return False - - return True + qn = Qryptonight() + seed_block = chain_manager.get_block_by_number(qn.get_seed_height(self.block_number)) - def apply_state_changes(self, address_txn: dict) -> bool: - coinbase_tx = Transaction.from_pbdata(self.transactions[0]) + self.blockheader._seed_height = seed_block.block_number + self.blockheader._seed_hash = seed_block.headerhash - if not coinbase_tx.validate_extended(self.block_number): - logger.warning('Coinbase transaction failed') + if not self.blockheader.validate(fee_reward, + coinbase_amount, + merkle_tx_hash(hashedtransactions), + dev_config): return False - coinbase_tx.apply_state_changes(address_txn) + return True - len_transactions = len(self.transactions) - for tx_idx in range(1, len_transactions): - tx = Transaction.from_pbdata(self.transactions[tx_idx]) + def is_future_block(self, dev_config: DevConfig) -> bool: + if self.timestamp > ntp.getTime() + dev_config.block_max_drift: + return True - if isinstance(tx, CoinBase): - logger.warning('Found another coinbase transaction') - return False + return False - if not tx.validate(): - return False + def _validate_parent_child_relation(self, parent_block) -> bool: + return self.blockheader.validate_parent_child_relation(parent_block) - addr_from_pk_state = address_txn[tx.addr_from] - addr_from_pk = Transaction.get_slave(tx) - if addr_from_pk: - addr_from_pk_state = address_txn[addr_from_pk] + @staticmethod + def put_block(state: State, block, batch): + state._db.put_raw(block.headerhash, block.serialize(), batch) - if not tx.validate_extended(address_txn[tx.addr_from], addr_from_pk_state): - return False + @staticmethod + def get_block(state: State, header_hash: bytes): + try: + data = state._db.get_raw(header_hash) + return Block.deserialize(data) + except KeyError: + logger.debug('[get_block] Block header_hash %s not found', bin2hstr(header_hash).encode()) + except Exception as e: + logger.error('[get_block] %s', e) - expected_nonce = addr_from_pk_state.nonce + 1 + return None - if tx.nonce != expected_nonce: - logger.warning('nonce incorrect, invalid tx') - logger.warning('subtype: %s', tx.type) - logger.warning('%s actual: %s expected: %s', tx.addr_from, tx.nonce, expected_nonce) - return False + @staticmethod + def get_block_size_limit(state: State, block, dev_config: DevConfig): + # NOTE: Miner + block_size_list = [] + for _ in range(0, 10): + block = Block.get_block(state, block.prev_headerhash) + if not block: + return None + block_size_list.append(block.size) + if block.block_number == 0: + break + return max(dev_config.block_min_size_limit_in_bytes, dev_config.size_multiplier * median(block_size_list)) - if addr_from_pk_state.ots_key_reuse(tx.ots_key): - logger.warning('pubkey reuse detected: invalid tx %s', bin2hstr(tx.txhash)) - logger.warning('subtype: %s', tx.type) - return False + @staticmethod + def remove_blocknumber_mapping(state: State, block_number, batch): + state._db.delete(str(block_number).encode(), batch) - tx.apply_state_changes(address_txn) + @staticmethod + def put_block_number_mapping(state: State, block_number: int, block_number_mapping, batch): + state._db.put_raw(str(block_number).encode(), MessageToJson(block_number_mapping, sort_keys=True).encode(), batch) - return True + @staticmethod + def get_block_number_mapping(state: State, block_number: int): + try: + data = state._db.get_raw(str(block_number).encode()) + block_number_mapping = qrl_pb2.BlockNumberMapping() + return Parse(data, block_number_mapping) + except KeyError: + logger.debug('[get_block_number_mapping] Block #%s not found', block_number) + except Exception as e: + logger.error('[get_block_number_mapping] %s', e) - def is_future_block(self) -> bool: - if self.timestamp > ntp.getTime() + config.dev.block_max_drift: - return True + return None - return False + @staticmethod + def get_block_by_number(state: State, block_number: int): + block_number_mapping = Block.get_block_number_mapping(state, block_number) + if not block_number_mapping: + return None + return Block.get_block(state, block_number_mapping.headerhash) - def _validate_parent_child_relation(self, parent_block) -> bool: - return self.blockheader.validate_parent_child_relation(parent_block) + @staticmethod + def get_block_header_hash_by_number(state: State, block_number: int): + block_number_mapping = Block.get_block_number_mapping(state, block_number) + if not block_number_mapping: + return None + return block_number_mapping.headerhash + + @staticmethod + def last_block(state: State): + block_number = state.get_mainchain_height() + return Block.get_block_by_number(state, block_number) diff --git a/src/qrl/core/BlockHeader.py b/src/qrl/core/BlockHeader.py index b517d3072..5b4907965 100644 --- a/src/qrl/core/BlockHeader.py +++ b/src/qrl/core/BlockHeader.py @@ -4,7 +4,7 @@ from google.protobuf.json_format import MessageToJson, Parse from pyqrllib.pyqrllib import shake128, bin2hstr -from qrl.core import config +from qrl.core.config import DevConfig, user as user_config from qrl.core.formulas import block_reward from qrl.core.misc import ntp, logger from qrl.crypto.Qryptonight import Qryptonight @@ -17,6 +17,8 @@ def __init__(self, protobuf_blockheader=None): >>> BlockHeader() is not None True """ + self._seed_hash = None + self._seed_height = None self._data = protobuf_blockheader if protobuf_blockheader is None: self._data = qrl_pb2.BlockHeader() @@ -34,10 +36,6 @@ def pbdata(self): def block_number(self): return self._data.block_number - @property - def epoch(self): - return self._data.block_number // config.dev.blocks_per_epoch - @property def timestamp(self): return self._data.timestamp_seconds @@ -70,16 +68,13 @@ def extra_nonce(self): def mining_nonce(self): return self._data.mining_nonce - @property - def nonce_offset(self): - return config.dev.mining_nonce_offset + def nonce_offset(self, dev_config: DevConfig): + return dev_config.mining_nonce_offset - @property - def extra_nonce_offset(self): - return config.dev.extra_nonce_offset + def extra_nonce_offset(self, dev_config: DevConfig): + return dev_config.extra_nonce_offset - @property - def mining_blob(self) -> bytes: + def mining_blob(self, dev_config: DevConfig) -> bytes: blob = self.block_number.to_bytes(8, byteorder='big', signed=False) \ + self.timestamp.to_bytes(8, byteorder='big', signed=False) \ + self.prev_headerhash \ @@ -88,12 +83,13 @@ def mining_blob(self) -> bytes: + self.tx_merkle_root # reduce mining blob: 1 byte zero + 4 bytes nonce + 8 bytes extra_nonce by pool + 5 bytes for pool (17 bytes) - blob = bytes(shake128(config.dev.mining_blob_size - 18, blob)) + blob = bytes(shake128(dev_config.mining_blob_size_in_bytes - 18, blob)) zero = 0 blob = zero.to_bytes(1, byteorder='big', signed=False) + blob - if len(blob) < self.nonce_offset: + nonce_offset = self.nonce_offset(dev_config) + if len(blob) < nonce_offset: raise Exception("Mining blob size below 56 bytes") # Now insert mining nonce and extra nonce in offset 56 for compatibility @@ -102,26 +98,32 @@ def mining_blob(self) -> bytes: self.extra_nonce.to_bytes(8, byteorder='big', signed=False) + \ zero.to_bytes(5, byteorder='big', signed=False) - blob = blob[:self.nonce_offset] + mining_nonce_bytes + blob[self.nonce_offset:] + blob = blob[:nonce_offset] + mining_nonce_bytes + blob[nonce_offset:] return bytes(blob) @staticmethod @functools.lru_cache(maxsize=5) - def _get_qryptonight_hash(blob): + def _get_qryptonight_hash(block_number, seed_height, seed_hash, blob): qn = Qryptonight() - qnhash = bytes(qn.hash(blob)) + qnhash = bytes(qn.hash(block_number, seed_height, seed_hash, blob)) return qnhash - def generate_headerhash(self): - return self._get_qryptonight_hash(self.mining_blob) + def generate_headerhash(self, dev_config: DevConfig): + return self._get_qryptonight_hash(self.block_number, + self._seed_height, + self._seed_hash, + self.mining_blob(dev_config)) @staticmethod - def create(blocknumber: int, + def create(dev_config: DevConfig, + blocknumber: int, prev_headerhash: bytes, prev_timestamp: int, hashedtransactions: bytes, - fee_reward: int): + fee_reward: int, + seed_height: int, + seed_hash: bytes): bh = BlockHeader() bh._data.block_number = blocknumber @@ -141,62 +143,67 @@ def create(blocknumber: int, bh._data.merkle_root = hashedtransactions bh._data.reward_fee = fee_reward - bh._data.reward_block = bh.block_reward_calc(blocknumber) + bh._data.reward_block = bh.block_reward_calc(blocknumber, dev_config) - bh.set_nonces(0, 0) + bh._seed_hash = seed_hash + bh._seed_height = seed_height + bh.set_nonces(dev_config, 0, 0) return bh - def update_merkle_root(self, hashedtransactions: bytes): + def update_merkle_root(self, dev_config: DevConfig, hashedtransactions: bytes): self._data.merkle_root = hashedtransactions - self.set_nonces(0, 0) + self.set_nonces(dev_config, 0, 0) - def set_nonces(self, mining_nonce, extra_nonce=0): + def set_nonces(self, dev_config: DevConfig, mining_nonce, extra_nonce=0): self._data.mining_nonce = mining_nonce self._data.extra_nonce = extra_nonce - self._data.hash_header = self.generate_headerhash() + self._data.hash_header = self.generate_headerhash(dev_config) + + def set_mining_nonce_from_blob(self, blob, dev_config: DevConfig): + nonce_offset = self.nonce_offset(dev_config) + extra_nonce_offset = self.extra_nonce_offset(dev_config) - def set_mining_nonce_from_blob(self, blob): - mining_nonce_bytes = blob[self.nonce_offset: self.nonce_offset + 4] + mining_nonce_bytes = blob[nonce_offset: nonce_offset + 4] mining_nonce = int.from_bytes(mining_nonce_bytes, byteorder='big', signed=False) - extra_nonce_bytes = blob[self.extra_nonce_offset: self.extra_nonce_offset + 8] + extra_nonce_bytes = blob[extra_nonce_offset: extra_nonce_offset + 8] extra_nonce = int.from_bytes(extra_nonce_bytes, byteorder='big', signed=False) - self.set_nonces(mining_nonce, extra_nonce) + self.set_nonces(dev_config, mining_nonce, extra_nonce) @staticmethod - def block_reward_calc(block_number): + def block_reward_calc(block_number, dev_config: DevConfig): """ return block reward for the block_n :return: """ if block_number == 0: - return config.dev.supplied_coins - return int(block_reward(block_number)) + return dev_config.supplied_coins + return int(block_reward(block_number, dev_config)) - def validate(self, fee_reward, coinbase_amount, tx_merkle_root): + def validate(self, fee_reward, coinbase_amount, tx_merkle_root, dev_config: DevConfig): current_time = ntp.getTime() - allowed_timestamp = current_time + config.dev.block_lead_timestamp + allowed_timestamp = current_time + dev_config.block_lead_timestamp if self.timestamp > allowed_timestamp: logger.warning('BLOCK timestamp is more than the allowed block lead timestamp') logger.warning('Block timestamp %s ', self.timestamp) logger.warning('threshold timestamp %s', allowed_timestamp) return False - if self.timestamp < config.user.genesis_timestamp: + if self.timestamp < user_config.genesis_timestamp: logger.warning('Timestamp lower than genesis timestamp') - logger.warning('Genesis Timestamp %s', config.user.genesis_timestamp) + logger.warning('Genesis Timestamp %s', user_config.genesis_timestamp) logger.warning('Block Timestamp %s', self.timestamp) return False - generated_hash = self.generate_headerhash() + generated_hash = self.generate_headerhash(dev_config) if generated_hash != self.headerhash: logger.warning('received: {}'.format(bin2hstr(self.headerhash))) logger.warning('calculated: {}'.format(bin2hstr(generated_hash))) logger.warning('Headerhash false for block: failed validation') return False - if self.block_reward != self.block_reward_calc(self.block_number): + if self.block_reward != self.block_reward_calc(self.block_number, dev_config): logger.warning('Block reward incorrect for block: failed validation') return False @@ -241,11 +248,11 @@ def from_json(json_data): Parse(json_data, pbdata) return BlockHeader(pbdata) - def verify_blob(self, blob: bytes) -> bool: - mining_nonce_offset = config.dev.mining_nonce_offset + def verify_blob(self, blob: bytes, dev_config: DevConfig) -> bool: + mining_nonce_offset = dev_config.mining_nonce_offset blob = blob[:mining_nonce_offset] + blob[mining_nonce_offset + 17:] - actual_blob = self.mining_blob + actual_blob = self.mining_blob(dev_config) actual_blob = actual_blob[:mining_nonce_offset] + actual_blob[mining_nonce_offset + 17:] if blob != actual_blob: diff --git a/src/qrl/core/BlockMetadata.py b/src/qrl/core/BlockMetadata.py index 138af06e6..80b85e439 100644 --- a/src/qrl/core/BlockMetadata.py +++ b/src/qrl/core/BlockMetadata.py @@ -3,7 +3,10 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from google.protobuf.json_format import MessageToJson, Parse +from pyqrllib.pyqrllib import bin2hstr from qrl.core import config +from qrl.core.misc import logger +from qrl.core.State import State from qrl.generated import qrl_pb2 @@ -102,3 +105,20 @@ def deserialize(data): pbdata = qrl_pb2.BlockMetaData() pbdata.ParseFromString(bytes(data)) return BlockMetadata(pbdata) + + @staticmethod + def put_block_metadata(state: State, headerhash: bytes, block_metadata, batch): + state._db.put_raw(b'metadata_' + headerhash, block_metadata.serialize(), batch) + + @staticmethod + def get_block_metadata(state: State, header_hash: bytes): + try: + data = state._db.get_raw(b'metadata_' + header_hash) + return BlockMetadata.deserialize(data) + except KeyError: + logger.debug('[get_block_metadata] Block header_hash %s not found', + b'metadata_' + bin2hstr(header_hash).encode()) + except Exception as e: + logger.error('[get_block_metadata] %s', e) + + return None diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 74f63a875..e1215bdf8 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -3,19 +3,36 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import threading from typing import Optional, Tuple +from math import ceil +import functools from pyqrllib.pyqrllib import bin2hstr from pyqryptonight.pyqryptonight import StringToUInt256, UInt256ToString from qrl.core import config, BlockHeader +from qrl.core.config import DevConfig +from qrl.core.StateContainer import StateContainer +from qrl.core.StateMigration import StateMigration from qrl.core.AddressState import AddressState +from qrl.core.VoteStats import VoteStats +from qrl.core.LastTransactions import LastTransactions +from qrl.core.TransactionMetadata import TransactionMetadata +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.PaginatedData import PaginatedData +from qrl.core.PaginatedBitfield import PaginatedBitfield +from qrl.core.Indexer import Indexer from qrl.core.Block import Block from qrl.core.BlockMetadata import BlockMetadata from qrl.core.DifficultyTracker import DifficultyTracker from qrl.core.GenesisBlock import GenesisBlock +from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.PoWValidator import PoWValidator from qrl.core.txs.Transaction import Transaction from qrl.core.txs.CoinBase import CoinBase +from qrl.core.txs.LatticeTransaction import LatticeTransaction +from qrl.core.txs.SlaveTransaction import SlaveTransaction +from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote from qrl.core.TransactionPool import TransactionPool from qrl.core.misc import logger from qrl.crypto.Qryptonight import Qryptonight @@ -32,6 +49,11 @@ def __init__(self, state): self.trigger_miner = False self.lock = threading.RLock() + @property + def re_org_limit(self): + with self.lock: + return self._state.get_re_org_limit() + @property def height(self): with self.lock: @@ -49,30 +71,28 @@ def total_coin_supply(self): with self.lock: return self._state.total_coin_supply - def get_block_datapoint(self, headerhash): - with self.lock: - return self._state.get_block_datapoint(headerhash) - def get_cumulative_difficulty(self): with self.lock: - last_block_metadata = self._state.get_block_metadata(self._last_block.headerhash) + last_block_metadata = BlockMetadata.get_block_metadata(self._state, + self._last_block.headerhash) return last_block_metadata.cumulative_difficulty def get_block_by_number(self, block_number) -> Optional[Block]: with self.lock: - return self._state.get_block_by_number(block_number) + return Block.get_block_by_number(self._state, block_number) def get_block_header_hash_by_number(self, block_number) -> Optional[bytes]: with self.lock: - return self._state.get_block_header_hash_by_number(block_number) + return Block.get_block_header_hash_by_number(self._state, + block_number) def get_block(self, header_hash: bytes) -> Optional[Block]: with self.lock: - return self._state.get_block(header_hash) + return Block.get_block(self._state, header_hash) def get_address_balance(self, address: bytes) -> int: with self.lock: - return self._state.get_address_balance(address) + return self.get_optimized_address_state(address).balance def get_address_is_used(self, address: bytes) -> bool: with self.lock: @@ -80,19 +100,98 @@ def get_address_is_used(self, address: bytes) -> bool: def get_address_state(self, address: bytes) -> AddressState: with self.lock: - return self._state.get_address_state(address) + return AddressState.get_address_state(self._state, address) + + def get_optimized_address_state(self, address: bytes) -> OptimizedAddressState: + with self.lock: + return OptimizedAddressState.get_optimized_address_state(self._state, address) + + def get_multi_sig_address_state(self, address: bytes) -> MultiSigAddressState: + with self.lock: + return MultiSigAddressState.get_multi_sig_address_state_by_address(self._state._db, address) + + def get_bitfield(self, address: bytes, page: int): + with self.lock: + p = PaginatedBitfield(False, self._state._db) + return p.get_paginated_data(address, page) + + def is_slave(self, master_address: bytes, slave_pk: bytes) -> bool: + with self.lock: + return self._state.get_slave_pk_access_type(master_address, slave_pk) == 0 + + def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.SlaveMetadata: + with self.lock: + return self._state.get_slave_pk_access_type(address, slave_pk) + + def get_transaction_hashes(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_tx_hash', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) - def get_all_address_state(self): + def get_multi_sig_spend_txn_hashes(self, multi_sig_address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_multi_sig_spend', False, self._state._db) with self.lock: - return self._state.get_all_address_state() + return p.get_paginated_data(multi_sig_address, item_index) + + def get_token_transaction_hashes(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_token', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) + + def get_slave_transaction_hashes(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_slave', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) + + def get_lattice_pks_transaction_hashes(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_lattice_pk', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) + + def get_multi_sig_addresses(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_multisig_address', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) + + def get_vote_stats(self, multi_sig_spend_txn_hash: bytes): + with self.lock: + return VoteStats.get_state(state=self._state, shared_key=multi_sig_spend_txn_hash) + + def get_token(self, address: bytes, token_txhash: bytes) -> list: + with self.lock: + return self._state.get_token(address, token_txhash) + + def validate_all(self, tx: Transaction, check_nonce: bool) -> bool: + with self.lock: + addresses_set = set() + tx.set_affected_address(addresses_set) + state_container = self.new_state_container(addresses_set, self.height, True, None) + if state_container is None: + return False + if not self.update_state_container(tx, state_container): + return False + return tx.validate_all(state_container, check_nonce) + + def validate_tx(self, + tx: Transaction, + addresses_state: dict, + addresses_bitfield: dict, + tokens: dict, + slaves: dict) -> bool: + with self.lock: + return self._state.validate_tx(tx, addresses_state, addresses_bitfield, tokens, slaves) + + def apply_txn(self, tx: Transaction, state_container: StateContainer) -> bool: + with self.lock: + return tx.apply(self._state, state_container) def get_tx_metadata(self, transaction_hash) -> list: with self.lock: - return self._state.get_tx_metadata(transaction_hash) + return TransactionMetadata.get_tx_metadata(self._state, transaction_hash) def get_last_transactions(self): with self.lock: - return self._state.get_last_txs() + return LastTransactions.get_last_txs(self._state) def get_unconfirmed_transaction(self, transaction_hash) -> list: with self.lock: @@ -110,7 +209,7 @@ def get_unconfirmed_transaction(self, transaction_hash) -> list: def get_block_metadata(self, header_hash: bytes) -> Optional[BlockMetadata]: with self.lock: - return self._state.get_block_metadata(header_hash) + return BlockMetadata.get_block_metadata(self._state, header_hash) def get_blockheader_and_metadata(self, block_number=0) -> Tuple: with self.lock: @@ -135,27 +234,38 @@ def get_block_to_mine(self, miner, wallet_address) -> list: last_block, last_block_metadata.block_difficulty) - def get_measurement(self, block_timestamp, parent_headerhash, parent_metadata: BlockMetadata): + def get_block_size_limit(self, block: Block, dev_config: DevConfig): with self.lock: - return self._state.get_measurement(block_timestamp, parent_headerhash, parent_metadata) + return Block.get_block_size_limit(self._state, block, dev_config) - def get_block_size_limit(self, block: Block): + def get_block_is_duplicate(self, block: Block) -> bool: with self.lock: - return self._state.get_block_size_limit(block) + return block.get_block(self._state, block.headerhash) is not None + + def get_config_by_block_number(self, block_number: int) -> config.DevConfig: + dev_config = config.dev + if block_number == 0: + return dev_config - def get_block_is_duplicate(self, block: Block) -> bool: with self.lock: - return self._state.get_block(block.headerhash) is not None + while dev_config.activation_block_number >= block_number: + dev_config_pb_data = self._state.get_dev_config_state(dev_config.prev_state_key) + dev_config = config.DevConfig(dev_config_pb_data, True, True) + return dev_config - def validate_mining_nonce(self, blockheader: BlockHeader, enable_logging=True): + def validate_mining_nonce(self, blockheader: BlockHeader, dev_config: config.DevConfig, enable_logging=True): with self.lock: - parent_metadata = self.get_block_metadata(blockheader.prev_headerhash) - parent_block = self._state.get_block(blockheader.prev_headerhash) + parent_metadata = BlockMetadata.get_block_metadata(self._state, blockheader.prev_headerhash) + parent_block = Block.get_block(self._state, blockheader.prev_headerhash) - measurement = self.get_measurement(blockheader.timestamp, blockheader.prev_headerhash, parent_metadata) + measurement = self.get_measurement(dev_config, + blockheader.timestamp, + blockheader.prev_headerhash, + parent_metadata) diff, target = DifficultyTracker.get( measurement=measurement, - parent_difficulty=parent_metadata.block_difficulty) + parent_difficulty=parent_metadata.block_difficulty, + dev_config=dev_config) if enable_logging: logger.debug('-----------------START--------------------') @@ -167,11 +277,20 @@ def validate_mining_nonce(self, blockheader: BlockHeader, enable_logging=True): logger.debug('target %s', bin2hstr(target)) logger.debug('-------------------END--------------------') - if not PoWValidator().verify_input(blockheader.mining_blob, target): + qn = Qryptonight() + seed_block = self.get_block_by_number(qn.get_seed_height(blockheader.block_number)) + + if not PoWValidator().verify_input(blockheader.block_number, + seed_block.block_number, + seed_block.headerhash, + blockheader.mining_blob(dev_config), + target): if enable_logging: logger.warning("PoW verification failed") - qn = Qryptonight() - tmp_hash = qn.hash(blockheader.mining_blob) + tmp_hash = qn.hash(blockheader.block_number, + seed_block.block_number, + seed_block.headerhash, + blockheader.mining_blob(dev_config)) logger.warning("{}".format(bin2hstr(tmp_hash))) logger.debug('%s', blockheader.to_json()) return False @@ -189,13 +308,13 @@ def get_headerhashes(self, start_blocknumber): node_header_hash = qrl_pb2.NodeHeaderHash() node_header_hash.block_number = start_blocknumber - block = self._state.get_block_by_number(end_blocknumber) + block = Block.get_block_by_number(self._state, end_blocknumber) block_headerhash = block.headerhash node_header_hash.headerhashes.append(block_headerhash) end_blocknumber -= 1 while end_blocknumber >= start_blocknumber: - block_metadata = self._state.get_block_metadata(block_headerhash) + block_metadata = BlockMetadata.get_block_metadata(self._state, block_headerhash) for headerhash in block_metadata.last_N_headerhashes[-1::-1]: node_header_hash.headerhashes.append(headerhash) end_blocknumber -= len(block_metadata.last_N_headerhashes) @@ -220,79 +339,137 @@ def load(self, genesis_block): # Generate AddressStates from Genesis Block balances # Apply Genesis Block's transactions to the state # Detect if we are forked from genesis block and if so initiate recovery. + + # Loading Current Dev Config from State + current_state_key = self._state.get_dev_config_current_state_key() + if current_state_key is None: + dev_config = config.DevConfig.create(None, + config.DevConfig.get_state_key(genesis_block.headerhash), + genesis_block.headerhash, + 0, + ignore_check=True) + dev_config_pbdata = dev_config.pbdata + self._state.put_dev_config_state(dev_config_pbdata, None) + current_state_key = dev_config.current_state_key + self._state.put_dev_config_current_state_key(current_state_key, None) + + dev_config_pbdata = self._state.get_dev_config_state(current_state_key) + config.dev.update_from_pbdata(dev_config_pbdata) + + state_migration = StateMigration() + is_state_migration_needed = self._state.is_older_state_version() + if is_state_migration_needed: + state_migration.state_migration_step_1(self._state) + height = self._state.get_mainchain_height() if height == -1: - self._state.put_block(genesis_block, None) + Block.put_block(self._state, genesis_block, None) block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=genesis_block.headerhash, prev_headerhash=genesis_block.prev_headerhash) - - self._state.put_block_number_mapping(genesis_block.block_number, block_number_mapping, None) + Block.put_block_number_mapping(self._state, genesis_block.block_number, block_number_mapping, None) parent_difficulty = StringToUInt256(str(config.user.genesis_difficulty)) self.current_difficulty, _ = DifficultyTracker.get( - measurement=config.dev.mining_setpoint_blocktime, - parent_difficulty=parent_difficulty) + measurement=config.dev.block_timing_in_seconds, + parent_difficulty=parent_difficulty, + dev_config=config.dev) block_metadata = BlockMetadata.create() block_metadata.set_block_difficulty(self.current_difficulty) block_metadata.set_cumulative_difficulty(self.current_difficulty) - self._state.put_block_metadata(genesis_block.headerhash, block_metadata, None) - addresses_state = dict() + BlockMetadata.put_block_metadata(self._state, genesis_block.headerhash, block_metadata, None) + address_set = set() + + coinbase_tx = Transaction.from_pbdata(genesis_block.transactions[0]) + coinbase_tx.set_affected_address(address_set) + state_container = self.new_state_container(address_set, + 0, + True, + None) for genesis_balance in GenesisBlock().genesis_balance: bytes_addr = genesis_balance.address - addresses_state[bytes_addr] = AddressState.get_default(bytes_addr) - addresses_state[bytes_addr]._data.balance = genesis_balance.balance + state_container.addresses_state[bytes_addr] = OptimizedAddressState.get_default(bytes_addr) + state_container.addresses_state[bytes_addr]._data.balance = genesis_balance.balance for tx_idx in range(1, len(genesis_block.transactions)): tx = Transaction.from_pbdata(genesis_block.transactions[tx_idx]) for addr in tx.addrs_to: - addresses_state[addr] = AddressState.get_default(addr) + state_container.addresses_state[addr] = OptimizedAddressState.get_default(addr) + - coinbase_tx = Transaction.from_pbdata(genesis_block.transactions[0]) if not isinstance(coinbase_tx, CoinBase): return False - addresses_state[coinbase_tx.addr_to] = AddressState.get_default(coinbase_tx.addr_to) + state_container.addresses_state[coinbase_tx.addr_to] = OptimizedAddressState.get_default(coinbase_tx.addr_to) - if not coinbase_tx.validate_extended(genesis_block.block_number): + if not coinbase_tx.validate_extended(genesis_block.block_number, config.dev): return False - coinbase_tx.apply_state_changes(addresses_state) + coinbase_tx.apply(self._state, state_container) for tx_idx in range(1, len(genesis_block.transactions)): tx = Transaction.from_pbdata(genesis_block.transactions[tx_idx]) - tx.apply_state_changes(addresses_state) + tx.apply(self._state, state_container) + + state_container.paginated_tx_hash.put_paginated_data(None) + state_container.tokens.put() + self._state.put_tokens_hash(state_container.tokens.data, state_container.addresses_state) + + state_container.slaves.put() + self._state.put_slaves_hash(state_container.slaves.data, state_container.addresses_state) - self._state.put_addresses_state(addresses_state) - self._state.update_tx_metadata(genesis_block, None) + AddressState.put_addresses_state(self._state, state_container.addresses_state) + state_container.paginated_bitfield.put_addresses_bitfield(None) + TransactionMetadata.update_tx_metadata(self._state, genesis_block, None) self._state.update_mainchain_height(0, None) else: self._last_block = self.get_block_by_number(height) - self.current_difficulty = self._state.get_block_metadata(self._last_block.headerhash).block_difficulty + self.current_difficulty = BlockMetadata.get_block_metadata(self._state, + self._last_block.headerhash).block_difficulty fork_state = self._state.get_fork_state() if fork_state: - block = self._state.get_block(fork_state.initiator_headerhash) + block = Block.get_block(self._state, fork_state.initiator_headerhash) self._fork_recovery(block, fork_state) - def _apply_block(self, block: Block, batch) -> bool: - address_set = self._state.prepare_address_list(block) # Prepare list for current block - addresses_state = self._state.get_state_mainchain(address_set) - if not block.apply_state_changes(addresses_state): + if is_state_migration_needed: + logger.warning("Please Wait... Starting State Migration From Version 0 to %s", self._state.state_version) + height = state_migration.height_from_state_version_0() + start_blocknumber = self._state.get_mainchain_height() + 1 + logger.warning("Start blockheight %s", start_blocknumber) + for block_number in range(start_blocknumber, height): + block = state_migration.block_from_state_version_0(block_number) + dev_config = self.get_config_by_block_number(block_number) + self.add_block(block, check_stale=False) + if block_number % 1000 == 0: + logger.warning("Migrated Block %s/%s", block_number, height) + + if self.height % 1000 != 0: + logger.warning("Migrated Block %s/%s", self.height, height) + state_migration.state_migration_step_2(self._state) + + def _apply_block(self, block: Block, dev_config: DevConfig, batch) -> bool: + # address_set = self._state.prepare_address_list(block) # Prepare list for current block + # addresses_state = self._state.get_state_mainchain(address_set) + # if not block.apply_state_changes(addresses_state): + # return False + if not self.apply_state_changes(block, dev_config, batch): return False - self._state.put_addresses_state(addresses_state, batch) + # self._state.put_addresses_state(addresses_state, batch) return True + # TODO: Update re-org limit when dev_config is updated def _update_chainstate(self, block: Block, batch): self._last_block = block self._update_block_number_mapping(block, batch) self.tx_pool.remove_tx_in_block_from_pool(block) self._state.update_mainchain_height(block.block_number, batch) - self._state.update_tx_metadata(block, batch) + self._state.update_re_org_limit(block.block_number, batch) + TransactionMetadata.update_tx_metadata(self._state, block, batch) - def _try_branch_add_block(self, block, batch, check_stale=True) -> (bool, bool): + def _try_branch_add_block(self, block, dev_config: DevConfig, check_stale=True) -> bool: """ This function returns list of bool types. The first bool represent if the block has been added successfully and the second bool @@ -302,20 +479,22 @@ def _try_branch_add_block(self, block, batch, check_stale=True) -> (bool, bool): :param batch: :return: [Added successfully, fork_flag] """ + batch = self._state.batch + if self._last_block.headerhash == block.prev_headerhash: - if not self._apply_block(block, batch): - return False, False + if not self._apply_block(block, dev_config, batch): + return False - self._state.put_block(block, batch) + Block.put_block(self._state, block, batch) - last_block_metadata = self._state.get_block_metadata(self._last_block.headerhash) + last_block_metadata = BlockMetadata.get_block_metadata(self._state, self._last_block.headerhash) if last_block_metadata is None: logger.warning("Could not find log metadata for %s", bin2hstr(self._last_block.headerhash)) - return False, False + return False last_block_difficulty = int(UInt256ToString(last_block_metadata.cumulative_difficulty)) - new_block_metadata = self._add_block_metadata(block.headerhash, block.timestamp, block.prev_headerhash, batch) + new_block_metadata = self._add_block_metadata(block, dev_config, batch) new_block_difficulty = int(UInt256ToString(new_block_metadata.cumulative_difficulty)) if new_block_difficulty > last_block_difficulty: @@ -323,27 +502,37 @@ def _try_branch_add_block(self, block, batch, check_stale=True) -> (bool, bool): fork_state = qrlstateinfo_pb2.ForkState(initiator_headerhash=block.headerhash) self._state.put_fork_state(fork_state, batch) self._state.write_batch(batch) - return self._fork_recovery(block, fork_state), True + return self._fork_recovery(block, fork_state) self._update_chainstate(block, batch) if check_stale: - self.tx_pool.check_stale_txn(self._state, block.block_number) + self.tx_pool.check_stale_txn(self.new_state_container, + self.update_state_container, + block.block_number) self.trigger_miner = True - return True, False + self._state.write_batch(batch) - def _remove_block_from_mainchain(self, block: Block, latest_block_number: int, batch): - addresses_set = self._state.prepare_address_list(block) - addresses_state = self._state.get_state_mainchain(addresses_set) - for tx_idx in range(len(block.transactions) - 1, -1, -1): - tx = Transaction.from_pbdata(block.transactions[tx_idx]) - tx.revert_state_changes(addresses_state, self) + return True + + def _remove_block_from_mainchain(self, block: Block, latest_block_number: int, batch) -> bool: + # Reverting Dev Config to older state, if any new config + # was activated after addition of this block number + if config.dev.activation_block_number == block.block_number: + older_dev_config_pb_data = self._state.get_dev_config_state(config.dev.prev_state_key) + self._state.put_dev_config_current_state_key(config.dev.prev_state_key, batch) + config.dev.update_from_pbdata(older_dev_config_pb_data) + + if not self.revert_state_changes(block, batch): + logger.warning("Fork Recovery: Revert State Changes Failed") + return False self.tx_pool.add_tx_from_block_to_pool(block, latest_block_number) self._state.update_mainchain_height(block.block_number - 1, batch) - self._state.rollback_tx_metadata(block, batch) - self._state.remove_blocknumber_mapping(block.block_number, batch) - self._state.put_addresses_state(addresses_state, batch) + TransactionMetadata.rollback_tx_metadata(self._state, block, batch) + Block.remove_blocknumber_mapping(self._state, block.block_number, batch) + + return True def _get_fork_point(self, block: Block): tmp_block = block @@ -351,13 +540,15 @@ def _get_fork_point(self, block: Block): while True: if not block: raise Exception('[get_state] No Block Found %s, Initiator %s', block.headerhash, tmp_block.headerhash) - mainchain_block = self.get_block_by_number(block.block_number) + + mainchain_block = Block.get_block_by_number(self._state, block.block_number) if mainchain_block and mainchain_block.headerhash == block.headerhash: break + if block.block_number == 0: raise Exception('[get_state] Alternate chain genesis is different, Initiator %s', tmp_block.headerhash) hash_path.append(block.headerhash) - block = self._state.get_block(block.prev_headerhash) + block = Block.get_block(self._state, block.prev_headerhash) return block.headerhash, hash_path @@ -370,8 +561,8 @@ def _rollback(self, forked_header_hash: bytes, fork_state: qrlstateinfo_pb2.Fork """ hash_path = [] while self._last_block.headerhash != forked_header_hash: - block = self._state.get_block(self._last_block.headerhash) - mainchain_block = self._state.get_block_by_number(block.block_number) + block = Block.get_block(self._state, self._last_block.headerhash) + mainchain_block = Block.get_block_by_number(self._state, block.block_number) if block is None: logger.warning("self.state.get_block(self.last_block.headerhash) returned None") @@ -384,7 +575,8 @@ def _rollback(self, forked_header_hash: bytes, fork_state: qrlstateinfo_pb2.Fork hash_path.append(self._last_block.headerhash) batch = self._state.batch - self._remove_block_from_mainchain(self._last_block, block.block_number, batch) + if not self._remove_block_from_mainchain(self._last_block, block.block_number, batch): + return hash_path, False if fork_state: fork_state.old_mainchain_hash_path.extend([self._last_block.headerhash]) @@ -392,9 +584,9 @@ def _rollback(self, forked_header_hash: bytes, fork_state: qrlstateinfo_pb2.Fork self._state.write_batch(batch) - self._last_block = self._state.get_block(self._last_block.prev_headerhash) + self._last_block = Block.get_block(self._state, self._last_block.prev_headerhash) - return hash_path + return hash_path, True def add_chain(self, hash_path: list, fork_state: qrlstateinfo_pb2.ForkState) -> bool: """ @@ -415,11 +607,11 @@ def add_chain(self, hash_path: list, fork_state: qrlstateinfo_pb2.ForkState) -> for i in range(start, len(hash_path)): header_hash = hash_path[i] - block = self._state.get_block(header_hash) + block = Block.get_block(self._state, header_hash) batch = self._state.batch - if not self._apply_block(block, batch): + if not self._apply_block(block, config.dev, batch): return False self._update_chainstate(block, batch) @@ -445,17 +637,18 @@ def _fork_recovery(self, block: Block, fork_state: qrlstateinfo_pb2.ForkState) - rollback_done = False if fork_state.old_mainchain_hash_path: - b = self._state.get_block(fork_state.old_mainchain_hash_path[-1]) + b = Block.get_block(self._state, fork_state.old_mainchain_hash_path[-1]) if b and b.prev_headerhash == fork_state.fork_point_headerhash: rollback_done = True + success = True if not rollback_done: logger.info("Rolling back") - old_hash_path = self._rollback(forked_header_hash, fork_state) + old_hash_path, success = self._rollback(forked_header_hash, fork_state) else: old_hash_path = fork_state.old_mainchain_hash_path - if not self.add_chain(hash_path[-1::-1], fork_state): + if not success or not self.add_chain(hash_path[-1::-1], fork_state): logger.warning("Fork Recovery Failed... Recovering back to old mainchain") # If above condition is true, then it means, the node failed to add_chain # Thus old chain state, must be retrieved @@ -468,55 +661,53 @@ def _fork_recovery(self, block: Block, fork_state: qrlstateinfo_pb2.ForkState) - self.trigger_miner = True return True - def _add_block(self, block, batch=None, check_stale=True) -> (bool, bool): + def _add_block(self, block, check_stale=True) -> bool: + dev_config = self.get_config_by_block_number(block.block_number) self.trigger_miner = False - block_size_limit = self.get_block_size_limit(block) + block_size_limit = self.get_block_size_limit(block, dev_config) if block_size_limit and block.size > block_size_limit: logger.info('Block Size greater than threshold limit %s > %s', block.size, block_size_limit) - return False, False + return False - return self._try_branch_add_block(block, batch, check_stale) + return self._try_branch_add_block(block, dev_config, check_stale) def add_block(self, block: Block, check_stale=True) -> bool: with self.lock: - if block.block_number < self.height - config.dev.reorg_limit: + if block.block_number <= self.re_org_limit: logger.debug('Skipping block #%s as beyond re-org limit', block.block_number) return False if self.get_block_is_duplicate(block): return False - batch = self._state.batch - block_flag, fork_flag = self._add_block(block, batch=batch, check_stale=check_stale) - if block_flag: - if not fork_flag: - self._state.write_batch(batch) - logger.info('Added Block #%s %s', block.block_number, bin2hstr(block.headerhash)) - return True + block_flag = self._add_block(block, check_stale=check_stale) + if not block_flag: + return False - return False + logger.info('Added Block #%s %s', block.block_number, bin2hstr(block.headerhash)) + return True def _add_block_metadata(self, - headerhash, - block_timestamp, - parent_headerhash, + block: Block, + dev_config: DevConfig, batch): - block_metadata = self._state.get_block_metadata(headerhash) + block_metadata = BlockMetadata.get_block_metadata(self._state, block.headerhash) if not block_metadata: block_metadata = BlockMetadata.create() - parent_metadata = self._state.get_block_metadata(parent_headerhash) + parent_metadata = BlockMetadata.get_block_metadata(self._state, block.prev_headerhash) parent_block_difficulty = parent_metadata.block_difficulty parent_cumulative_difficulty = parent_metadata.cumulative_difficulty - block_metadata.update_last_headerhashes(parent_metadata.last_N_headerhashes, parent_headerhash) - measurement = self._state.get_measurement(block_timestamp, parent_headerhash, parent_metadata) + block_metadata.update_last_headerhashes(parent_metadata.last_N_headerhashes, block.prev_headerhash) + measurement = self.get_measurement(dev_config, block.timestamp, block.prev_headerhash, parent_metadata) block_difficulty, _ = DifficultyTracker.get( measurement=measurement, - parent_difficulty=parent_block_difficulty) + parent_difficulty=parent_block_difficulty, + dev_config=dev_config) block_cumulative_difficulty = StringToUInt256(str( int(UInt256ToString(block_difficulty)) + @@ -525,13 +716,447 @@ def _add_block_metadata(self, block_metadata.set_block_difficulty(block_difficulty) block_metadata.set_cumulative_difficulty(block_cumulative_difficulty) - parent_metadata.add_child_headerhash(headerhash) - self._state.put_block_metadata(parent_headerhash, parent_metadata, batch) - self._state.put_block_metadata(headerhash, block_metadata, batch) + parent_metadata.add_child_headerhash(block.headerhash) + BlockMetadata.put_block_metadata(self._state, block.prev_headerhash, parent_metadata, batch) + BlockMetadata.put_block_metadata(self._state, block.headerhash, block_metadata, batch) return block_metadata def _update_block_number_mapping(self, block, batch): block_number_mapping = qrl_pb2.BlockNumberMapping(headerhash=block.headerhash, prev_headerhash=block.prev_headerhash) - self._state.put_block_number_mapping(block.block_number, block_number_mapping, batch) + Block.put_block_number_mapping(self._state, block.block_number, block_number_mapping, batch) + + @staticmethod + def set_affected_address(block: Block) -> set: + addresses_set = set() + for proto_tx in block.transactions: + tx = Transaction.from_pbdata(proto_tx) + tx.set_affected_address(addresses_set) + + for genesis_balance in GenesisBlock().genesis_balance: + bytes_addr = genesis_balance.address + if bytes_addr not in addresses_set: + addresses_set.add(bytes_addr) + + return addresses_set + + def new_state_container(self, + address_set: set, + block_number: int, + write_access: bool, + batch) -> Optional[StateContainer]: + tokens = Indexer(b'token', self._state._db) + slaves = Indexer(b'slave', self._state._db) + lattice_pk = Indexer(b'lattice_pk', self._state._db) + multi_sig_spend_txs = dict() + votes_stats = dict() + + dev_config = self.get_config_by_block_number(block_number) + + addresses_state, success = self.get_state_mainchain(address_set) + if not success: + logger.warning("Failed to get state mainchain for coinbase_tx") + return None + + return StateContainer(addresses_state, + tokens, + slaves, + lattice_pk, + multi_sig_spend_txs, + votes_stats, + block_number, + self._state.total_coin_supply, + dev_config, + write_access, + self._state._db, + batch) + + def update_state_container(self, + tx: Transaction, + state_container: StateContainer) -> bool: + address_set = set() + tx.set_affected_address(address_set) + tokens = Indexer(b'token', self._state._db) + slaves = Indexer(b'slave', self._state._db) + lattice_pk = Indexer(b'lattice_pk', self._state._db) + multi_sig_spend_txs = dict() + votes_stats = dict() + + if isinstance(tx, CoinBase): + logger.warning("Coinbase txn found in new_state_container txn list") + return False + slave_addr = Transaction.get_slave(tx) + if slave_addr is not None: + key = (tx.addr_from, tx.PK) + if key not in state_container.slaves.data: + slaves.load(key) + if isinstance(tx, TransferTokenTransaction): + key = (tx.addr_from, tx.token_txhash) + if key not in state_container.tokens.data: + tokens.load(key) + + for address in tx.addrs_to: + key = (address, tx.token_txhash) + if key in state_container.tokens.data: + continue + tokens.load(key) + if isinstance(tx, SlaveTransaction): + for slave_pk in tx.slave_pks: + key = (tx.addr_from, slave_pk) + if key not in state_container.slaves.data: + slaves.load(key) + elif isinstance(tx, LatticeTransaction): + key = (tx.addr_from, tx.pk1, tx.pk2, tx.pk3, tx.pk4) + if key not in state_container.lattice_pk.data: + lattice_pk.load(key) + # elif isinstance(tx, TokenTransaction): + # for initial_balance in tx.initial_balances: + # if (initial_balance.address, tx.txhash) not in tokens: + # tokens[(initial_balance.address, tx.txhash)] = 0 + elif isinstance(tx, MultiSigVote): + if tx.shared_key not in state_container.multi_sig_spend_txs: + tx_meta_data = TransactionMetadata.get_tx_metadata(self._state, tx.shared_key) + if tx_meta_data is None: + logger.warning("[MultiSigVote] TransactionMetaData not found for the shared_key %s", tx.shared_key) + return False + + multi_sig_spend_tx = tx_meta_data[0] + multi_sig_spend_txs[tx.shared_key] = multi_sig_spend_tx + + if tx.shared_key not in state_container.votes_stats: + votes_stats[tx.shared_key] = VoteStats.get_state(self._state, + tx.shared_key) + + # Adding address whose address state will be affected on the execution of multi_sig txn. + if multi_sig_spend_tx.multi_sig_address not in state_container.addresses_state: + address_set.add(multi_sig_spend_tx.multi_sig_address) + for address in multi_sig_spend_tx.addrs_to: + if address not in state_container.addresses_state: + address_set.add(address) + elif isinstance(tx, LatticeTransaction): + # Load lattice_pk and lattice_pk_tx_hashes + pass + + addresses_state, success = self.get_state_mainchain(address_set, + ignore_addresses_set=state_container.addresses_state.keys()) + if not success: + logger.warning("get_state_mainchain failed") + return False + + return state_container.update(addresses_state, + tokens, + slaves, + lattice_pk, + multi_sig_spend_txs, + votes_stats) + + def apply_state_changes(self, block, dev_config: DevConfig, batch) -> bool: + address_set = set() + + coinbase_tx = Transaction.from_pbdata(block.transactions[0]) + coinbase_tx.set_affected_address(address_set) + state_container = self.new_state_container(address_set, + block.block_number, + True, + batch) + if state_container is None: + return False + + if not coinbase_tx.validate_extended(block.block_number, dev_config): + logger.warning('Coinbase transaction failed') + return False + + # Processing CoinBase Txn + coinbase_tx.apply(self._state, state_container) + + # Processing Rest of the Transaction + len_transactions = len(block.transactions) + for tx_idx in range(1, len_transactions): + tx = Transaction.from_pbdata(block.transactions[tx_idx]) + if not self.update_state_container(tx, state_container): + return False + + if not tx.validate_all(state_container): + return False + + tx.apply(self._state, state_container) + + # This should be done before put_addresses_state & paginated_tx_hash + # as it make changes on the balance and add more txn hash that needed + # to be added + VoteStats.put_all(self._state, state_container) + + state_container.paginated_tx_hash.put_paginated_data(batch) + + state_container.paginated_lattice_pk.put_paginated_data(batch) + + state_container.paginated_multisig_address.put_paginated_data(batch) + + state_container.paginated_multi_sig_spend.put_paginated_data(batch) + + # TODO: Add Key value storage to lattice pk + state_container.tokens.put(batch) + # This is needed to show list of tokens owned by an address on Web Wallet + state_container.paginated_tokens_hash.put_paginated_data(batch) + + state_container.slaves.put(batch) + # This is to retrieve the list of slaves of any particular address + # Could be removed if not needed + state_container.paginated_slaves_hash.put_paginated_data(batch) + + state_container.lattice_pk.put(batch) + + state_container.paginated_bitfield.put_addresses_bitfield(batch) + + AddressState.put_addresses_state(self._state, state_container.addresses_state, batch) + + return True + + def revert_state_changes(self, block, batch) -> bool: + address_set = set() + + coinbase_tx = Transaction.from_pbdata(block.transactions[0]) + coinbase_tx.set_affected_address(address_set) + state_container = self.new_state_container(address_set, + block.block_number, + True, + batch) + if state_container is None: + return False + + # Processing Rest of the Transaction + len_transactions = len(block.transactions) + for tx_idx in range(len_transactions - 1, 0, -1): + tx = Transaction.from_pbdata(block.transactions[tx_idx]) + if not self.update_state_container(tx, state_container): + logger.warning("Failed to update state_container in fork recovery") + return False + + addr_from_pk_state = state_container.addresses_state[tx.addr_from] + addr_from_pk = Transaction.get_slave(tx) + if addr_from_pk: + addr_from_pk_state = state_container.addresses_state[addr_from_pk] + + if tx.nonce != addr_from_pk_state.nonce: + logger.warning('nonce incorrect while reverting state') + logger.warning('subtype: %s', tx.type) + logger.warning('%s actual: %s expected: %s', tx.addr_from, tx.nonce, addr_from_pk_state.nonce) + return False + + if not state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(addr_from_pk_state.address, tx.ots_key): + logger.warning('pubkey reuse not detected: invalid tx %s', bin2hstr(tx.txhash)) + logger.warning('subtype: %s', tx.type) + return False + + if not tx.revert(self._state, state_container): + return False + + # Reverting CoinBase Txn + coinbase_tx.revert(self._state, state_container) + + # Invalid if slave_key doesnt exists in state + for address_slave_pk in state_container.slaves.data: + address, slave_pk = address_slave_pk + access_type = self.get_slave_pk_access_type(address, slave_pk) + if access_type is None: + logger.warning("Failed No Access Type Found") + return False + + # This should be done before put_addresses_state, paginated_tx_hash & + # after vote_txn as it make changes on the balance and add more txn hash that + # needed to be removed, as well as total weight is checked before + # reverting the multi sig execution. + if not VoteStats.revert_all(self._state, state_container): + logger.warning("Failed to Revert Vote Stats") + return False + + if not state_container.paginated_tx_hash.put_paginated_data(batch): + logger.warning("Failed Revert Addresses Transaction Hashes") + return False + + if not state_container.paginated_lattice_pk.put_paginated_data(batch): + logger.warning("Failed Revert Addresses Lattice PK Hashes") + return False + + # TODO: Put token should delete tokens address map with 0 balance + state_container.tokens.put(batch) + + if not state_container.paginated_tokens_hash.put_paginated_data(batch): + logger.warning("Failed Revert Tokens Hash") + return False + + state_container.slaves.put(batch) + + if not state_container.paginated_slaves_hash.put_paginated_data(batch): + logger.warning("Failed Revert Slaves Hash") + return False + + state_container.lattice_pk.put(batch) + + if not state_container.paginated_multi_sig_spend.put_paginated_data(batch): + logger.warning("Failed Revert Multi Sig Spend") + return False + + if not state_container.paginated_multisig_address.put_paginated_data(batch): + logger.warning("Failed Revert Multi Sig Addresses") + return False + + state_container.paginated_bitfield.put_addresses_bitfield(batch) + + # All state which records page numbers, must be saved at last + AddressState.put_addresses_state(self._state, state_container.addresses_state, batch) + + return True + + def get_state_mainchain(self, addresses_set: set, ignore_addresses_set: set = None) -> [dict, bool]: + addresses_state = dict() + for address in addresses_set: + if ignore_addresses_set is not None: + if address in ignore_addresses_set: + continue + if OptimizedAddressState.address_is_valid(address) or address == config.dev.coinbase_address: + addresses_state[address] = self.get_optimized_address_state(address) + elif MultiSigAddressState.address_is_valid(address): + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self._state._db, + address) + addresses_state[address] = multi_sig_address_state + + # Load Address State of signatories as it needs to be processed by MultiSigSpend Txn + # for inserting txn hash of MultiSigSpend to all signatories + for signatory in multi_sig_address_state.signatories: + # Ignore signatore which are in ignore_addresses_set as their address state is already loaded + if ignore_addresses_set is not None: + if signatory in ignore_addresses_set: + continue + if OptimizedAddressState.address_is_valid(signatory): + addresses_state[signatory] = self.get_optimized_address_state(signatory) + elif MultiSigAddressState.address_is_valid(signatory): + addresses_state[signatory] = MultiSigAddressState.get_multi_sig_address_state_by_address(self._state._db, + signatory) + else: + return None, False + else: + return None, False + + return addresses_state, True + + def get_all_address_state(self) -> list: + addresses_state = [] + + try: + for address, _ in self._state._db.db: + if AddressState.address_is_valid(address) or address == config.dev.coinbase_address: + addresses_state.append(self.get_address_state(address).pbdata) + return addresses_state + except Exception as e: + logger.error("Exception in get_all_address_state %s", e) + + return [] + + def get_measurement(self, + dev_config: DevConfig, + block_timestamp, + parent_headerhash, + parent_metadata: BlockMetadata): + count_headerhashes = len(parent_metadata.last_N_headerhashes) + + if count_headerhashes == 0: + return dev_config.block_timing_in_seconds + elif count_headerhashes == 1: + nth_block = Block.get_block(self._state, parent_headerhash) + count_headerhashes += 1 + else: + nth_block = Block.get_block(self._state, parent_metadata.last_N_headerhashes[1]) + + nth_block_timestamp = nth_block.timestamp + if count_headerhashes < dev_config.N_measurement: + nth_block_timestamp -= dev_config.block_timing_in_seconds + + return (block_timestamp - nth_block_timestamp) // count_headerhashes + + # TODO: This will be broken by stateful dev config + @functools.lru_cache(maxsize=config.dev.block_timeseries_size + 50) + def get_block_datapoint(self, headerhash): + block = self.get_block(headerhash) + if block is None: + return None + + block_metadata = self.get_block_metadata(headerhash) + prev_block_metadata = self.get_block_metadata(block.prev_headerhash) + prev_block = self.get_block(block.prev_headerhash) + + data_point = qrl_pb2.BlockDataPoint() + data_point.number = block.block_number + data_point.header_hash = headerhash + if prev_block is not None: + data_point.header_hash_prev = prev_block.headerhash + data_point.timestamp = block.timestamp + data_point.time_last = 0 + data_point.time_movavg = 0 + data_point.difficulty = UInt256ToString(block_metadata.block_difficulty) + + if prev_block is not None: + data_point.time_last = block.timestamp - prev_block.timestamp + if prev_block.block_number == 0: + data_point.time_last = config.dev.block_timing_in_seconds + + movavg = self.get_measurement(config.dev, + block.timestamp, + block.prev_headerhash, + prev_block_metadata) + data_point.time_movavg = movavg + + try: + # FIXME: need to consider average difficulty here + data_point.hash_power = int(data_point.difficulty) * (config.dev.block_timing_in_seconds / movavg) + except ZeroDivisionError: + data_point.hash_power = 0 + + return data_point + + def get_unused_ots_index2(self, address, start_ots_index=0): + return self.get_unused_ots_index(addresses_bitfield=dict(), + addresses_state=dict(), + address=address, + paginated_bitfield=PaginatedBitfield(False, self._state._db), + start_ots_index=start_ots_index) + + def get_unused_ots_index(self, + addresses_bitfield: dict, + addresses_state: dict, + address, + paginated_bitfield: PaginatedBitfield, + start_ots_index=0): + """ + Finds the unused ots index above the given start_ots_index. + """ + if address not in addresses_state: + addresses_state[address] = self.get_optimized_address_state(address) + + address_state = addresses_state[address] + + ots_key_count = (2 ** address_state.height) + max_page = ceil(ots_key_count / config.dev.ots_tracking_per_page) + if address_state.ots_bitfield_used_page == max_page: + return None + + page = max(address_state.ots_bitfield_used_page, start_ots_index // config.dev.ots_tracking_per_page) + 1 + + for i in range((page - 1) * config.dev.ots_tracking_per_page // 8, ots_key_count // 8): + page = (i // config.dev.ots_tracking_per_page) + 1 + key = paginated_bitfield.generate_bitfield_key(address, page) + if key not in addresses_bitfield: + addresses_bitfield[key] = paginated_bitfield.get_paginated_data(address, page) + + ots_bitfield = addresses_bitfield[key] + index = i % config.dev.ots_tracking_per_page + if ots_bitfield[index][0] < 255: + offset = 8 * index + (page - 1) * config.dev.ots_tracking_per_page + bitfield = bytearray(ots_bitfield[index]) + for relative in range(0, 8): + if ((bitfield[0] >> relative) & 1) != 1: + if offset + relative >= start_ots_index: + return offset + relative + + return None diff --git a/src/qrl/core/DifficultyTracker.py b/src/qrl/core/DifficultyTracker.py index 713e8c4b7..63379115f 100644 --- a/src/qrl/core/DifficultyTracker.py +++ b/src/qrl/core/DifficultyTracker.py @@ -1,24 +1,20 @@ from pyqryptonight.pyqryptonight import PoWHelper -from qrl.core import config - class DifficultyTracker(object): def __init__(self): pass @staticmethod - def get_target(current_difficulty): - ph = PoWHelper(kp=config.dev.kp, - set_point=config.dev.mining_setpoint_blocktime) + def get_target(current_difficulty, dev_config): + ph = PoWHelper(kp=dev_config.kp, + set_point=dev_config.block_timing_in_seconds) return ph.getTarget(current_difficulty) @staticmethod - def get(measurement, - parent_difficulty): - - ph = PoWHelper(kp=config.dev.kp, - set_point=config.dev.mining_setpoint_blocktime) + def get(measurement, parent_difficulty, dev_config): + ph = PoWHelper(kp=dev_config.kp, + set_point=dev_config.block_timing_in_seconds) current_difficulty = ph.getDifficulty(measurement=measurement, parent_difficulty=parent_difficulty) diff --git a/src/qrl/core/Indexer.py b/src/qrl/core/Indexer.py new file mode 100644 index 000000000..2955154e4 --- /dev/null +++ b/src/qrl/core/Indexer.py @@ -0,0 +1,53 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from qrl.core.misc import db +from qrl.generated.qrl_pb2 import SlaveMetadata + + +class Indexer: + def __init__(self, name: bytes, db: db): + self._name = name + self._db = db + # self._data = IndexerData(self._name) + self._data = dict() + + @property + def data(self): + return self._data + + def put(self, batch=None): + for key, value in self._data.items(): + if not value.delete: + self._db.put_raw(self.generate_key(key), value.SerializeToString(), batch) + else: + self._db.delete(self.generate_key(key), batch) + + def load(self, key) -> bool: + generated_key = self.generate_key(key) + try: + slaves_meta_data = SlaveMetadata() + self._data[key] = slaves_meta_data.ParseFromString(self._db.get_raw(generated_key)) + except Exception: + return False + + return True + + def remove(self, batch=None): + for key, value in self._data.items(): + self._db.delete(self.generate_key(key), batch) + + def generate_key(self, keys) -> bytes: + if not isinstance(keys, tuple): + raise Exception("Keys are not of type tuple for IndexerData") + new_key = self._name + + for key in keys: + if not isinstance(key, bytes): + if not isinstance(key, str): + raise Exception("Invalid key datatype, neither bytes nor string") + key = key.encode() + new_key += b'_' + key + + return new_key diff --git a/src/qrl/core/LastTransactions.py b/src/qrl/core/LastTransactions.py index 8e0921052..c4852d8f3 100644 --- a/src/qrl/core/LastTransactions.py +++ b/src/qrl/core/LastTransactions.py @@ -2,7 +2,11 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from qrl.core.misc import logger +from qrl.core.Block import Block +from qrl.core.State import State from qrl.core.txs.Transaction import Transaction +from qrl.core.txs.CoinBase import CoinBase from qrl.generated import qrlstateinfo_pb2 @@ -33,3 +37,62 @@ def deserialize(data): pbdata = qrlstateinfo_pb2.LastTransactions() pbdata.ParseFromString(bytes(data)) return LastTransactions(pbdata) + + @staticmethod + def _remove_last_tx(state: State, block: Block, batch): + if len(block.transactions) == 0: + return + + try: + last_txn = LastTransactions.deserialize(state._db.get_raw(b'last_txn')) + except: # noqa + return + + for protobuf_txn in block.transactions: + txn = Transaction.from_pbdata(protobuf_txn) + i = 0 + while i < len(last_txn.tx_metadata): + tx = Transaction.from_pbdata(last_txn.tx_metadata[i].transaction) + if txn.txhash == tx.txhash: + del last_txn.tx_metadata[i] + break + i += 1 + + state._db.put_raw(b'last_txn', last_txn.serialize(), batch) + + @staticmethod + def _update_last_tx(state: State, block: Block, batch): + if len(block.transactions) == 0: + return + last_txn = LastTransactions() + + try: + last_txn = LastTransactions.deserialize(state._db.get_raw(b'last_txn')) + except: # noqa + pass + + for protobuf_txn in block.transactions[-20:]: + txn = Transaction.from_pbdata(protobuf_txn) + if isinstance(txn, CoinBase): + continue + last_txn.add(txn, block.block_number, block.timestamp) + + state._db.put_raw(b'last_txn', last_txn.serialize(), batch) + + @staticmethod + def get_last_txs(state: State): + try: + last_txn = LastTransactions.deserialize(state._db.get_raw(b'last_txn')) + except KeyError: + return [] + except Exception as e: # noqa + logger.warning("[get_last_txs] Exception during call %s", e) + return [] + + txs = [] + for tx_metadata in last_txn.tx_metadata: + data = tx_metadata.transaction + tx = Transaction.from_pbdata(data) + txs.append(tx) + + return txs diff --git a/src/qrl/core/Miner.py b/src/qrl/core/Miner.py index ea4042513..fe2634079 100644 --- a/src/qrl/core/Miner.py +++ b/src/qrl/core/Miner.py @@ -6,50 +6,73 @@ from typing import Optional from pyqrllib.pyqrllib import bin2hstr, hstr2bin -from pyqryptonight.pyqryptonight import Qryptominer, UInt256ToString, SOLUTION +from pyqryptonight.pyqryptonight import UInt256ToString -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.config import DevConfig +from qrl.core.miners.qryptonight7.CNv1Miner import CNv1Miner +from qrl.core.miners.qrandomx.QRXMiner import QRandomXMiner +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.Block import Block from qrl.core.DifficultyTracker import DifficultyTracker from qrl.core.TransactionPool import TransactionPool from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction +from qrl.crypto.Qryptonight import Qryptonight -class Miner(Qryptominer): +class Miner: def __init__(self, + chain_manager, pre_block_logic, mining_address: bytes, - chain_manager, - mining_thread_count, - add_unprocessed_txn_fn): - super().__init__() - self.pre_block_logic = pre_block_logic # FIXME: Circular dependency with node.py - + mining_thread_count): + self.qryptonight_7_miner = CNv1Miner(pre_block_logic, + mining_address, + mining_thread_count) + + self.qrandomx_miner = QRandomXMiner(chain_manager, + pre_block_logic, + mining_address, + mining_thread_count) + self._qn = Qryptonight() + self._chain_manager = chain_manager + self._pre_block_logic = pre_block_logic self._mining_block = None self._current_difficulty = None self._current_target = None - self._measurement = None # Required only for logging - - self._mining_address = mining_address - self._reward_address = None - self._chain_manager = chain_manager - self._add_unprocessed_txn_fn = add_unprocessed_txn_fn - self._mining_thread_count = mining_thread_count - self._dummy_xmss = None - self.setForcedSleep(config.user.mining_pause) + self._measurement = None + self._current_miner = self.qrandomx_miner self.lock = threading.RLock() - def prepare_next_unmined_block_template(self, mining_address, tx_pool, parent_block: Block, parent_difficulty): + def isRunning(self): + return self._current_miner.isRunning + + def get_miner(self, height, dev_config: DevConfig): + if height < dev_config.hard_fork_heights[0]: + self._current_miner = self.qryptonight_7_miner + return self.qryptonight_7_miner + else: + self._current_miner = self.qrandomx_miner + return self.qrandomx_miner + + def solutionAvailable(self): + return self._current_miner.solutionAvailable() + + def prepare_next_unmined_block_template(self, + mining_address, + tx_pool, + parent_block: Block, + parent_difficulty, + dev_config: DevConfig): + miner = self.get_miner(parent_block.block_number + 1, dev_config) try: logger.debug('Miner-Try - prepare_next_unmined_block_template') with self.lock: logger.debug('Miner-Locked - prepare_next_unmined_block_template') logger.debug('Miner-TryCancel - prepare_next_unmined_block_template') - self.cancel() + miner.cancel() logger.debug('Miner-Cancel - prepare_next_unmined_block_template') self._mining_block = self.create_block(last_block=parent_block, @@ -58,13 +81,15 @@ def prepare_next_unmined_block_template(self, mining_address, tx_pool, parent_bl miner_address=mining_address) parent_metadata = self._chain_manager.get_block_metadata(parent_block.headerhash) - self._measurement = self._chain_manager.get_measurement(self._mining_block.timestamp, + self._measurement = self._chain_manager.get_measurement(dev_config, + self._mining_block.timestamp, self._mining_block.prev_headerhash, parent_metadata) self._current_difficulty, self._current_target = DifficultyTracker.get( measurement=self._measurement, - parent_difficulty=parent_difficulty) + parent_difficulty=parent_difficulty, + dev_config=dev_config) except Exception as e: logger.warning("Exception in start_mining") @@ -72,129 +97,101 @@ def prepare_next_unmined_block_template(self, mining_address, tx_pool, parent_bl def start_mining(self, parent_block: Block, - parent_difficulty): - try: - logger.debug('start_mining - TRY LOCK') - with self.lock: - logger.debug('start_mining - LOCKED') - self.cancel() - - mining_blob = self._mining_block.mining_blob - nonce_offset = self._mining_block.mining_nonce_offset - - logger.debug('!!! Mine #{} | {} ({}) | {} -> {} | {} '.format( - self._mining_block.block_number, - self._measurement, self._mining_block.timestamp - parent_block.timestamp, - UInt256ToString(parent_difficulty), UInt256ToString(self._current_difficulty), - bin2hstr(bytearray(self._current_target)) - )) - logger.debug('!!! Mine #{} | blob: {}'.format( - self._mining_block.block_number, - bin2hstr(bytearray(mining_blob)) - )) - - work_seq_id = self.start(input=mining_blob, - nonceOffset=nonce_offset, - target=self._current_target, - thread_count=self._mining_thread_count) - - logger.debug("MINING START [{}]".format(work_seq_id)) - - except Exception as e: - logger.warning("Exception in start_mining") - logger.exception(e) - - logger.debug('start_mining - UNLOCKED') - - def handleEvent(self, event): - # NOTE: This function usually runs in the context of a C++ thread - if event.type == SOLUTION: - logger.debug('handleEvent - TRY LOCK') - if not self.lock.acquire(blocking=False): - logger.debug('handleEvent - SKIP') - return False - - try: - logger.debug('handleEvent - LOCKED') - - logger.debug('Solution Found %s', event.nonce) - logger.info('Hash Rate: %s H/s', self.hashRate()) - cloned_block = copy.deepcopy(self._mining_block) - cloned_block.set_nonces(event.nonce, 0) - logger.debug("Blob %s", cloned_block) - logger.info('Block #%s nonce: %s', cloned_block.block_number, event.nonce) - self.pre_block_logic(cloned_block) - except Exception as e: - logger.warning("Exception in solutionEvent") - logger.exception(e) - finally: - logger.debug('handleEvent - UNLOCK') - self.lock.release() - - return True + parent_difficulty, + dev_config: DevConfig): + logger.debug('!!! Mine #{} | {} ({}) | {} -> {} | {} '.format( + self._mining_block.block_number, + self._measurement, self._mining_block.timestamp - parent_block.timestamp, + UInt256ToString(parent_difficulty), UInt256ToString(self._current_difficulty), + bin2hstr(bytearray(self._current_target)) + )) + logger.debug('!!! Mine #{} | blob: {}'.format( + self._mining_block.block_number, + bin2hstr(bytearray(self._mining_block.mining_blob(dev_config))) + )) + miner = self.get_miner(parent_block.block_number + 1, dev_config) + miner.start_mining(self._mining_block, self._current_target, dev_config) def create_block(self, last_block, mining_nonce, tx_pool: TransactionPool, miner_address) -> Optional[Block]: - dummy_block = Block.create(block_number=last_block.block_number + 1, + seed_block = self._chain_manager.get_block_by_number(self._qn.get_seed_height(last_block.block_number + 1)) + dev_config = self._chain_manager.get_config_by_block_number(block_number=last_block.block_number + 1) + + dummy_block = Block.create(dev_config=dev_config, + block_number=last_block.block_number + 1, prev_headerhash=last_block.headerhash, prev_timestamp=last_block.timestamp, transactions=[], - miner_address=miner_address) - dummy_block.set_nonces(mining_nonce, 0) + miner_address=miner_address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + dummy_block.set_nonces(dev_config, mining_nonce, 0) t_pool2 = tx_pool.transactions - addresses_set = set() - for tx_set in t_pool2: - tx = tx_set[1].transaction - tx.set_affected_address(addresses_set) - - addresses_state = dict() - for address in addresses_set: - addresses_state[address] = self._chain_manager.get_address_state(address) - block_size = dummy_block.size - block_size_limit = self._chain_manager.get_block_size_limit(last_block) + block_size_limit = self._chain_manager.get_block_size_limit(last_block, dev_config) transactions = [] + state_container = self._chain_manager.new_state_container([], + set(), + last_block.block_number, + True, + None) for tx_set in t_pool2: tx = tx_set[1].transaction + # Skip Transactions for later, which doesn't fit into block - if block_size + tx.size + config.dev.tx_extra_overhead > block_size_limit: + if block_size + tx.size + dev_config.tx_extra_overhead > block_size_limit: continue - addr_from_pk_state = addresses_state[tx.addr_from] - addr_from_pk = Transaction.get_slave(tx) - if addr_from_pk: - addr_from_pk_state = addresses_state[addr_from_pk] + if not self._chain_manager.update_state_container(tx, state_container): + logger.error("[create_block] Error updating state_container") + return None - if not tx.validate_extended(addresses_state[tx.addr_from], addr_from_pk_state): - logger.warning('Txn validation failed for tx in tx_pool') - tx_pool.remove_tx_from_pool(tx) + if not tx.validate_all(state_container, check_nonce=False): + if not state_container.revert_update(): + return None + continue + if not self._chain_manager.apply_txn(tx, state_container): + logger.error("[create_block] Failed to apply txn") + if not state_container.revert_update(): + return None continue - tx.apply_state_changes(addresses_state) + addr_from_pk_state = state_container.addresses_state[tx.addr_from] + addr_from_pk = Transaction.get_slave(tx) + if addr_from_pk: + addr_from_pk_state = state_container.addresses_state[addr_from_pk] tx._data.nonce = addr_from_pk_state.nonce - block_size += tx.size + config.dev.tx_extra_overhead + block_size += tx.size + dev_config.tx_extra_overhead transactions.append(tx) - block = Block.create(block_number=last_block.block_number + 1, + block = Block.create(dev_config=dev_config, + block_number=last_block.block_number + 1, prev_headerhash=last_block.headerhash, prev_timestamp=last_block.timestamp, transactions=transactions, - miner_address=miner_address) + miner_address=miner_address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) return block - def get_block_to_mine(self, wallet_address, tx_pool, last_block, last_block_difficulty) -> list: + def get_block_to_mine(self, + wallet_address, + tx_pool, + last_block, + last_block_difficulty) -> list: + dev_config = self._chain_manager.get_config_by_block_number(last_block.block_number + 1) try: mining_address = bytes(hstr2bin(wallet_address[1:].decode())) - if not AddressState.address_is_valid(mining_address): + if not OptimizedAddressState.address_is_valid(mining_address): raise ValueError("[get_block_to_mine] Invalid Wallet Address %s", wallet_address) except Exception as e: raise ValueError("Error while decoding wallet address %s", e) @@ -202,27 +199,39 @@ def get_block_to_mine(self, wallet_address, tx_pool, last_block, last_block_diff if self._mining_block: if last_block.headerhash == self._mining_block.prev_headerhash: if self._mining_block.transactions[0].coinbase.addr_to == mining_address: - return [bin2hstr(self._mining_block.mining_blob), + return [bin2hstr(self._mining_block.mining_blob(dev_config)), int(bin2hstr(self._current_difficulty), 16)] else: - self._mining_block.update_mining_address(mining_address) # Updates only Miner Address + self._mining_block.update_mining_address(dev_config, mining_address) # Updates only Miner Address - self.prepare_next_unmined_block_template(mining_address, tx_pool, last_block, last_block_difficulty) + self.prepare_next_unmined_block_template(mining_address, + tx_pool, + last_block, + last_block_difficulty, + dev_config=dev_config) - return [bin2hstr(self._mining_block.mining_blob), + return [bin2hstr(self._mining_block.mining_blob(dev_config)), int(bin2hstr(self._current_difficulty), 16)] def submit_mined_block(self, blob: bytes) -> bool: - if not self._mining_block.verify_blob(blob): + dev_config = self._chain_manager.get_config_by_block_number(self._mining_block.block_number - 1) + if not self._mining_block.verify_blob(blob, dev_config): return False blockheader = copy.deepcopy(self._mining_block.blockheader) blockheader.set_mining_nonce_from_blob(blob) - if not self._chain_manager.validate_mining_nonce(blockheader): + dev_config = self._chain_manager.get_config_by_block_number(blockheader.block_number) + + if not self._chain_manager.validate_mining_nonce(blockheader, dev_config): return False - self._mining_block.set_nonces(blockheader.mining_nonce, blockheader.extra_nonce) + self._mining_block.set_nonces(dev_config, + blockheader.mining_nonce, + blockheader.extra_nonce) cloned_block = copy.deepcopy(self._mining_block) - self.pre_block_logic(cloned_block) - return True + return self._pre_block_logic(cloned_block) + + def cancel(self): + self.qryptonight_7_miner.cancel() + self.qrandomx_miner.cancel() diff --git a/src/qrl/core/MultiSigAddressState.py b/src/qrl/core/MultiSigAddressState.py new file mode 100644 index 000000000..9f9d568e1 --- /dev/null +++ b/src/qrl/core/MultiSigAddressState.py @@ -0,0 +1,195 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from pyqrllib.pyqrllib import QRLHelper, hstr2bin, sha2_256 + +from collections import namedtuple +from qrl.core.misc import logger +from qrl.core.State import State +from qrl.core.TransactionMetadata import TransactionMetadata +from qrl.generated import qrl_pb2 + + +class MultiSigAddressState(object): + def __init__(self, protobuf_block=None): + self._data = protobuf_block + if protobuf_block is None: + self._data = qrl_pb2.MultiSigAddressState() + + counter_mapping = namedtuple("counter_mapping", ["get", "update"]) + + self._counter_by_name = { + b'p_tx_hash': counter_mapping(self.transaction_hash_count, + self.update_transaction_hash_count), + b'p_multi_sig_spend': counter_mapping(self.multi_sig_spend_count, + self.update_multi_sig_spend_count), + } + + @property + def pbdata(self): + """ + Returns a protobuf object that contains persistable data representing this object + :return: A protobuf MultiSigAddressState object + :rtype: qrl_pb2.MultiSigAddressState + """ + return self._data + + @property + def address(self): + return self._data.address + + @property + def creation_tx_hash(self): + return self._data.creation_tx_hash + + @property + def balance(self): + return self._data.balance + + @property + def signatories(self): + return self._data.signatories + + @property + def weights(self): + return self._data.weights + + @property + def threshold(self): + return self._data.threshold + + # @property + def transaction_hash_count(self): + return self._data.transaction_hash_count + + def multi_sig_spend_count(self): + return self._data.multi_sig_spend_count + + @staticmethod + def generate_multi_sig_address(creation_tx_hash: bytes) -> bytes: + desc = bytes(hstr2bin('110000')) + prev_hash = bytes(sha2_256(desc + creation_tx_hash)) + new_hash = bytes(sha2_256(desc + prev_hash))[-4:] + return desc + prev_hash + new_hash + + @staticmethod + def create(creation_tx_hash: bytes, + balance: int, + signatories: list, + weights: list, + threshold: int, + transaction_hash_count: int): + multi_sig_address_state = MultiSigAddressState() + + multi_sig_address_state._data.address = MultiSigAddressState.generate_multi_sig_address(creation_tx_hash) + multi_sig_address_state._data.creation_tx_hash = creation_tx_hash + multi_sig_address_state._data.balance = balance + multi_sig_address_state._data.signatories.extend(signatories) + multi_sig_address_state._data.weights.extend(weights) + multi_sig_address_state._data.threshold = threshold + multi_sig_address_state._data.transaction_hash_count = transaction_hash_count + + return multi_sig_address_state + + @staticmethod + def create_by_address(address: bytes): + multi_sig_address_state = MultiSigAddressState() + multi_sig_address_state._data.address = address + return multi_sig_address_state + + def update_transaction_hash_count(self, value=1, subtract=False): + if subtract: + self._data.transaction_hash_count -= value + else: + self._data.transaction_hash_count += value + + def update_multi_sig_spend_count(self, value=1, subtract=False): + if subtract: + self._data.multi_sig_spend_count -= value + else: + self._data.multi_sig_spend_count += value + + def get_counter_by_name(self, name: bytes): + return self._counter_by_name[name].get() + + def update_counter_by_name(self, name, value=1, subtract=False): + self._counter_by_name[name].update(value, subtract) + + def update_balance(self, state_container, value, subtract=False): + if subtract: + self._data.balance -= value + else: + self._data.balance += value + + @staticmethod + def get_default(creation_tx_hash, signatories: list, weights: list, threshold: int): + return MultiSigAddressState.create(creation_tx_hash=creation_tx_hash, + balance=0, + signatories=signatories, + weights=weights, + threshold=threshold, + transaction_hash_count=0) + + @staticmethod + def address_is_valid(address: bytes) -> bool: + if address[0:1] != b'\x11': + return False + + # Warning: Never pass this validation True for Coinbase Address + if not QRLHelper.addressIsValid(address): + return False + + return True + + def serialize(self): + return self._data.SerializeToString() + + def get_weight_by_signatory(self, signatory_address) -> [int, bool]: + for i in range(len(self.signatories)): + if self.signatories[i] == signatory_address: + return self.weights[i], True + return 0, False + + @staticmethod + def get_multi_sig_address_state(state: State, + multi_sig_tx): + try: + data = state._db.get_raw(multi_sig_tx.addr_from) + pbdata = qrl_pb2.MultiSigAddressState() + pbdata.ParseFromString(bytes(data)) + address_state = MultiSigAddressState(pbdata) + return address_state + except KeyError: + return None + + @staticmethod + def get_multi_sig_address_state_by_address(db, + multi_sig_address: bytes): + try: + data = db.get_raw(multi_sig_address) + pbdata = qrl_pb2.MultiSigAddressState() + pbdata.ParseFromString(bytes(data)) + address_state = MultiSigAddressState(pbdata) + return address_state + except KeyError: + return None + + @staticmethod + def get_multi_sig_address_by_shared_key(state: State, + shared_key: bytes): + tx, block_number = TransactionMetadata.get_tx_metadata(state, shared_key) + if tx is None: + return None + # if not isinstance(tx, MultiSigSpend): + # return None + return tx.multi_sig_address + + @staticmethod + def remove_multi_sig_address_state(state: State, + multi_sig_address: bytes, + batch=None): + try: + state._db.delete(multi_sig_address, batch) + except Exception as e: + logger.warning("Exception ", e) diff --git a/src/qrl/core/OptimizedAddressState.py b/src/qrl/core/OptimizedAddressState.py new file mode 100644 index 000000000..398932d90 --- /dev/null +++ b/src/qrl/core/OptimizedAddressState.py @@ -0,0 +1,256 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from pyqrllib.pyqrllib import QRLHelper, bin2hstr +from collections import namedtuple + +from qrl.core import config +from qrl.core.State import State +from qrl.generated import qrl_pb2 + + +class OptimizedAddressState(object): + def __init__(self, protobuf_block=None): + self._data = protobuf_block + if protobuf_block is None: + self._data = qrl_pb2.OptimizedAddressState() + + counter_mapping = namedtuple("counter_mapping", ["get", "update"]) + + self._counter_by_name = { + b"p_tx_hash": counter_mapping(self.transaction_hash_count, + self.update_transaction_hash_count), + # b"bitfield": counter_mapping(self.ots_bitfield_used_page, + # self.update_ots_bitfield_used_page), + b"p_tokens": counter_mapping(self.tokens_count, + self.update_tokens_count), + b"p_slaves": counter_mapping(self.slaves_count, + self.update_slaves_count), + b"p_lattice_pk": counter_mapping(self.lattice_pk_count, + self.update_lattice_pk_count), + b"p_multisig_address": counter_mapping(self.multi_sig_address_count, + self.update_multi_sig_address_count), + b"p_multi_sig_spend": counter_mapping(self.multi_sig_spend_count, + self.update_multi_sig_spend_count), + } + + @staticmethod + def bin_to_qaddress(binAddress): + return 'Q' + bin2hstr(binAddress) + + @property + def pbdata(self): + """ + Returns a protobuf object that contains persistable data representing this object + :return: A protobuf OptimizedAddressState object + :rtype: qrl_pb2.OptimizedAddressState + """ + return self._data + + @property + def address(self): + return self._data.address + + @property + def height(self): + return self._data.address[1] << 1 + + @property + def nonce(self): + return self._data.nonce + + @property + def balance(self): + return self._data.balance + + @property + def ots_bitfield_used_page(self): + return self._data.ots_bitfield_used_page + + @ots_bitfield_used_page.setter + def ots_bitfield_used_page(self, used_page: int): + self._data.ots_bitfield_used_page = used_page + + @property + def used_ots_key_count(self): + return self._data.used_ots_key_count + + @used_ots_key_count.setter + def used_ots_key_count(self, new_value: int): + self._data.used_ots_key_count = new_value + + @property + def ots_bitfield(self): + return self._data.ots_bitfield + + @property + def ots_counter(self): + return self._data.ots_counter + + # @property + def transaction_hash_count(self): + return self._data.transaction_hash_count + + # @property + def tokens_count(self): + return self._data.tokens_count + + # @property + def slaves_count(self): + return self._data.slaves_count + + # @property + def lattice_pk_count(self): + return self._data.lattice_pk_count + + # @property + def multi_sig_address_count(self): + return self._data.multi_sig_address_count + + def multi_sig_spend_count(self): + return self._data.multi_sig_spend_count + + def get_counter_by_name(self, name: bytes): + return self._counter_by_name[name].get() + + def update_counter_by_name(self, name, value=1, subtract=False): + self._counter_by_name[name].update(value, subtract) + + def update_balance(self, state_container, value, subtract=False): + if subtract: + self._data.balance -= value + else: + self._data.balance += value + + @staticmethod + def create(address: bytes, + nonce: int, + balance: int, + ots_bitfield_used_page: int, + transaction_hash_count: int, + tokens_count: int, + slaves_count: int, + lattice_pk_count: int, + multi_sig_address_count: int): + address_state = OptimizedAddressState() + + address_state._data.address = address + address_state._data.nonce = nonce + address_state._data.balance = balance + + address_state._data.ots_bitfield_used_page = ots_bitfield_used_page + address_state._data.transaction_hash_count = transaction_hash_count + address_state._data.tokens_count = tokens_count + address_state._data.slaves_count = slaves_count + address_state._data.lattice_pk_count = lattice_pk_count + address_state._data.multi_sig_address_count = multi_sig_address_count + + return address_state + + def update_ots_bitfield_used_page(self, value=1, subtract=False): + if subtract: + self._data.ots_bitfield_used_page -= value + else: + self._data.ots_bitfield_used_page += value + + def update_transaction_hash_count(self, value=1, subtract=False): + if subtract: + self._data.transaction_hash_count -= value + else: + self._data.transaction_hash_count += value + + def update_tokens_count(self, value=1, subtract=False): + if subtract: + self._data.tokens_count -= value + else: + self._data.tokens_count += value + + def update_slaves_count(self, value=1, subtract=False): + if subtract: + self._data.slaves_count -= value + else: + self._data.slaves_count += value + + def update_lattice_pk_count(self, value=1, subtract=False): + if subtract: + self._data.lattice_pk_count -= value + else: + self._data.lattice_pk_count += value + + def update_multi_sig_address_count(self, value=1, subtract=False): + if subtract: + self._data.multi_sig_address_count -= value + else: + self._data.multi_sig_address_count += value + + def update_multi_sig_spend_count(self, value=1, subtract=False): + if subtract: + self._data.multi_sig_spend_count -= value + else: + self._data.multi_sig_spend_count += value + + def increase_nonce(self): + self._data.nonce += 1 + + def decrease_nonce(self): + self._data.nonce -= 1 + + def get_slave_permission(self, slave_pk) -> int: + slave_pk_str = str(slave_pk) + if slave_pk_str in self._data.slave_pks_access_type: + return self._data.slave_pks_access_type[slave_pk_str] + + return -1 + + @staticmethod + def get_default(address): + address_state = OptimizedAddressState.create(address=address, + nonce=config.dev.default_nonce, + balance=config.dev.default_account_balance, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + slaves_count=0, + lattice_pk_count=0, + multi_sig_address_count=0) + + if address == config.dev.coinbase_address: + address_state._data.balance = int(config.dev.max_coin_supply * config.dev.shor_per_quanta) + return address_state + + @staticmethod + def address_is_valid(address: bytes) -> bool: + # Warning: Never pass this validation True for Coinbase Address + if not QRLHelper.addressIsValid(address): + return False + if address[0:1] == b'\x11': + return False + return True + + def serialize(self): + return self._data.SerializeToString() + + @staticmethod + def put_optimized_addresses_state(state: State, addresses_state: dict, batch=None): + """ + :param addresses_state: + :param batch: + :return: + """ + for address in addresses_state: + address_state = addresses_state[address] + data = address_state.pbdata.SerializeToString() + state._db.put_raw(address_state.address, data, batch) + + @staticmethod + def get_optimized_address_state(state: State, address: bytes): + try: + data = state._db.get_raw(address) + pbdata = qrl_pb2.OptimizedAddressState() + pbdata.ParseFromString(bytes(data)) + address_state = OptimizedAddressState(pbdata) + return address_state + except KeyError: + return OptimizedAddressState.get_default(address) + diff --git a/src/qrl/core/PaginatedBitfield.py b/src/qrl/core/PaginatedBitfield.py new file mode 100644 index 000000000..3d8155ead --- /dev/null +++ b/src/qrl/core/PaginatedBitfield.py @@ -0,0 +1,118 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from math import ceil + +from qrl.core import config +from qrl.core.PaginatedData import PaginatedData +from qrl.core.misc import logger +from qrl.generated import qrl_pb2 + + +class PaginatedBitfield(PaginatedData): + def __init__(self, write_access: bool, db): + super(PaginatedBitfield, self).__init__(b'bitfield', write_access, db) + + def generate_bitfield_key(self, address, page): + return self.name + b'_' + address + b'_' + page.to_bytes(8, byteorder='big', signed=False) + + def load_bitfield_and_ots_key_reuse(self, address, ots_key_index) -> bool: + page = (ots_key_index // config.dev.ots_tracking_per_page) + 1 + key = self.generate_bitfield_key(address, page) + self.load_bitfield(address, ots_key_index) + ots_bitfield = self.key_value[key] + + return self.ots_key_reuse(ots_bitfield, ots_key_index) + + @staticmethod + def ots_key_reuse(ots_bitfield, ots_key_index) -> bool: + offset = ots_key_index >> 3 + relative = ots_key_index % 8 + bitfield = bytearray(ots_bitfield[offset]) + bit_value = (bitfield[0] >> relative) & 1 + + if bit_value: + return True + + return False + + def set_ots_key(self, addresses_state: dict, address, ots_key_index): + page = ots_key_index // config.dev.ots_tracking_per_page + 1 + key = self.generate_bitfield_key(address, page) + self.load_bitfield(address, ots_key_index) + ots_bitfield = self.key_value[key] + + ots_key_index = ots_key_index % config.dev.ots_tracking_per_page + offset = ots_key_index >> 3 + relative = ots_key_index % 8 + bitfield = bytearray(ots_bitfield[offset]) + ots_bitfield[offset] = bytes([bitfield[0] | (1 << relative)]) + address_state = addresses_state[address] + address_state.used_ots_key_count += 1 + self.update_used_page_in_address_state(address, addresses_state, page) + + def update_used_page_in_address_state(self, address, addresses_state: dict, page: int): + # TODO: Write Unit Test + address_state = addresses_state[address] + if address_state.ots_bitfield_used_page == page - 1: + remaining_ots = 2 ** address_state.height - (page - 1) * config.dev.ots_tracking_per_page + while remaining_ots > 0: + key = self.generate_bitfield_key(address, page) + if key not in self.key_value: + self.key_value[key] = self.get_paginated_data(address, page) + ots_bitfield = self.key_value[key] + + for i in range(min(config.dev.ots_bitfield_size, ceil(remaining_ots / 8))): + if ots_bitfield[i] != b'\xff': + return + if remaining_ots >= 8: + remaining_ots -= 8 + address_state.ots_bitfield_used_page = page # TODO: Replace by setter function + page += 1 + if page * config.dev.ots_tracking_per_page > 2 ** address_state.height: + return + + def unset_ots_key(self, addresses_state: dict, address, ots_key_index): + page = ots_key_index // config.dev.ots_tracking_per_page + 1 + key = self.generate_bitfield_key(address, page) + self.load_bitfield(address, ots_key_index) + ots_bitfield = self.key_value[key] + + ots_key_index = ots_key_index % config.dev.ots_tracking_per_page + offset = ots_key_index >> 3 + relative = ots_key_index % 8 + bitfield = bytearray(ots_bitfield[offset]) + ots_bitfield[offset] = bytes([bitfield[0] & ~(1 << relative)]) + address_state = addresses_state[address] + address_state.used_ots_key_count -= 1 + if address_state.ots_bitfield_used_page >= page: + address_state.ots_bitfield_used_page = page - 1 # TODO: Replace by setter function + + def load_bitfield(self, address, ots_key_index): + page = (ots_key_index // config.dev.ots_tracking_per_page) + 1 + key = self.generate_bitfield_key(address, page) + if key not in self.key_value: + self.key_value[key] = self.get_paginated_data(address, page) + + def get_paginated_data(self, key, page): + try: + pbData = self.db.get_raw(self.name + b'_' + key + b'_' + page.to_bytes(8, byteorder='big', signed=False)) + data_list = qrl_pb2.DataList() + data_list.ParseFromString(bytes(pbData)) + return list(data_list.values) + except KeyError: + return [b'\x00'] * config.dev.ots_bitfield_size + except Exception as e: + logger.error('[get_paginated_data] Exception for %s', self.name) + logger.exception(e) + raise + + def put_addresses_bitfield(self, batch): + if not self.write_access: + return + for key in self.key_value: + data_list = qrl_pb2.DataList(values=self.key_value[key]) + self.db.put_raw(key, + data_list.SerializeToString(), + batch) diff --git a/src/qrl/core/PaginatedData.py b/src/qrl/core/PaginatedData.py new file mode 100644 index 000000000..64ead409c --- /dev/null +++ b/src/qrl/core/PaginatedData.py @@ -0,0 +1,154 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from qrl.core import config +from qrl.core.misc import logger +from qrl.generated import qrl_pb2 + + +class PaginatedData: + def __init__(self, name: bytes, write_access: bool, db): + self.name = name + self.key_value = dict() + self.db = db + self.write_access = write_access + + def reset_key_value(self): + self.key_value = dict() + + def get_value(self, key: bytes, count: int) -> list: + storage_key = self.generate_key(key, count) + return self.key_value[storage_key] + + def insert(self, address_state, value: bytes): + key = address_state.address + count = address_state.get_counter_by_name(self.name) + storage_key = self.generate_key(address_state.address, count) + + if storage_key not in self.key_value: + self.key_value[storage_key] = self.get_paginated_data(key, count) + + self.key_value[storage_key].append(value) + + address_state.update_counter_by_name(self.name) + + def remove(self, address_state, value: bytes): + address_state.update_counter_by_name(self.name, value=1, subtract=True) + + key = address_state.address + count = address_state.get_counter_by_name(self.name) + storage_key = self.generate_key(address_state.address, count) + + if storage_key not in self.key_value: + self.key_value[storage_key] = self.get_paginated_data(key, count) + + if self.key_value[storage_key][-1] != value: + logger.warning("Expected value %s", self.key_value[storage_key][-1]) + logger.warning("Found value %s", value) + raise Exception("Unexpected value into storage") + + del self.key_value[storage_key][-1] + + """ + states_with_counter: It could be address state, vote stats, proposal vote stats, proposal record + """ + # def put_paginated_data(self, states_with_counter: dict, batch) -> bool: + # data = dict() + # key_value = self.key_value + # self.key_value = dict() + # for key in key_value: + # my_state = states_with_counter[key] + # t = self.get_paginated_data(key=key, + # count=my_state.get_counter_by_name(self.name)) + # my_state.update_counter_by_name(self.name, len(t), subtract=True) + # t.extend(key_value[key]) + # data[key] = t + # + # for key in data: + # full_hashes = data[key] + # start = 0 + # hashes = full_hashes[start:start + config.dev.data_per_page] + # while hashes: + # my_state = states_with_counter[key] + # self.put(key, + # my_state.get_counter_by_name(self.name), + # hashes, + # batch) + # my_state.update_counter_by_name(self.name, len(hashes)) + # start += config.dev.data_per_page + # hashes = full_hashes[start:start + config.dev.data_per_page] + # + # return True + + def put_paginated_data(self, batch) -> bool: + key_value = self.key_value + self.key_value = dict() + for storage_key in key_value: + value = key_value[storage_key] + if len(value) == 0: + self.delete(storage_key, batch) + self.put(storage_key, value, batch) + + return True + + def get_paginated_data(self, key, count) -> list: + storage_key = self.generate_key(key, count) + try: + pbData = self.db.get_raw(storage_key) + data_list = qrl_pb2.DataList() + data_list.ParseFromString(bytes(pbData)) + return list(data_list.values) + except KeyError: + return [] + except Exception as e: + logger.error('[get_paginated_data] Exception for %s', self.name) + logger.exception(e) + raise + + def generate_key(self, key, count: int): + page = count // config.dev.data_per_page + return self.name + b'_' + key + b'_' + str(page).encode() + + def put(self, storage_key, value, batch): + if not self.write_access: + return + data_list = qrl_pb2.DataList(values=value) + self.db.put_raw(storage_key, + data_list.SerializeToString(), + batch) + + def delete(self, storage_key, batch): + if not self.write_access: + return + self.db.delete(storage_key, + batch) + + # def revert_paginated_data(self, states_with_counter: dict, batch) -> bool: + # key_value = self.key_value + # self.key_value = dict() + # for key in key_value: + # v = states_with_counter[key] + # data = self.get_paginated_data(key, v.get_counter_by_name(self.name)) + # + # for value in key_value[key]: + # if data[-1] != value: + # logger.warning("Mismatch Paginated data", data[-5:], value) + # return False + # del data[-1] + # v.update_counter_by_name(self.name, subtract=True) + # if len(data) == 0: + # self.delete(key, + # v.get_counter_by_name(self.name), + # batch) + # if v.get_counter_by_name(self.name) > 0: + # data = self.get_paginated_data(key, + # v.get_counter_by_name(self.name) - 1) + # + # if data: + # self.put(key, + # v.get_counter_by_name(self.name), + # data, + # batch) + # + # return True diff --git a/src/qrl/core/PoWValidator.py b/src/qrl/core/PoWValidator.py index 6ae6cfd4d..ff1eb6095 100644 --- a/src/qrl/core/PoWValidator.py +++ b/src/qrl/core/PoWValidator.py @@ -1,22 +1,23 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. -import functools -import threading - -from pyqryptonight.pyqryptonight import PoWHelper - +from qrl.core import config from qrl.core.Singleton import Singleton +from qrl.core.miners.qryptonight7.CNv1PoWValidator import CNv1PoWValidator +from qrl.core.miners.qrandomx.QRXPoWValidator import QRXPoWValidator class PoWValidator(object, metaclass=Singleton): def __init__(self): - self.lock = threading.Lock() - self._powv = PoWHelper() - - def verify_input(self, mining_blob, target): - return self._verify_input_cached(mining_blob, target) + self.qryptonight_7_pow_validator = CNv1PoWValidator() + self.qryptonight_r_pow_validator = QRXPoWValidator() - @functools.lru_cache(maxsize=5) - def _verify_input_cached(self, mining_blob, target): - return self._powv.verifyInput(mining_blob, target) + def verify_input(self, block_number, seed_height, seed_hash, mining_blob, target): + if block_number < config.dev.hard_fork_heights[0]: + return self.qryptonight_7_pow_validator.verify_input(mining_blob, target) + else: + return self.qryptonight_r_pow_validator.verify_input(block_number, + seed_height, + seed_hash, + mining_blob, + target) diff --git a/src/qrl/core/ProposalRecord.py b/src/qrl/core/ProposalRecord.py new file mode 100644 index 000000000..0e9287de3 --- /dev/null +++ b/src/qrl/core/ProposalRecord.py @@ -0,0 +1,75 @@ +from collections import namedtuple + +from qrl.generated import qrl_pb2 +from qrl.core.misc import logger +from qrl.core.State import State + + +class ProposalRecord: + def __init__(self, protobuf_block=None): + self._data = protobuf_block + if protobuf_block is None: + self._data = qrl_pb2.ProposalRecord() + + counter_mapping = namedtuple("counter_mapping", ["get", "update"]) + + self._counter_by_name = { + b'p_proposal_tx_hash': counter_mapping(self.number_of_tx_hashes, + self.update_number_of_tx_hashes), + } + + def pbdata(self): + return self._data + + def get_counter_by_name(self, name: bytes): + return self._counter_by_name[name].get() + + def update_counter_by_name(self, name, value=1, subtract=False): + self._counter_by_name[name].update(value, subtract) + + def number_of_tx_hashes(self): + return self._data.number_of_tx_hashes + + def update_number_of_tx_hashes(self, value=1, subtract=False): + if subtract: + self._data.number_of_tx_hashes -= value + else: + self._data.number_of_tx_hashes += value + + def serialize(self): + return self._data.SerializeToString() + + @staticmethod + def deserialize(data): + pbdata = qrl_pb2.ProposalRecord() + pbdata.ParseFromString(bytes(data)) + return ProposalRecord(pbdata) + + @staticmethod + def put_state(state: State, key, proposal_record, batch): + try: + state._db.put_raw(key, proposal_record.serialize(), batch) + except Exception as e: + raise Exception("[ProposalRecord] Exception in put_state %s", e) + + @staticmethod + def get_state(state: State, key: bytes): + try: + data = state._db.get_raw(key) + return ProposalRecord.deserialize(data) + except KeyError: + logger.debug('[get_state] ProposalRecord not found') + except Exception as e: + logger.error('[get_state] %s', e) + + return ProposalRecord() + + @staticmethod + def get_key(block_number, activation_delay): + """ + activation_block_number is the block number after which config will be activated + so an activation block number 10 means the config will be activated only after adding + block number 10 into the block chain + """ + activation_block_number = block_number + activation_delay + return b'proposal_record_block_number_' + activation_block_number.to_bytes(8, byteorder='big', signed=False) diff --git a/src/qrl/core/State.py b/src/qrl/core/State.py index 3af65be56..7f43dd901 100644 --- a/src/qrl/core/State.py +++ b/src/qrl/core/State.py @@ -2,26 +2,9 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from typing import Optional -from statistics import median - -import functools -from google.protobuf.json_format import MessageToJson, Parse -from pyqrllib.pyqrllib import bin2hstr -from pyqryptonight.pyqryptonight import UInt256ToString from qrl.core import config -from qrl.core.BlockMetadata import BlockMetadata -from qrl.core.GenesisBlock import GenesisBlock -from qrl.core.Block import Block from qrl.core.misc import logger, db -from qrl.core.txs.Transaction import Transaction -from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction -from qrl.core.txs.TokenTransaction import TokenTransaction -from qrl.core.txs.CoinBase import CoinBase -from qrl.core.TokenMetadata import TokenMetadata -from qrl.core.AddressState import AddressState -from qrl.core.LastTransactions import LastTransactions -from qrl.core.TransactionMetadata import TransactionMetadata from qrl.generated import qrl_pb2, qrlstateinfo_pb2 @@ -30,8 +13,12 @@ class State: # FIXME: Move blockchain caching/storage over here # FIXME: Improve key generation - def __init__(self): - self._db = db.DB() # generate db object here + def __init__(self, my_db=None): + self._db = my_db + if not my_db: + self._db = db.DB() # generate db object here + self._tmp_state = None # Temporary State file which needs to be fetched during migration to new db + self._state_version = 1 # Change State Version, each time any change made to leveldb structure def __enter__(self): return self @@ -43,6 +30,10 @@ def __exit__(self, exc_type, exc_val, exc_tb): del self._db self._db = None + @property + def state_version(self): + return self._state_version + @property def batch(self): return self._db.get_batch() @@ -54,107 +45,36 @@ def total_coin_supply(self): except KeyError: return 0 - def get_block_size_limit(self, block: Block): - # NOTE: Miner / - block_size_list = [] - for _ in range(0, 10): - block = self.get_block(block.prev_headerhash) - if not block: - return None - block_size_list.append(block.size) - if block.block_number == 0: - break - return max(config.dev.block_min_size_limit, config.dev.size_multiplier * median(block_size_list)) - - def put_block(self, block: Block, batch): - self._db.put_raw(block.headerhash, block.serialize(), batch) - - def get_block(self, header_hash: bytes) -> Optional[Block]: + def get_state_version(self) -> int: try: - data = self._db.get_raw(header_hash) - return Block.deserialize(data) + version = self._db.get_raw(b'state_version') + return int(version.decode()) except KeyError: - logger.debug('[get_block] Block header_hash %s not found', bin2hstr(header_hash).encode()) - except Exception as e: - logger.error('[get_block] %s', e) - - return None - - def put_block_metadata(self, headerhash: bytes, block_metadata: BlockMetadata, batch): - self._db.put_raw(b'metadata_' + headerhash, block_metadata.serialize(), batch) - - def get_block_metadata(self, header_hash: bytes) -> Optional[BlockMetadata]: - try: - data = self._db.get_raw(b'metadata_' + header_hash) - return BlockMetadata.deserialize(data) - except KeyError: - logger.debug('[get_block_metadata] Block header_hash %s not found', - b'metadata_' + bin2hstr(header_hash).encode()) - except Exception as e: - logger.error('[get_block_metadata] %s', e) - - return None - - def remove_blocknumber_mapping(self, block_number, batch): - self._db.delete(str(block_number).encode(), batch) - - def put_block_number_mapping(self, block_number: int, block_number_mapping, batch): - self._db.put_raw(str(block_number).encode(), MessageToJson(block_number_mapping, sort_keys=True).encode(), batch) + return 0 + except Exception: + raise Exception("Exception while retrieving version") - def get_block_number_mapping(self, block_number: int) -> Optional[qrl_pb2.BlockNumberMapping]: + def put_state_version(self): try: - data = self._db.get_raw(str(block_number).encode()) - block_number_mapping = qrl_pb2.BlockNumberMapping() - return Parse(data, block_number_mapping) - except KeyError: - logger.debug('[get_block_number_mapping] Block #%s not found', block_number) - except Exception as e: - logger.error('[get_block_number_mapping] %s', e) - - return None - - def get_block_by_number(self, block_number: int) -> Optional[Block]: - block_number_mapping = self.get_block_number_mapping(block_number) - if not block_number_mapping: - return None - return self.get_block(block_number_mapping.headerhash) - - def get_block_header_hash_by_number(self, block_number: int): - block_number_mapping = self.get_block_number_mapping(block_number) - if not block_number_mapping: - return None - return block_number_mapping.headerhash - - @staticmethod - def prepare_address_list(block) -> set: - addresses = set() - for proto_tx in block.transactions: - tx = Transaction.from_pbdata(proto_tx) - tx.set_affected_address(addresses) - - for genesis_balance in GenesisBlock().genesis_balance: - bytes_addr = genesis_balance.address - if bytes_addr not in addresses: - addresses.add(bytes_addr) - - return addresses - - def put_addresses_state(self, addresses_state: dict, batch=None): - """ - :param addresses_state: - :param batch: - :return: - """ - for address in addresses_state: - address_state = addresses_state[address] - data = address_state.pbdata.SerializeToString() - self._db.put_raw(address_state.address, data, batch) + self._db.put_raw(b'state_version', str(self._state_version).encode()) + except Exception: + raise Exception("Exception while Setting version") + + def is_older_state_version(self): + current_state_version = self.get_state_version() + if current_state_version < self._state_version: + return True + + def is_state_compatible(self) -> bool: + current_state_version = self.get_state_version() + if current_state_version > self._state_version: + logger.warning("You have a state with Version %s", current_state_version) + logger.warning("This node only supports State Version %s", self._state_version) + return False + elif self.is_older_state_version(): + logger.warning("Old State Version Found %s", current_state_version) - def get_state_mainchain(self, addresses_set: set): - addresses_state = dict() - for address in addresses_set: - addresses_state[address] = self.get_address_state(address) - return addresses_state + return True def get_mainchain_height(self) -> int: try: @@ -166,121 +86,42 @@ def get_mainchain_height(self) -> int: return -1 - @property - def last_block(self): - block_number = self.get_mainchain_height() - return self.get_block_by_number(block_number) - def update_mainchain_height(self, height, batch): self._db.put_raw(b'blockheight', height.to_bytes(8, byteorder='big', signed=False), batch) - def _remove_last_tx(self, block, batch): - if len(block.transactions) == 0: - return - - try: - last_txn = LastTransactions.deserialize(self._db.get_raw(b'last_txn')) - except: # noqa - return - - for protobuf_txn in block.transactions: - txn = Transaction.from_pbdata(protobuf_txn) - i = 0 - while i < len(last_txn.tx_metadata): - tx = Transaction.from_pbdata(last_txn.tx_metadata[i].transaction) - if txn.txhash == tx.txhash: - del last_txn.tx_metadata[i] - break - i += 1 - - self._db.put_raw(b'last_txn', last_txn.serialize(), batch) - - def _update_last_tx(self, block, batch): - if len(block.transactions) == 0: - return - last_txn = LastTransactions() - + def get_re_org_limit(self) -> int: try: - last_txn = LastTransactions.deserialize(self._db.get_raw(b'last_txn')) - except: # noqa - pass - - for protobuf_txn in block.transactions[-20:]: - txn = Transaction.from_pbdata(protobuf_txn) - if isinstance(txn, CoinBase): - continue - last_txn.add(txn, block.block_number, block.timestamp) - - self._db.put_raw(b'last_txn', last_txn.serialize(), batch) - - def get_last_txs(self): - try: - last_txn = LastTransactions.deserialize(self._db.get_raw(b'last_txn')) - except: # noqa - return [] - - txs = [] - for tx_metadata in last_txn.tx_metadata: - data = tx_metadata.transaction - tx = Transaction.from_pbdata(data) - txs.append(tx) - - return txs - - ######################################### - ######################################### - ######################################### - ######################################### - ######################################### - - def get_token_metadata(self, token_txhash: bytes): - try: - data = self._db.get_raw(b'token_' + token_txhash) - return TokenMetadata.deserialize(data) + return int.from_bytes(self._db.get_raw(b'reorg_limit'), byteorder='big', signed=False) except KeyError: - pass + return 0 except Exception as e: - logger.error('[get_token_metadata] %s', e) - - return None - - def update_token_metadata(self, transfer_token: TransferTokenTransaction): - token_metadata = self.get_token_metadata(transfer_token.token_txhash) - token_metadata.update([transfer_token.txhash]) - self._db.put_raw(b'token_' + transfer_token.token_txhash, - token_metadata.serialize()) + logger.error('get_re_org_limit Exception %s', e) - def create_token_metadata(self, token: TokenTransaction): - token_metadata = TokenMetadata.create(token_txhash=token.txhash, transfer_token_txhashes=[token.txhash]) - self._db.put_raw(b'token_' + token.txhash, - token_metadata.serialize()) - - def remove_transfer_token_metadata(self, transfer_token: TransferTokenTransaction): - token_metadata = self.get_token_metadata(transfer_token.token_txhash) - token_metadata.remove(transfer_token.txhash) - self._db.put_raw(b'token_' + transfer_token.token_txhash, - token_metadata.serialize()) - - def remove_token_metadata(self, token: TokenTransaction): - self._db.delete(b'token_' + token.txhash) + return -1 - ######################################### - ######################################### - ######################################### - ######################################### - ######################################### + def update_re_org_limit(self, height, batch): + reorg_limit = height - config.dev.reorg_limit + if reorg_limit <= 0: + return + current_reorg_limit = self.get_re_org_limit() + if reorg_limit <= current_reorg_limit: + return + self._db.put_raw(b'reorg_limit', reorg_limit.to_bytes(8, byteorder='big', signed=False), batch) - def get_txn_count(self, addr): + def get_address_is_used(self, address: bytes) -> bool: + # FIXME: Probably obsolete try: - return int.from_bytes(self._db.get_raw(b'txn_count_' + addr), byteorder='big', signed=False) + return self._db.get_raw(address) except KeyError: - pass + return False except Exception as e: # FIXME: Review - logger.error('Exception in get_txn_count') + logger.error('Exception in address_used') logger.exception(e) + raise - return 0 + def write_batch(self, batch, sync=True): + self._db.write_batch(batch, sync) ######################################### ######################################### @@ -288,169 +129,42 @@ def get_txn_count(self, addr): ######################################### ######################################### - def rollback_tx_metadata(self, block, batch): - fee_reward = 0 - for protobuf_txn in block.transactions: - txn = Transaction.from_pbdata(protobuf_txn) - fee_reward += txn.fee - self.remove_tx_metadata(txn, batch) - # FIXME: Being updated without batch, need to fix, - if isinstance(txn, TransferTokenTransaction): - self.remove_transfer_token_metadata(txn) - elif isinstance(txn, TokenTransaction): - self.remove_token_metadata(txn) - self._decrease_txn_count(self.get_txn_count(txn.addr_from), - txn.addr_from) - - txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction - self._update_total_coin_supply(fee_reward - txn.amount) - self._remove_last_tx(block, batch) - - def update_tx_metadata(self, block, batch): - fee_reward = 0 - # TODO (cyyber): Move To State Cache, instead of writing directly - for protobuf_txn in block.transactions: - txn = Transaction.from_pbdata(protobuf_txn) - fee_reward += txn.fee - self.put_tx_metadata(txn, - block.block_number, - block.timestamp, - batch) - # FIXME: Being updated without batch, need to fix, - if isinstance(txn, TransferTokenTransaction): - self.update_token_metadata(txn) - elif isinstance(txn, TokenTransaction): - self.create_token_metadata(txn) - self._increase_txn_count(self.get_txn_count(txn.addr_from), - txn.addr_from) - - txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction - self._update_total_coin_supply(txn.amount - fee_reward) - self._update_last_tx(block, batch) - - def remove_tx_metadata(self, txn, batch): - try: - self._db.delete(txn.txhash, batch) - except Exception: - pass + def _update_total_coin_supply(self, balance, batch): + self._db.put_raw(b'total_coin_supply', + (self.total_coin_supply + balance).to_bytes(8, byteorder='big', signed=False), + batch) - def put_tx_metadata(self, txn: Transaction, block_number: int, timestamp: int, batch): - try: - tm = TransactionMetadata.create(tx=txn, - block_number=block_number, - timestamp=timestamp) - self._db.put_raw(txn.txhash, - tm.serialize(), - batch) - except Exception: - pass - - def get_tx_metadata(self, txhash: bytes): - try: - tx_metadata = TransactionMetadata.deserialize(self._db.get_raw(txhash)) - data, block_number = tx_metadata.transaction, tx_metadata.block_number - return Transaction.from_pbdata(data), block_number - except Exception: - return None - - ######################################### - ######################################### - ######################################### - ######################################### - ######################################### - - def _increase_txn_count(self, last_count: int, addr: bytes): - # FIXME: This should be transactional - self._db.put_raw(b'txn_count_' + addr, (last_count + 1).to_bytes(8, byteorder='big', signed=False)) + def _delete(self, key, batch): + self._db.delete(key, batch) - def _decrease_txn_count(self, last_count: int, addr: bytes): - # FIXME: This should be transactional - if last_count == 0: - raise ValueError('Cannot decrease transaction count last_count: %s, addr %s', - last_count, bin2hstr(addr)) - self._db.put_raw(b'txn_count_' + addr, (last_count - 1).to_bytes(8, byteorder='big', signed=False)) + def put_dev_config_state(self, dev_config, batch): + self._db.put_raw(dev_config.current_state_key, dev_config.SerializeToString(), batch) - def get_address_state(self, address: bytes) -> AddressState: + def get_dev_config_state(self, dev_config_state_key: bytes): try: - data = self._db.get_raw(address) - pbdata = qrl_pb2.AddressState() + data = self._db.get_raw(dev_config_state_key) + pbdata = qrl_pb2.DevConfig() pbdata.ParseFromString(bytes(data)) - address_state = AddressState(pbdata) - return address_state + return pbdata except KeyError: - return AddressState.get_default(address) - - def get_all_address_state(self) -> list: - addresses_state = [] - - try: - for address in self._db.get_db_keys(False): - if AddressState.address_is_valid(address) or address == config.dev.coinbase_address: - addresses_state.append(self.get_address_state(address).pbdata) - return addresses_state + logger.debug('[get_dev_config_state] Dev Config not found') except Exception as e: - logger.error("Exception in get_addresses_state %s", e) - - return [] + logger.error('[get_dev_config_state] %s', e) - def get_address_balance(self, addr: bytes) -> int: - return self.get_address_state(addr).balance - - def get_address_nonce(self, addr: bytes) -> int: - return self.get_address_state(addr).nonce + return None - def get_address_is_used(self, address: bytes) -> bool: - # FIXME: Probably obsolete + def get_dev_config_current_state_key(self): try: - return self.get_address_state(address) is not None + return self._db.get_raw(b'dev_config_current_state_key') except KeyError: - return False + logger.debug('[get_dev_config_current_state_key] Dev Config not found') except Exception as e: - # FIXME: Review - logger.error('Exception in address_used') - logger.exception(e) - raise - - def _return_all_addresses(self): - addresses = [] - for key, data in self._db.RangeIter(b'Q', b'Qz'): - pbdata = qrl_pb2.AddressState() - pbdata.ParseFromString(bytes(data)) - address_state = AddressState(pbdata) - addresses.append(address_state) - return addresses - - def write_batch(self, batch): - self._db.write_batch(batch) - - ######################################### - ######################################### - ######################################### - ######################################### - ######################################### - - def _update_total_coin_supply(self, balance): - self._db.put_raw(b'total_coin_supply', (self.total_coin_supply + balance).to_bytes(8, byteorder='big', signed=False)) - - def get_measurement(self, block_timestamp, parent_headerhash, parent_metadata: BlockMetadata): - count_headerhashes = len(parent_metadata.last_N_headerhashes) - - if count_headerhashes == 0: - return config.dev.mining_setpoint_blocktime - elif count_headerhashes == 1: - nth_block = self.get_block(parent_headerhash) - count_headerhashes += 1 - else: - nth_block = self.get_block(parent_metadata.last_N_headerhashes[1]) - - nth_block_timestamp = nth_block.timestamp - if count_headerhashes < config.dev.N_measurement: - nth_block_timestamp -= config.dev.mining_setpoint_blocktime + logger.error('[get_dev_config_current_state_key] %s', e) - return (block_timestamp - nth_block_timestamp) // count_headerhashes + return None - def _delete(self, key, batch): - self._db.delete(key, batch) + def put_dev_config_current_state_key(self, dev_config_state_key: bytes, batch): + self._db.put_raw(b'dev_config_current_state_key', dev_config_state_key, batch) def put_fork_state(self, fork_state: qrlstateinfo_pb2.ForkState, batch=None): self._db.put_raw(b'fork_state', fork_state.SerializeToString(), batch) @@ -471,40 +185,219 @@ def get_fork_state(self) -> Optional[qrlstateinfo_pb2.ForkState]: def delete_fork_state(self, batch=None): self._db.delete(b'fork_state', batch) - @functools.lru_cache(maxsize=config.dev.block_timeseries_size + 50) - def get_block_datapoint(self, headerhash): - block = self.get_block(headerhash) - if block is None: - return None + @staticmethod + def generate_token_key(address, token_txhash) -> bytes: + return b'token_' + address + b'_' + token_txhash + + @staticmethod + def generate_slave_key(address, slave_pk) -> bytes: + return b'slave_' + address + b'_' + slave_pk + + def get_token(self, address: bytes, token_txhash: bytes) -> qrl_pb2.TokenBalance: + try: + token_balance = qrl_pb2.TokenBalance() + token_balance.ParseFromString(self._db.get_raw(self.generate_token_key(address, token_txhash))) + return token_balance + except KeyError: + pass + except Exception as e: + logger.error('[get_token] %s', e) + + return None + + def put_tokens(self, tokens: dict, batch=None): + for address_txhash, value in tokens.items(): + token_key = self.generate_token_key(address_txhash[0], address_txhash[1]) + self._db.put_raw(token_key, str(value).encode(), batch) + return True + + def revert_tokens(self, tokens: dict, batch): + for address_txhash in tokens: + token_key = self.generate_token_key(address_txhash[0], address_txhash[1]) + self._db.delete(token_key, batch) + return True + + def revert_slaves(self, slaves: dict, batch): + for address, slave_pk in slaves: + slave_key = self.generate_slave_key(address, slave_pk) + self._db.delete(slave_key, batch) + return True + + def put_slaves(self, slaves: dict, batch=None): + for address_slave_pk in slaves: + address, slave_pk = address_slave_pk + slave_key = self.generate_slave_key(address, slave_pk) + self._db.put_raw(slave_key, str(slaves[address_slave_pk][0]).encode(), batch) + + def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.SlaveMetadata: + slave_key = self.generate_slave_key(address, slave_pk) + try: + slave_metadata = qrl_pb2.SlaveMetadata() + slave_metadata.ParseFromString(self._db.get_raw(slave_key)) + return slave_metadata + except KeyError: + pass + except Exception as e: + logger.error('[get_slave_pk_access_type] %s', e) + + return None + + def revert_slaves_hash(self, slaves: dict, addresses_state: dict, batch): + addresses_slave_hashes = dict() + for address, slave_pk in slaves: + if address not in addresses_slave_hashes: + addresses_slave_hashes[address] = self.get_slave_transaction_hashes(address, + addresses_state[address].slaves_count) + + if addresses_slave_hashes[address][-1] != slaves[(address, slave_pk)].tx_hash: + logger.warning("UnExpected Addresses Slave hashes") + logger.warning("Expected %s", slaves[(address, slave_pk)][1]) + logger.warning("Found %s", addresses_slave_hashes[address][-1]) + return False + + del addresses_slave_hashes[address][-1] + address_state = addresses_state[address] + address_state.update_slaves_count(subtract=True) + + if len(addresses_slave_hashes[address]) == 0: + self.remove_slave_transaction_hashes(address, + address_state.slaves_count, + batch) + if address_state.slaves_count > 0: + addresses_slave_hashes[address] = self.get_slave_transaction_hashes( + address, address_state.slaves_count - 1) + + for address in addresses_slave_hashes: + if addresses_slave_hashes[address]: + self.put_slave_transaction_hashes(address, + addresses_state[address].slaves_count, + addresses_slave_hashes[address], + batch) + + return True + + def put_slaves_hash(self, slaves: dict, addresses_state: dict, batch=None): + slave_hashes = dict() + for address_slave_pk in slaves: + address, slave_pk = address_slave_pk + # There could be case where same address associated with multiple + # slave_pk so full_hashes needs to be loaded only once + if address not in slave_hashes: + full_hashes = self.get_slave_transaction_hashes(address, addresses_state[address].slaves_count) + addresses_state[address].update_slaves_count(len(full_hashes), subtract=True) + slave_hashes[address] = full_hashes + slave_hashes[address].append(slaves[address_slave_pk].tx_hash) + + for address in slave_hashes: + full_hashes = slave_hashes[address] + start = 0 + hashes = full_hashes[start:start+config.dev.data_per_page] + address_state = addresses_state[address] + while hashes: + address_state.update_slaves_count(len(hashes)) + self.put_slave_transaction_hashes(address, address_state.slaves_count, hashes, batch) + start += config.dev.data_per_page + hashes = full_hashes[start:start + config.dev.data_per_page] + + def remove_slave_transaction_hashes(self, address: bytes, page: int, batch=None): + self._db.delete(b'slave_transaction_hash_' + address + b'_' + str(page).encode(), + batch) + + def put_slave_transaction_hashes(self, address: bytes, count: int, hashes: list, batch=None): + page = count // config.dev.data_per_page + transaction_hash_list = qrl_pb2.TransactionHashList(hashes=hashes) + self._db.put_raw(b'slave_transaction_hash_' + address + b'_' + str(page).encode(), + transaction_hash_list.SerializeToString(), + batch) + + def get_slave_transaction_hashes(self, address: bytes, count: int) -> list: + page = count // config.dev.data_per_page + try: + data = self._db.get_raw(b'slave_transaction_hash_' + address + b'_' + str(page).encode()) + transaction_hash_list = qrl_pb2.TransactionHashList() + transaction_hash_list.ParseFromString(bytes(data)) + return list(transaction_hash_list.hashes) + except KeyError: + return [] + except Exception as e: + logger.error('Exception in get_slave_transaction_hashes') + logger.exception(e) + raise - block_metadata = self.get_block_metadata(headerhash) - prev_block_metadata = self.get_block_metadata(block.prev_headerhash) - prev_block = self.get_block(block.prev_headerhash) - - data_point = qrl_pb2.BlockDataPoint() - data_point.number = block.block_number - data_point.header_hash = headerhash - if prev_block is not None: - data_point.header_hash_prev = prev_block.headerhash - data_point.timestamp = block.timestamp - data_point.time_last = 0 - data_point.time_movavg = 0 - data_point.difficulty = UInt256ToString(block_metadata.block_difficulty) - - if prev_block is not None: - data_point.time_last = block.timestamp - prev_block.timestamp - if prev_block.block_number == 0: - data_point.time_last = config.dev.mining_setpoint_blocktime - - movavg = self.get_measurement(block.timestamp, - block.prev_headerhash, - prev_block_metadata) - data_point.time_movavg = movavg - - try: - # FIXME: need to consider average difficulty here - data_point.hash_power = int(data_point.difficulty) * (config.dev.mining_setpoint_blocktime / movavg) - except ZeroDivisionError: - data_point.hash_power = 0 - - return data_point + def put_tokens_hash(self, tokens: dict, addresses_state: dict, batch=None): + token_hashes = dict() + for address_token_tx_hash in tokens: + address, token_tx_hash = address_token_tx_hash + # There could be case where same address associated with multiple + # token_tx_hash so full_hashes needs to be loaded only once + if address not in token_hashes: + full_hashes = self.get_token_transaction_hashes(address, addresses_state[address].tokens_count) + addresses_state[address].update_tokens_count(len(full_hashes), subtract=True) + token_hashes[address] = full_hashes + token_hashes[address].append(token_tx_hash) + + for address in token_hashes: + full_hashes = token_hashes[address] + start = 0 + hashes = full_hashes[start:start+config.dev.data_per_page] + address_state = addresses_state[address] + while hashes: + self.put_token_transaction_hashes(address, address_state.tokens_count, hashes, batch) + address_state.update_tokens_count(len(hashes)) + start += config.dev.data_per_page + hashes = full_hashes[start:start + config.dev.data_per_page] + + def revert_tokens_hash(self, tokens: dict, addresses_state: dict, batch): + addresses_token_tx_hashes = dict() + for address_token_tx_hash in tokens: + address, token_tx_hash = address_token_tx_hash + if address not in addresses_token_tx_hashes: + addresses_token_tx_hashes[address] = self.get_token_transaction_hashes(address, + addresses_state[address].tokens_count) + + if addresses_token_tx_hashes[address][-1] != token_tx_hash: + return False + del addresses_token_tx_hashes[address][-1] + address_state = addresses_state[address] + address_state.update_tokens_count(subtract=True) + if len(addresses_token_tx_hashes[address]) == 0: + self.remove_token_transaction_hash(address, + address_state.tokens_count, + batch) + if address_state.tokens_count > 0: + addresses_token_tx_hashes[address] = self.get_token_transaction_hashes( + address, address_state.tokens_count - 1) + + for address in addresses_token_tx_hashes: + if addresses_token_tx_hashes[address]: + self.put_token_transaction_hashes(address, + addresses_state[address].tokens_count, + addresses_token_tx_hashes[address], + batch) + + return True + + def remove_token_transaction_hash(self, address, count, batch): + page = count // config.dev.data_per_page + self._db.delete(b'token_transaction_hash_' + address + b'_' + str(page).encode(), batch) + + def put_token_transaction_hashes(self, address: bytes, count: int, hashes: list, batch=None): + page = count // config.dev.data_per_page + transaction_hash_list = qrl_pb2.TransactionHashList(hashes=hashes) + self._db.put_raw(b'token_transaction_hash_' + address + b'_' + str(page).encode(), + transaction_hash_list.SerializeToString(), + batch) + + def get_token_transaction_hashes(self, address: bytes, count: int) -> list: + page = count // config.dev.data_per_page + try: + data = self._db.get_raw(b'token_transaction_hash_' + address + b'_' + str(page).encode()) + transaction_hash_list = qrl_pb2.TransactionHashList() + transaction_hash_list.ParseFromString(bytes(data)) + return list(transaction_hash_list.hashes) + except KeyError: + return [] + except Exception as e: + logger.error('Exception in get_token_transaction_hashes') + logger.exception(e) + raise diff --git a/src/qrl/core/StateContainer.py b/src/qrl/core/StateContainer.py new file mode 100644 index 000000000..784bd75a1 --- /dev/null +++ b/src/qrl/core/StateContainer.py @@ -0,0 +1,150 @@ +from qrl.core.config import DevConfig +from qrl.core.Indexer import Indexer +from qrl.core.PaginatedData import PaginatedData +from qrl.core.PaginatedBitfield import PaginatedBitfield +from qrl.core.misc import db, logger + + +class StateContainer: + def __init__(self, + addresses_state: dict, + tokens: Indexer, + slaves: Indexer, + lattice_pk: Indexer, + multi_sig_spend_txs: dict, + votes_stats: dict, + block_number: int, + total_coin_supply: int, + current_dev_config: DevConfig, + write_access: bool, + my_db: db, + batch): + self.delete_keys = set() + self.paginated_bitfield = PaginatedBitfield(write_access, my_db) + self.paginated_tx_hash = PaginatedData(b'p_tx_hash', write_access, my_db) + self.paginated_tokens_hash = PaginatedData(b'p_tokens', write_access, my_db) + self.paginated_slaves_hash = PaginatedData(b'p_slaves', write_access, my_db) + self.paginated_lattice_pk = PaginatedData(b'p_lattice_pk', write_access, my_db) + self.paginated_multisig_address = PaginatedData(b'p_multisig_address', write_access, my_db) + self.paginated_multi_sig_spend = PaginatedData(b'p_multi_sig_spend', write_access, my_db) + + self.addresses_state = addresses_state + + self.tokens = tokens + self.slaves = slaves + self.lattice_pk = lattice_pk + self.multi_sig_spend_txs = multi_sig_spend_txs + self.votes_stats = votes_stats + self.block_number = block_number # Block number that is being processed + self.batch = batch + self.db = my_db + self.current_dev_config = current_dev_config + + # Keeps track of last update so that it can be reverted + self.last_addresses_state = dict() + self.last_tokens = Indexer(b'token', self.db) + self.last_slaves = Indexer(b'slave', self.db) + self.last_lattice_pk = Indexer(b'lattice_pk', self.db) + self.last_multi_sig_spend_txs = dict() + self.last_votes_stats = dict() + + self._total_coin_supply = total_coin_supply # TODO: Coinbase transaction of current block is not included + + @property + def total_coin_supply(self): + return self._total_coin_supply + + @staticmethod + def _copy_key_value(src: dict, dst: dict) -> bool: + for key in src: + if key in dst: + StateContainer._revert_copy_key_value(src, dst, False) + return False + dst[key] = src[key] + + return True + + @staticmethod + def _revert_copy_key_value(src: dict, dst: dict, error_if_key_not_found: bool) -> bool: + for key in src: + if key in dst: + del dst[key] + elif error_if_key_not_found: + logger.error("Key %s not found while reverting key from state_container", key) + return False + + return True + + def update(self, + addresses_state: dict, + tokens: Indexer, + slaves: Indexer, + lattice_pk: Indexer, + multi_sig_spend_txs: dict, + votes_stats: dict) -> bool: + + self.last_addresses_state = addresses_state + self.last_tokens = tokens + self.last_slaves = slaves + self.last_lattice_pk = lattice_pk + self.last_multi_sig_spend_txs = multi_sig_spend_txs + self.last_votes_stats = votes_stats + + if not self._copy_key_value(addresses_state, self.addresses_state): + logger.error("Error updating addresses_state in state_container") + return False + + if not self._copy_key_value(tokens.data, self.tokens.data): + logger.error("Error updating tokens in state_container") + return False + + if not self._copy_key_value(slaves.data, self.slaves.data): + logger.error("Error updating slaves in state_container") + return False + + if not self._copy_key_value(lattice_pk.data, self.lattice_pk.data): + logger.error("Error updating lattice_pk in state_container") + return False + + if not self._copy_key_value(multi_sig_spend_txs, self.multi_sig_spend_txs): + logger.error("Error updating multi_sig_spend_txs in state_container") + return False + + if not self._copy_key_value(votes_stats, self.votes_stats): + logger.error("Error updating votes_stats in state_container") + return False + + return True + + def revert_update(self) -> bool: + if not self._revert_copy_key_value(self.last_addresses_state, self.addresses_state, True): + logger.error("Error reverting last_addresses_state from state_container") + return False + self.last_addresses_state = dict() + + if not self._revert_copy_key_value(self.last_tokens.data, self.tokens.data, True): + logger.error("Error reverting last_tokens from state_container") + return False + self.last_tokens = Indexer(b'token', self.db) + + if not self._revert_copy_key_value(self.last_slaves.data, self.slaves.data, True): + logger.error("Error reverting last_slaves from state_container") + return False + self.last_slaves = Indexer(b'slave', self.db) + + if not self._revert_copy_key_value(self.last_lattice_pk.data, self.lattice_pk.data, True): + logger.error("Error reverting last_lattice_pk from state_container") + return False + self.last_lattice_pk = Indexer(b'lattice_pk', self.db) + + if not self._revert_copy_key_value(self.last_multi_sig_spend_txs, self.multi_sig_spend_txs, True): + logger.error("Error reverting last_multi_sig_spend_txs from state_container") + return False + self.last_multi_sig_spend_txs = dict() + + if not self._revert_copy_key_value(self.last_votes_stats, self.votes_stats, True): + logger.error("Error reverting last_votes_stats from state_container") + return False + self.last_votes_stats = dict() + + return True diff --git a/src/qrl/core/StateMigration.py b/src/qrl/core/StateMigration.py new file mode 100644 index 000000000..feaaac318 --- /dev/null +++ b/src/qrl/core/StateMigration.py @@ -0,0 +1,49 @@ +import os +import shutil +from qrl.core import config +from qrl.core.misc import db, logger +from qrl.core.State import State +from qrl.core.Block import Block + + +# TODO: State Migration integration pending +class StateMigration: + def __init__(self): + pass + + def state_migration_step_1(self, state: State) -> bool: + """ + Migration Step from State Version 0 to 1 + :return: + """ + if state.is_older_state_version(): + db_dir_v1 = os.path.join(config.user.data_dir, config.dev.db_name+"2") + self._tmp_state = State(state._db) + state._db = db.DB(db_dir_v1) + return True + return False + + def height_from_state_version_0(self) -> int: + return self._tmp_state.get_mainchain_height() + + def block_from_state_version_0(self, block_number): + return Block.get_block_by_number(self._tmp_state, block_number) + + def state_migration_step_2(self, state: State): + """ + Migration Step from State Version 0 to 1 + :return: + """ + del self._tmp_state + self._tmp_state = None + del state._db + + tmp_db_dir = os.path.join(config.user.data_dir, config.dev.db_name + "3") + db_dir = os.path.join(config.user.data_dir, config.dev.db_name) + shutil.move(db_dir, + tmp_db_dir) + tmp_db_dir = os.path.join(config.user.data_dir, config.dev.db_name + "2") + shutil.move(tmp_db_dir, + db_dir) + state._db = db.DB() + logger.warning("State Migration Finished") diff --git a/src/qrl/core/TokenMetadata.py b/src/qrl/core/TokenMetadata.py index 052aa84f4..723748cce 100644 --- a/src/qrl/core/TokenMetadata.py +++ b/src/qrl/core/TokenMetadata.py @@ -5,6 +5,10 @@ from google.protobuf.json_format import MessageToJson, Parse from qrl.generated import qrl_pb2 +from qrl.core.misc import logger +from qrl.core.State import State +from qrl.core.txs.TokenTransaction import TokenTransaction +from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction class TokenMetadata(object): @@ -69,3 +73,42 @@ def deserialize(data): pbdata = qrl_pb2.TokenMetadata() pbdata.ParseFromString(bytes(data)) return TokenMetadata(pbdata) + + @staticmethod + def get_token_metadata(state: State, token_txhash: bytes): + try: + data = state._db.get_raw(b'token_' + token_txhash) + return TokenMetadata.deserialize(data) + except KeyError: + pass + except Exception as e: + logger.error('[get_token_metadata] %s', e) + + return None + + @staticmethod + def update_token_metadata(state: State, transfer_token: TransferTokenTransaction, batch): + token_metadata = TokenMetadata.get_token_metadata(state, transfer_token.token_txhash) + token_metadata.update([transfer_token.txhash]) + state._db.put_raw(b'token_' + transfer_token.token_txhash, + token_metadata.serialize(), + batch) + + @staticmethod + def create_token_metadata(state: State, token: TokenTransaction, batch): + token_metadata = TokenMetadata.create(token_txhash=token.txhash, transfer_token_txhashes=[token.txhash]) + state._db.put_raw(b'token_' + token.txhash, + token_metadata.serialize(), + batch) + + @staticmethod + def remove_transfer_token_metadata(state: State, transfer_token: TransferTokenTransaction, batch): + token_metadata = TokenMetadata.get_token_metadata(state, transfer_token.token_txhash) + token_metadata.remove(transfer_token.txhash) + state._db.put_raw(b'token_' + transfer_token.token_txhash, + token_metadata.serialize(), + batch) + + @staticmethod + def remove_token_metadata(state: State, token: TokenTransaction, batch): + state._db.delete(b'token_' + token.txhash, batch) diff --git a/src/qrl/core/TransactionInfo.py b/src/qrl/core/TransactionInfo.py index 006a8ccba..784a21986 100644 --- a/src/qrl/core/TransactionInfo.py +++ b/src/qrl/core/TransactionInfo.py @@ -4,6 +4,7 @@ from qrl.core import config from qrl.core.misc import ntp +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.Transaction import Transaction @@ -48,21 +49,20 @@ def is_stale(self, current_block_number: int): def update_block_number(self, current_block_number: int): self._block_number = current_block_number - def validate(self, state) -> bool: + def validate(self, new_state_container, update_state_container, block_number) -> bool: addresses_set = set() self.transaction.set_affected_address(addresses_set) + state_container = new_state_container(addresses_set, + block_number, + False, + None) - addresses_state = dict() - for address in addresses_set: - addresses_state[address] = state.get_address_state(address) - - addr_from_pk_state = addresses_state[self.transaction.addr_from] - addr_from_pk = Transaction.get_slave(self.transaction) - - if addr_from_pk: - addr_from_pk_state = addresses_state[addr_from_pk] - - if not self.transaction.validate_extended(addresses_state[self.transaction.addr_from], addr_from_pk_state): + if not update_state_container(self.transaction, state_container): return False + # Nonce should not be checked during transaction validation, + # as the appropriate nonce can be set by miner before placing + # the txn into block + if not self.transaction.validate_all(state_container, False): + return False return True diff --git a/src/qrl/core/TransactionMetadata.py b/src/qrl/core/TransactionMetadata.py index 51fc5548b..793b63589 100644 --- a/src/qrl/core/TransactionMetadata.py +++ b/src/qrl/core/TransactionMetadata.py @@ -2,6 +2,8 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from qrl.core.State import State +from qrl.core.LastTransactions import LastTransactions from qrl.core.txs.Transaction import Transaction from qrl.generated import qrlstateinfo_pb2 @@ -42,3 +44,74 @@ def deserialize(data): pbdata = qrlstateinfo_pb2.TransactionMetadata() pbdata.ParseFromString(bytes(data)) return TransactionMetadata(pbdata) + + @staticmethod + def put_tx_metadata(state: State, txn: Transaction, block_number: int, timestamp: int, batch): + try: + tm = TransactionMetadata.create(tx=txn, + block_number=block_number, + timestamp=timestamp) + state._db.put_raw(txn.txhash, + tm.serialize(), + batch) + except Exception: + pass + + @staticmethod + def get_tx_metadata(state: State, txhash: bytes): + try: + tx_metadata = TransactionMetadata.deserialize(state._db.get_raw(txhash)) + data, block_number = tx_metadata.transaction, tx_metadata.block_number + return Transaction.from_pbdata(data), block_number + except Exception: + return None + + @staticmethod + def rollback_tx_metadata(state: State, block, batch): + fee_reward = 0 + for protobuf_txn in block.transactions: + txn = Transaction.from_pbdata(protobuf_txn) + fee_reward += txn.fee + TransactionMetadata.remove_tx_metadata(state, txn, batch) + # FIXME: Being updated without batch, need to fix, + # if isinstance(txn, TransferTokenTransaction): + # self.remove_transfer_token_metadata(txn) + # elif isinstance(txn, TokenTransaction): + # self.remove_token_metadata(txn) + # self._decrease_txn_count(self.get_txn_count(txn.addr_from), + # txn.addr_from) + + txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction + state._update_total_coin_supply(fee_reward - txn.amount, batch) + LastTransactions._remove_last_tx(state, block, batch) + + @staticmethod + def update_tx_metadata(state: State, block, batch): + fee_reward = 0 + # TODO (cyyber): Move To State Cache, instead of writing directly + for protobuf_txn in block.transactions: + txn = Transaction.from_pbdata(protobuf_txn) + fee_reward += txn.fee + TransactionMetadata.put_tx_metadata(state, + txn, + block.block_number, + block.timestamp, + batch) + # FIXME: Being updated without batch, need to fix, + # if isinstance(txn, TransferTokenTransaction): + # self.update_token_metadata(txn) + # elif isinstance(txn, TokenTransaction): + # self.create_token_metadata(txn) + # self._increase_txn_count(self.get_txn_count(txn.addr_from), + # txn.addr_from) + + txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction + state._update_total_coin_supply(txn.amount - fee_reward, batch) + LastTransactions._update_last_tx(state, block, batch) + + @staticmethod + def remove_tx_metadata(state: State, txn, batch): + try: + state._db.delete(txn.txhash, batch) + except Exception: + pass diff --git a/src/qrl/core/TransactionPool.py b/src/qrl/core/TransactionPool.py index 99957682a..65b05335e 100644 --- a/src/qrl/core/TransactionPool.py +++ b/src/qrl/core/TransactionPool.py @@ -133,12 +133,12 @@ def add_tx_from_block_to_pool(self, block: Block, current_block_number): logger.warning('Block #%s %s', block.block_number, bin2hstr(block.headerhash)) return - def check_stale_txn(self, state, current_block_number): + def check_stale_txn(self, new_state_container, update_state_container, current_block_number): i = 0 while i < len(self.transaction_pool): tx_info = self.transaction_pool[i][1] if tx_info.is_stale(current_block_number): - if not tx_info.validate(state): + if not tx_info.validate(new_state_container, update_state_container, current_block_number): logger.warning('Txn validation failed for tx in tx_pool') self.remove_tx_from_pool(tx_info.transaction) continue diff --git a/src/qrl/core/VoteStats.py b/src/qrl/core/VoteStats.py new file mode 100644 index 000000000..facc4a628 --- /dev/null +++ b/src/qrl/core/VoteStats.py @@ -0,0 +1,328 @@ +from pyqrllib.pyqrllib import bin2hstr, QRLHelper + +from qrl.generated import qrl_pb2 +from qrl.core.misc import logger +from qrl.core.StateContainer import StateContainer +from qrl.core.PaginatedData import PaginatedData +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote +from qrl.core.State import State + + +class VoteStats: + def __init__(self, protobuf_block=None): + self._data = protobuf_block + if protobuf_block is None: + self._data = qrl_pb2.VoteStats() + + def pbdata(self): + return self._data + + def is_active(self, current_block_number) -> bool: + return not self.executed and current_block_number <= self.expiry_block_number + + @property + def multi_sig_address(self): + return self._data.multi_sig_address + + @property + def expiry_block_number(self): + return self._data.expiry_block_number + + @property + def shared_key(self): + return self._data.shared_key + + @property + def signatories(self): + return self._data.signatories + + @property + def tx_hashes(self): + return self._data.tx_hashes + + @property + def unvotes(self): + return self._data.unvotes + + @property + def total_weight(self): + return self._data.total_weight + + @property + def executed(self): + return self._data.executed + + def update_total_weight(self, value, subtract): + if subtract: + self._data.total_weight -= value + else: + self._data.total_weight += value + + def get_address_index(self, address: bytes): + for i in range(len(self.signatories)): + if address == self.signatories[i]: + return i + + return -1 + + def get_unvote_by_address(self, address) -> [bool, int]: + i = self.get_address_index(address) + if i != -1: + return self.unvotes[i], i + + return False, -1 + + def get_vote_tx_hash_by_signatory_address(self, address): + i = self.get_address_index(address) + return self.tx_hashes[i] + + def apply_vote_stats(self, + tx: MultiSigVote, + weight: int, + state_container: StateContainer) -> bool: + if state_container.block_number > self.expiry_block_number: + return False + + i = self.get_address_index(tx.addr_from) + + if i == -1: + return False + + if tx.unvote == self.unvotes[i]: + return False + + self._data.tx_hashes[i] = tx.txhash + + if tx.unvote: + self._data.total_weight -= weight + else: + self._data.total_weight += weight + + self._data.unvotes[i] = tx.unvote + + multi_sig_spend = state_container.multi_sig_spend_txs[self.shared_key] + threshold = state_container.addresses_state[self.multi_sig_address].threshold + + # TODO: return bool response of apply function + self.apply(state_container, + multi_sig_spend, + state_container.addresses_state, + state_container.paginated_tx_hash, + state_container.block_number, + threshold) + + return True + + def revert_vote_stats(self, + tx: MultiSigVote, + weight: int, + state_container: StateContainer) -> bool: + if state_container.block_number > self.expiry_block_number: + return False + + i = self.get_address_index(tx.addr_from) + + if i == -1: + return False + + if tx.unvote != self.unvotes[i]: + return False + + if self._data.tx_hashes[i] != tx.txhash: + return False + + multi_sig_spend = state_container.multi_sig_spend_txs[self.shared_key] + threshold = state_container.addresses_state[self.multi_sig_address].threshold + + self.revert(state_container, + multi_sig_spend, + state_container.addresses_state, + state_container.paginated_tx_hash, + state_container.block_number, + threshold) + + self._data.tx_hashes[i] = tx.prev_tx_hash + + if tx.unvote: + self._data.total_weight += weight + else: + self._data.total_weight -= weight + + self._data.unvotes[i] = not tx.unvote + + return True + + @staticmethod + def create(multi_sig_address: bytes, + shared_key: bytes, + signatories: bytes, + expiry_block_number: int): + vote_stats = VoteStats() + + vote_stats._data.multi_sig_address = multi_sig_address + vote_stats._data.shared_key = shared_key + vote_stats._data.expiry_block_number = expiry_block_number + + for signatory in signatories: + vote_stats._data.signatories.append(signatory) + vote_stats._data.tx_hashes.append(b'') + vote_stats._data.unvotes.append(True) + + return vote_stats + + def apply(self, + state_container, + multi_sig_spend, + addresses_state: dict, + paginated_tx_hash: PaginatedData, + current_block_number: int, + threshold: int) -> bool: + # TODO: return False if executed + if self.executed: + return True + + if self.total_weight < threshold: + return False + + if current_block_number > self.expiry_block_number: + return False + + if multi_sig_spend.total_amount > addresses_state[self.multi_sig_address].balance: + logger.info("[VoteStats] Insufficient funds to execute Multi Sig Spend") + logger.info("Multi Sig Spend Amount: %s, Funds Available: %s", + multi_sig_spend.total_amount, + addresses_state[self.multi_sig_address].balance) + logger.info("Multi Sig Spend txn hash: %s", bin2hstr(multi_sig_spend.txhash)) + logger.info("Multi Sig Address: %s", bin2hstr(multi_sig_spend.multi_sig_address)) + return False + + addresses_state[self.multi_sig_address].update_balance(state_container, + multi_sig_spend.total_amount, + subtract=True) + + addr_from_pk = bytes(QRLHelper.getAddress(multi_sig_spend.PK)) + for index in range(0, len(multi_sig_spend.addrs_to)): + addr_to = multi_sig_spend.addrs_to[index] + address_state = addresses_state[addr_to] + if addr_to not in (multi_sig_spend.addr_from, addr_from_pk): + paginated_tx_hash.insert(address_state, multi_sig_spend.txhash) + address_state.update_balance(state_container, multi_sig_spend.amounts[index]) + + self._data.executed = True + return True + + def revert(self, + state_container, + multi_sig_spend, + addresses_state: dict, + paginated_tx_hash: PaginatedData, + current_block_number: int, + threshold: int) -> bool: + if not self.executed: + return True + + if self.total_weight < threshold: + return False + + if current_block_number > self.expiry_block_number: + return False + addresses_state[self.multi_sig_address].update_balance(state_container, multi_sig_spend.total_amount) + + addr_from_pk = bytes(QRLHelper.getAddress(multi_sig_spend.PK)) + for index in range(0, len(multi_sig_spend.addrs_to)): + addr_to = multi_sig_spend.addrs_to[index] + address_state = addresses_state[addr_to] + if addr_to not in (multi_sig_spend.addr_from, addr_from_pk): + paginated_tx_hash.insert(address_state, multi_sig_spend.txhash) + address_state.update_balance(state_container, multi_sig_spend.amounts[index], subtract=True) + + self._data.executed = False + return True + + def serialize(self): + return self._data.SerializeToString() + + @staticmethod + def deserialize(data): + pbdata = qrl_pb2.VoteStats() + pbdata.ParseFromString(bytes(data)) + return VoteStats(pbdata) + + def put_state(self, state: State, batch): + try: + state._db.put_raw(b'shared_key_' + self.shared_key, self.serialize(), batch) + except Exception as e: + raise Exception("[put_state] Exception in VoteStats %s", e) + + @staticmethod + def delete_state(state: State, shared_key: bytes, batch): + try: + state._db.delete(b'shared_key_' + shared_key, batch) + except Exception as e: + raise Exception("[delete_state] Exception in VoteStats %s", e) + + @staticmethod + def get_state(state: State, shared_key): + try: + data = state._db.get_raw(b'shared_key_' + shared_key) + return VoteStats.deserialize(data) + except KeyError: + logger.debug('[get_state] VoteStats %s not found', bin2hstr(shared_key).encode()) + except Exception as e: + logger.error('[get_state] %s', e) + + return None + + # @staticmethod + # def apply_and_put(state: State, + # state_container: StateContainer): + # for key in state_container.votes_stats: + # vote_stats = state_container.votes_stats[key] + # multi_sig_spend = state_container.multi_sig_spend_txs[vote_stats.shared_key] + # threshold = state_container.addresses_state[vote_stats.multi_sig_address].threshold + # + # vote_stats.apply(state_container, + # multi_sig_spend, + # state_container.addresses_state, + # state_container.paginated_tx_hash, + # state_container.block_number, + # threshold) + # vote_stats.put_state(state, state_container.batch) + # + # return True + # + # @staticmethod + # def revert_and_put(state: State, + # state_container: StateContainer): + # for key in state_container.votes_stats: + # vote_stats = state_container.votes_stats[key] + # multi_sig_spend = state_container.multi_sig_spend_txs[vote_stats.shared_key] + # threshold = state_container.addresses_state[vote_stats.multi_sig_address].threshold + # + # vote_stats.revert(state_container, + # multi_sig_spend, + # state_container.addresses_state, + # state_container.paginated_tx_hash, + # state_container.block_number, + # threshold) + # vote_stats.put_state(state, state_container.batch) + # + # return True + + @staticmethod + def put_all(state: State, + state_container: StateContainer): + for key in state_container.votes_stats: + vote_stats = state_container.votes_stats[key] + vote_stats.put_state(state, state_container.batch) + + return True + + @staticmethod + def revert_all(state: State, + state_container: StateContainer): + for key in state_container.votes_stats: + vote_stats = state_container.votes_stats[key] + vote_stats.put_state(state, state_container.batch) + + return True diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index 1ce1fc178..2a82fe1ad 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -3,7 +3,9 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import decimal from os.path import expanduser +from pyqrllib.pyqrllib import hstr2bin from qrl import __version__ as version +from qrl.generated import qrl_pb2 import os @@ -61,7 +63,7 @@ def __init__(self, ignore_check=False): self.chain_state_broadcast_period = 30 # must be less than ping_timeout - self.transaction_minimum_fee = int(0 * DevConfig(ignore_check).shor_per_quanta) + self.transaction_minimum_fee = int(0 * dev.shor_per_quanta) self.transaction_pool_size = 25000 self.pending_transaction_pool_size = 75000 # 1% of the pending_transaction_pool will be reserved for moving stale txn @@ -195,13 +197,16 @@ def create_path(path): class DevConfig(object): __instance = None - def __init__(self, ignore_check=False): + def __init__(self, pbdata, ignore_check=False, ignore_singleton=False): super(DevConfig, self).__init__() # TODO: Move to metaclass in Python 3 if not ignore_check and DevConfig.__instance is not None: - raise Exception("UserConfig can only be instantiated once") + raise Exception("DevConfig can only be instantiated once") - DevConfig.__instance = self + if not ignore_singleton: + DevConfig.__instance = self + + self._data = pbdata self.version = version + ' python' @@ -217,15 +222,12 @@ def __init__(self, ignore_check=False): self.min_margin_block_number = 7 self.public_ip = None - self.reorg_limit = 22000 self.cache_frequency = 1000 self.message_q_size = 300 self.message_receipt_timeout = 10 # request timeout for full message self.message_buffer_size = 64 * 1024 * 1024 # 64 MB - self.max_coin_supply = decimal.Decimal(105000000) - self.coin_remaning_at_genesis = decimal.Decimal(40000000) self.timestamp_error = 5 # Error in second self.blocks_per_epoch = 100 @@ -236,17 +238,14 @@ def __init__(self, ignore_check=False): # Maximum number of ots index upto which OTS index should be tracked. Any OTS index above the specified value # will be managed by OTS Counter self.max_ots_tracking_index = 8192 - self.mining_nonce_offset = 39 - self.extra_nonce_offset = 43 - self.mining_blob_size = 76 + self._ots_tracking_per_page = 8192 - self.ots_bitfield_size = ceil(self.max_ots_tracking_index / 8) + self._ots_bitfield_size = ceil(self.ots_tracking_per_page / 8) self.default_nonce = 0 self.default_account_balance = 0 * (10 ** 9) self.hash_buffer_size = 4 self.minimum_minting_delay = 45 # Minimum delay in second before a block is being created - self.mining_setpoint_blocktime = 60 self.tx_extra_overhead = 15 # 15 bytes self.coinbase_address = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' \ @@ -266,29 +265,10 @@ def __init__(self, ignore_check=False): self.supplied_coins = 65000000 * (10 ** 9) # ====================================== - # TRANSACTION CONTROLLER + # STATE PAGINATION CONTROLLER # ====================================== - # Max number of output addresses and corresponding data can be added into a list of a transaction - self.transaction_multi_output_limit = 100 - - # ====================================== - # TOKEN TRANSACTION - # ====================================== - self.max_token_symbol_length = 10 - self.max_token_name_length = 30 - - # ====================================== - # DIFFICULTY CONTROLLER - # ====================================== - self.N_measurement = 30 - self.kp = 5 - - # ====================================== - # BLOCK SIZE CONTROLLER - # ====================================== - self.number_of_blocks_analyze = 10 - self.size_multiplier = 1.1 - self.block_min_size_limit = 1024 * 1024 # 1 MB - Initial Block Size Limit + # Max number of data to be stored per key + self._data_per_page = 10000 # ====================================== # P2P SETTINGS @@ -308,12 +288,276 @@ def __init__(self, ignore_check=False): # ====================================== self.shor_per_quanta = decimal.Decimal(10 ** 9) + # ====================================== + # # FOUNDATION MULTI-SIG ADDRESSES + # # ====================================== + # self.percentage = 100 # multiplier for foundation_address_threshold_percentage to keep it an integer + # self.foundation_multi_sig_addresses = [b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + # b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + # b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + # ] + + # ====================================== + # HARD FORK HEIGHTS LIST + # ====================================== + self.hard_fork_heights = [50000] + + # ====================================== + # PROPOSAL CONFIG + # ====================================== + self.proposal_unit_percentage = 100 + + @property + def pbdata(self): + return self._data + + @property + def prev_state_key(self): + return self._data.prev_state_key + + @property + def current_state_key(self): + return self._data.current_state_key + + @property + def activation_header_hash(self): + return self._data.activation_header_hash + + @property + def activation_block_number(self): + return self._data.activation_block_number + + @property + def data_per_page(self): + return self._data_per_page + + @property + def ots_tracking_per_page(self): + return self._ots_tracking_per_page + + @property + def ots_bitfield_size(self): + return self._ots_bitfield_size + + @property + def reorg_limit(self): + return self.pbdata.chain.reorg_limit + + @property + def max_coin_supply(self): + return decimal.Decimal(self.pbdata.chain.max_coin_supply) + + @property + def complete_emission_time_span_in_years(self): + return self.pbdata.chain.complete_emission_time_span_in_years + + @property + def coin_remaining_at_genesis(self): + return decimal.Decimal(self.pbdata.chain.max_coin_supply - 65000000) + + @property + def mining_nonce_offset(self): + return self.pbdata.block.mining_nonce_offset + + @property + def extra_nonce_offset(self): + return self.pbdata.block.extra_nonce_offset + + @property + def mining_blob_size_in_bytes(self): + return self.pbdata.block.mining_blob_size_in_bytes + + @property + def block_timing_in_seconds(self): + return self.pbdata.block.block_timing_in_seconds + + @property + def number_of_blocks_to_analyze(self): + return self.pbdata.block.block_size_controller.number_of_blocks_analyze + + @property + def size_multiplier(self): + return self.pbdata.block.block_size_controller.size_multiplier / 100 + + @property + def block_min_size_limit_in_bytes(self): + return self.pbdata.block.block_size_controller.block_min_size_limit_in_bytes + + @property + def transaction_multi_output_limit(self): + return self.pbdata.transaction.multi_output_limit + + # @property + # def foundation_address_threshold_percentage(self): + # return self.pbdata.transaction.foundation_multi_sig.threshold_percentage + + @property + def message_max_length(self): + return self.pbdata.transaction.message.max_length + + @property + def slave_pk_max_length(self): + return self.pbdata.transaction.slave.slave_pk_max_length + + @property + def max_token_symbol_length(self): + return self.pbdata.transaction.token.symbol_max_length + + @property + def max_token_name_length(self): + return self.pbdata.transaction.token.name_max_length + + @property + def lattice_pk1_max_length(self): + return self.pbdata.transaction.lattice.pk1_max_length + + @property + def lattice_pk2_max_length(self): + return self.pbdata.transaction.lattice.pk2_max_length + + @property + def lattice_pk3_max_length(self): + return self.pbdata.transaction.lattice.pk3_max_length + + @property + def lattice_pk4_max_length(self): + return self.pbdata.transaction.lattice.pk4_max_length + + @property + def proposal_threshold_per(self): + return self.pbdata.transaction.proposal.threshold_per + + @property + def default_proposal_options(self): + return self.pbdata.transaction.proposal.default_options + + @property + def description_max_length(self): + return self.pbdata.transaction.proposal.description_max_length + + @property + def options_max_number(self): + return self.pbdata.transaction.proposal.options_max_number + + @property + def option_max_text_length(self): + return self.pbdata.transaction.proposal.option_max_text_length + + @property + def proposal_config_activation_delay(self): + return self.pbdata.transaction.proposal.proposal_config_activation_delay + + @property + def N_measurement(self): + return self.pbdata.pow.N_measurement + + @property + def kp(self): + return self.pbdata.pow.kp + @staticmethod - def getInstance(): + def getInstance(prev_state_key, + current_state_key: bytes, + current_block_header_hash: bytes, + current_block_number: int): if DevConfig.__instance is None: - return DevConfig() + return DevConfig.create(prev_state_key, + current_state_key, + current_block_header_hash, + current_block_number) return DevConfig.__instance + @staticmethod + def get_state_key(headerhash: bytes): + return b'dev_config_' + headerhash + + @staticmethod + def create(prev_state_key, + current_state_key: bytes, + current_block_header_hash: bytes, + current_block_number: int, + ignore_check=False, + ignore_singleton=False): + chain = qrl_pb2.DevConfig.Chain(reorg_limit=10, + max_coin_supply=105000000, + complete_emission_time_span_in_years=200) + block_size_controller = qrl_pb2.DevConfig.Block.BlockSizeController(number_of_blocks_analyze=10, + size_multiplier=110, # 1.1 + block_min_size_limit_in_bytes=1024 * 1024) + block = qrl_pb2.DevConfig.Block(mining_nonce_offset=39, + extra_nonce_offset=43, + mining_blob_size_in_bytes=76, + block_timing_in_seconds=60, + block_size_controller=block_size_controller) + + message = qrl_pb2.DevConfig.Transaction.Message(max_length=80) + + slave = qrl_pb2.DevConfig.Transaction.Slave(slave_pk_max_length=67) + + token = qrl_pb2.DevConfig.Transaction.Token(symbol_max_length=10, + name_max_length=30) + + # TODO: Change following values before hard fork + lattice = qrl_pb2.DevConfig.Transaction.Lattice(pk1_max_length=2000, + pk2_max_length=2000, + pk3_max_length=2000, + pk4_max_length=2000) + + foundation_multi_sig = qrl_pb2.DevConfig.Transaction.FoundationMultiSig(threshold_percentage=10) + + # proposal_config_activation_delay should not be less than reorg_limit + proposal = qrl_pb2.DevConfig.Transaction.Proposal(threshold_per=51, + default_options=["YES", "NO", "ABSTAIN"], + description_max_length=400, + options_max_number=100, + option_max_text_length=30, + proposal_config_activation_delay=10) + + transaction = qrl_pb2.DevConfig.Transaction(multi_output_limit=100, + message=message, + slave=slave, + token=token, + lattice=lattice, + foundation_multi_sig=foundation_multi_sig, + proposal=proposal) + + pow = qrl_pb2.DevConfig.POW(N_measurement=30, + kp=5) + + dev_config = qrl_pb2.DevConfig(chain=chain, + block=block, + transaction=transaction, + pow=pow) + + if prev_state_key is not None: + dev_config.prev_state_key = prev_state_key + dev_config.current_state_key = current_state_key + + dev_config.activation_header_hash = current_block_header_hash + dev_config.activation_block_number = current_block_number + + return DevConfig(dev_config, + ignore_check, + ignore_singleton) + + def serialize(self) -> str: + return self._data.SerializeToString() + @staticmethod + def deserialize(data): + pbdata = qrl_pb2.DevConfig() + pbdata.ParseFromString(bytes(data)) + dev_config = DevConfig(pbdata) + return dev_config + + def update_from_pbdata(self, pbdata): + self._data = pbdata + + +# Hard coded Genesis Header Hash, must be updated if any change is made to genesis block +genesis_header_hash = bytes(hstr2bin('2a1c4a9433f1de36f8b99c7c5aceb7bd2eb39e1ead648ea58227d399ad84c724')) +dev = DevConfig.getInstance(None, + DevConfig.get_state_key(genesis_header_hash), + genesis_header_hash, + 0) user = UserConfig.getInstance() -dev = DevConfig.getInstance() diff --git a/src/qrl/core/formulas.py b/src/qrl/core/formulas.py index 4ce2e2340..e9aebdd8a 100644 --- a/src/qrl/core/formulas.py +++ b/src/qrl/core/formulas.py @@ -4,28 +4,30 @@ import datetime import decimal from decimal import Decimal +from qrl.core.config import DevConfig -from qrl.core import config -START_DATE = datetime.datetime(2018, 4, 1, 0, 0, 0) -END_DATE = datetime.datetime(2218, 4, 1, 0, 0, 0) -c = END_DATE - START_DATE -TOTAL_MINUTES = divmod(c.days * 86400 + c.seconds, 60)[0] +def get_total_blocks(dev_config: DevConfig): + START_DATE = datetime.datetime(2018, 4, 1, 0, 0, 0) + END_DATE = datetime.datetime(2018 + dev_config.complete_emission_time_span_in_years, 4, 1, 0, 0, 0) + c = END_DATE - START_DATE + TOTAL_SECONDS = c.days * 86400 + c.seconds + total_blocks = divmod(TOTAL_SECONDS, dev_config.block_timing_in_seconds)[0] -# At 1 block per minute -TOTAL_BLOCKS = Decimal(TOTAL_MINUTES) + # At 1 block per minute + return Decimal(total_blocks) -def calc_coeff() -> Decimal: +def calc_coeff(dev_config: DevConfig) -> Decimal: """ block reward calculation. Decay curve: 200 years >>> calc_coeff() Decimal('1.664087503734056374552843909E-7') """ - return config.dev.coin_remaning_at_genesis.ln() / TOTAL_BLOCKS + return dev_config.coin_remaining_at_genesis.ln() / get_total_blocks(dev_config) -def remaining_emission(block_n) -> Decimal: +def remaining_emission(block_n, dev_config: DevConfig) -> Decimal: # TODO: This is more related to the way QRL works.. Move to another place """ calculate remaining emission at block_n: N=total initial coin supply, coeff = decay constant @@ -42,12 +44,12 @@ def remaining_emission(block_n) -> Decimal: >>> remaining_emission(100) Decimal('39999334370536850') """ - coeff = calc_coeff() - return (config.dev.coin_remaning_at_genesis * config.dev.shor_per_quanta * Decimal(-coeff * block_n).exp()) \ + coeff = calc_coeff(dev_config) + return (dev_config.coin_remaining_at_genesis * dev_config.shor_per_quanta * Decimal(-coeff * block_n).exp()) \ .quantize(Decimal('1.'), rounding=decimal.ROUND_DOWN) -def block_reward(block_number) -> Decimal: +def block_reward(block_number: int, dev_config: DevConfig) -> Decimal: """ :return: Block reward in shors for block number @@ -63,4 +65,4 @@ def block_reward(block_number) -> Decimal: >>> tmp_est - tmp_sum Decimal('0') """ - return remaining_emission(block_number - 1) - remaining_emission(block_number) + return remaining_emission(block_number - 1, dev_config) - remaining_emission(block_number, dev_config) diff --git a/src/qrl/core/messagereceipt.py b/src/qrl/core/messagereceipt.py index 070f6eb8a..e741abfc1 100644 --- a/src/qrl/core/messagereceipt.py +++ b/src/qrl/core/messagereceipt.py @@ -54,7 +54,10 @@ class MessageReceipt(object): LegacyMessage.MT, LegacyMessage.TK, LegacyMessage.TT, - LegacyMessage.SL] + LegacyMessage.SL, + LegacyMessage.MC, + LegacyMessage.MS, + LegacyMessage.MV] services_arg = { ###################### @@ -81,6 +84,10 @@ class MessageReceipt(object): qrllegacy_pb2.LegacyMessage.EPH: 'ephData', qrllegacy_pb2.LegacyMessage.SYNC: 'syncData', + + qrllegacy_pb2.LegacyMessage.MC: 'mcData', + qrllegacy_pb2.LegacyMessage.MS: 'msData', + qrllegacy_pb2.LegacyMessage.MV: 'mvData', } def __init__(self): diff --git a/src/qrl/core/miners/__init__.py b/src/qrl/core/miners/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/qrl/core/miners/qrandomx/QRXMiner.py b/src/qrl/core/miners/qrandomx/QRXMiner.py new file mode 100644 index 000000000..d6b2e6507 --- /dev/null +++ b/src/qrl/core/miners/qrandomx/QRXMiner.py @@ -0,0 +1,100 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import copy +import threading + +from pyqrandomx.pyqrandomx import QRXMiner, SOLUTION + +from qrl.core.config import DevConfig, user as user_config +from qrl.core.Block import Block +from qrl.core.misc import logger +from qrl.crypto.QRandomX import QRandomX + + +class QRandomXMiner(QRXMiner): + def __init__(self, + chain_manager, + pre_block_logic, + mining_address: bytes, + mining_thread_count): + super().__init__() + self._qn = QRandomX() + self._chain_manager = chain_manager + self._pre_block_logic = pre_block_logic # FIXME: Circular dependency with node.py + + self._mining_address = mining_address + self._mining_thread_count = mining_thread_count + + self._mining_block = None + self._seed_block = None + self.setForcedSleep(user_config.mining_pause) + self._dev_config = None + self.lock = threading.RLock() + + def get_seed_block(self, block_number): + # TODO: Verify when seed height is changed also add unit test for edge case + seed_height = self._qn.get_seed_height(block_number) + if self._seed_block is None or self._seed_block.block_number != seed_height: + self._seed_block = self._chain_manager.get_block_by_number(seed_height) + return self._seed_block + + def start_mining(self, + mining_block: Block, + current_target: bytes, + dev_config: DevConfig): + try: + logger.debug('start_mining - TRY LOCK') + with self.lock: + logger.debug('start_mining - LOCKED') + self.cancel() + + mining_blob = mining_block.mining_blob(dev_config) + nonce_offset = mining_block.mining_nonce_offset(dev_config) + + seed_block = self.get_seed_block(mining_block.block_number) + + self._dev_config = dev_config + self._mining_block = mining_block + work_seq_id = self.start(mainHeight=mining_block.block_number, + seedHeight=seed_block.block_number, + seedHash=seed_block.headerhash, + input=mining_blob, + nonceOffset=nonce_offset, + target=current_target, + thread_count=self._mining_thread_count) + + logger.debug("MINING START [{}]".format(work_seq_id)) + + except Exception as e: + logger.warning("Exception in start_mining") + logger.exception(e) + + logger.debug('start_mining - UNLOCKED') + + def handleEvent(self, event): + # NOTE: This function usually runs in the context of a C++ thread + if event.type == SOLUTION: + logger.debug('handleEvent - TRY LOCK') + if not self.lock.acquire(blocking=False): + logger.debug('handleEvent - SKIP') + return False + + try: + logger.debug('handleEvent - LOCKED') + + logger.debug('Solution Found %s', event.nonce) + logger.info('Hash Rate: %s H/s', self.hashRate()) + cloned_block = copy.deepcopy(self._mining_block) + cloned_block.set_nonces(self._dev_config, event.nonce, 0) + logger.debug("Blob %s", cloned_block) + logger.info('Block #%s nonce: %s', cloned_block.block_number, event.nonce) + self._pre_block_logic(cloned_block) + except Exception as e: + logger.warning("Exception in solutionEvent") + logger.exception(e) + finally: + logger.debug('handleEvent - UNLOCK') + self.lock.release() + + return True diff --git a/src/qrl/core/miners/qrandomx/QRXPoWValidator.py b/src/qrl/core/miners/qrandomx/QRXPoWValidator.py new file mode 100644 index 000000000..4f338c1af --- /dev/null +++ b/src/qrl/core/miners/qrandomx/QRXPoWValidator.py @@ -0,0 +1,23 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import functools +import threading + +from pyqrandomx.pyqrandomx import PoWHelper + +from qrl.core.Singleton import Singleton + + +class QRXPoWValidator(object, metaclass=Singleton): + def __init__(self): + self.lock = threading.Lock() + self._powv = PoWHelper() + + def verify_input(self, block_number, seed_height, seed_hash, mining_blob, target): + return self._verify_input_cached(block_number, seed_height, seed_hash, mining_blob, target) + + @functools.lru_cache(maxsize=5) + def _verify_input_cached(self, block_number: int, seed_height: int, + seed_hash: bytes, mining_blob: bytes, target: bytes): + return self._powv.verifyInput(block_number, seed_height, seed_hash, mining_blob, target) diff --git a/src/qrl/core/miners/qrandomx/__init__.py b/src/qrl/core/miners/qrandomx/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/qrl/core/miners/qryptonight7/CNv1Miner.py b/src/qrl/core/miners/qryptonight7/CNv1Miner.py new file mode 100644 index 000000000..cbecf76d8 --- /dev/null +++ b/src/qrl/core/miners/qryptonight7/CNv1Miner.py @@ -0,0 +1,84 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import copy +import threading + +from pyqryptonight.pyqryptonight import Qryptominer, SOLUTION + +from qrl.core.config import DevConfig, user as user_config +from qrl.core.Block import Block +from qrl.core.misc import logger + + +class CNv1Miner(Qryptominer): + def __init__(self, + pre_block_logic, + mining_address: bytes, + mining_thread_count): + super().__init__() + + self.pre_block_logic = pre_block_logic # FIXME: Circular dependency with node.py + + self._mining_address = mining_address + self._mining_thread_count = mining_thread_count + + self._mining_block = None + self.setForcedSleep(user_config.mining_pause) + self._dev_config = None + self.lock = threading.RLock() + + def start_mining(self, + mining_block: Block, + current_target: bytes, + dev_config: DevConfig): + try: + logger.debug('start_mining - TRY LOCK') + with self.lock: + logger.debug('start_mining - LOCKED') + self.cancel() + + mining_blob = mining_block.mining_blob(dev_config) + nonce_offset = mining_block.mining_nonce_offset(dev_config) + + self._dev_config = dev_config + self._mining_block = mining_block + work_seq_id = self.start(input=mining_blob, + nonceOffset=nonce_offset, + target=current_target, + thread_count=self._mining_thread_count) + + logger.debug("MINING START [{}]".format(work_seq_id)) + + except Exception as e: + logger.warning("Exception in start_mining") + logger.exception(e) + + logger.debug('start_mining - UNLOCKED') + + def handleEvent(self, event): + # NOTE: This function usually runs in the context of a C++ thread + if event.type == SOLUTION: + logger.debug('handleEvent - TRY LOCK') + if not self.lock.acquire(blocking=False): + logger.debug('handleEvent - SKIP') + return False + + try: + logger.debug('handleEvent - LOCKED') + + logger.debug('Solution Found %s', event.nonce) + logger.info('Hash Rate: %s H/s', self.hashRate()) + cloned_block = copy.deepcopy(self._mining_block) + cloned_block.set_nonces(self._dev_config, event.nonce, 0) + logger.debug("Blob %s", cloned_block) + logger.info('Block #%s nonce: %s', cloned_block.block_number, event.nonce) + self.pre_block_logic(cloned_block) + except Exception as e: + logger.warning("Exception in solutionEvent") + logger.exception(e) + finally: + logger.debug('handleEvent - UNLOCK') + self.lock.release() + + return True diff --git a/src/qrl/core/miners/qryptonight7/CNv1PoWValidator.py b/src/qrl/core/miners/qryptonight7/CNv1PoWValidator.py new file mode 100644 index 000000000..3a30913df --- /dev/null +++ b/src/qrl/core/miners/qryptonight7/CNv1PoWValidator.py @@ -0,0 +1,22 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import functools +import threading + +from pyqryptonight.pyqryptonight import PoWHelper + +from qrl.core.Singleton import Singleton + + +class CNv1PoWValidator(object, metaclass=Singleton): + def __init__(self): + self.lock = threading.Lock() + self._powv = PoWHelper() + + def verify_input(self, mining_blob, target): + return self._verify_input_cached(mining_blob, target) + + @functools.lru_cache(maxsize=5) + def _verify_input_cached(self, mining_blob, target): + return self._powv.verifyInput(mining_blob, target) diff --git a/src/qrl/core/miners/qryptonight7/__init__.py b/src/qrl/core/miners/qryptonight7/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/qrl/core/misc/db.py b/src/qrl/core/misc/db.py index 24b80e863..2ef62ef5d 100644 --- a/src/qrl/core/misc/db.py +++ b/src/qrl/core/misc/db.py @@ -3,7 +3,7 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. # leveldb code for maintaining account state data -import leveldb +import plyvel import os from qrl.core import config @@ -13,14 +13,31 @@ class DB: - def __init__(self): + def __init__(self, db_dir=None): self.db_dir = os.path.join(config.user.data_dir, config.dev.db_name) + if db_dir: + self.db_dir = db_dir logger.info('DB path: %s', self.db_dir) os.makedirs(self.db_dir, exist_ok=True) - # TODO: leveldb python module is not very active. Decouple and replace - self.db = leveldb.LevelDB(self.db_dir) + try: + self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5 * 1024) + except Exception: + self.db = plyvel.DB(self.db_dir, + max_open_files=1000, + lru_cache_size=5 * 1024, + create_if_missing=True, + compression='snappy') + self.db.put(b'state_version', str(1).encode()) + + def close(self): + del self.db + + def open(self, db_dir=None): + if db_dir: + self.db_dir = db_dir + self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5*1024) def RangeIter(self, key_obj_start, key_obj_end): if not isinstance(key_obj_start, bytes): @@ -36,23 +53,106 @@ def get_db_keys(self, include_value: bool): def delete(self, key_obj: bytes, batch=None): if batch: - batch.Delete(key_obj) + batch.delete(key_obj) else: - self.db.Delete(key_obj) + self.db.delete(key_obj) def put_raw(self, key, value, batch=None): if batch: - batch.Put(key, value) + batch.put(key, value) else: - self.db.Put(key, value) + self.db.put(key, value) def get_raw(self, key): if isinstance(key, str): key = bytes(key, 'utf-8') - return self.db.Get(key) + value = self.db.get(key) + if value is None: + raise KeyError + return value def get_batch(self): - return leveldb.WriteBatch() - - def write_batch(self, batch): - self.db.Write(batch, sync=True) + return self.db.write_batch() + + def write_batch(self, batch, sync=True): + batch.write() + + + + + +# +# +# +# +# +# # coding=utf-8 +# # Distributed under the MIT software license, see the accompanying +# # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +# +# # leveldb code for maintaining account state data +# #import leveldb +# import plyvel +# import os +# +# from qrl.core import config +# from qrl.core.misc import logger +# +# __author__ = 'pete' +# +# +# class DB: +# def __init__(self, db_dir=None): +# self.db_dir = os.path.join(config.user.data_dir, config.dev.db_name) +# if db_dir: +# self.db_dir = db_dir +# logger.info('DB path: %s', self.db_dir) +# +# os.makedirs(self.db_dir, exist_ok=True) +# +# # TODO: leveldb python module is not very active. Decouple and replace +# #self.db = leveldb.LevelDB(self.db_dir) +# self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5*1024) +# +# def close(self): +# del self.db +# +# def open(self, db_dir=None): +# if db_dir: +# self.db_dir = db_dir +# self.db = leveldb.LevelDB(self.db_dir) +# +# def RangeIter(self, key_obj_start, key_obj_end): +# if not isinstance(key_obj_start, bytes): +# key_obj_start = key_obj_start.encode() +# +# if not isinstance(key_obj_end, bytes): +# key_obj_end = key_obj_end.encode() +# +# return self.db.RangeIter(key_obj_start, key_obj_end) +# +# def get_db_keys(self, include_value: bool): +# return self.db.RangeIter(include_value=include_value) +# +# def delete(self, key_obj: bytes, batch=None): +# if batch: +# batch.Delete(key_obj) +# else: +# self.db.Delete(key_obj) +# +# def put_raw(self, key, value, batch=None): +# if batch: +# batch.Put(key, value) +# else: +# self.db.Put(key, value) +# +# def get_raw(self, key): +# if isinstance(key, str): +# key = bytes(key, 'utf-8') +# return self.db.Get(key) +# +# def get_batch(self): +# return leveldb.WriteBatch() +# +# def write_batch(self, batch, sync=True): +# self.db.Write(batch, sync=sync) diff --git a/src/qrl/core/misc/helper.py b/src/qrl/core/misc/helper.py index 2a7a8affd..2d63768e1 100644 --- a/src/qrl/core/misc/helper.py +++ b/src/qrl/core/misc/helper.py @@ -3,7 +3,8 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from pyqrllib.pyqrllib import hstr2bin -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState def parse_hexblob(blob: str) -> bytes: @@ -15,18 +16,24 @@ def parse_hexblob(blob: str) -> bytes: return bytes(hstr2bin(blob)) -def parse_qaddress(qaddress: str) -> bytes: +def parse_qaddress(qaddress: str, check_multi_sig_address=False) -> bytes: """ Converts from a Qaddress to an Address. qaddress: 'Q' + hexstring representation of an XMSS tree's address - address: binary representation, the Q is ignored when transforming from qaddress. + check_multi_sig_address: Flag if multi sig address should be checked :param qaddress: :return: """ try: qaddress = parse_hexblob(qaddress[1:]) - if not AddressState.address_is_valid(qaddress): - raise ValueError("Invalid Addresss ", qaddress) + if not OptimizedAddressState.address_is_valid(qaddress): + print("checking for multi_sig_address ", check_multi_sig_address) + if check_multi_sig_address: + print("checking for multi_sig_address") + if not MultiSigAddressState.address_is_valid(qaddress): + raise ValueError("Invalid Addresss ", qaddress) + else: + raise ValueError("Invalid Addresss ", qaddress) except Exception as e: raise ValueError("Failed To Decode Address", e) diff --git a/src/qrl/core/misc/logger.py b/src/qrl/core/misc/logger.py index fa41819d2..50962d0a0 100644 --- a/src/qrl/core/misc/logger.py +++ b/src/qrl/core/misc/logger.py @@ -33,6 +33,7 @@ def initialize_default(force_console_output=False, log_level=logging.DEBUG): handler = logging.StreamHandler(logging_target) handler.setFormatter(logging.Formatter(LOG_FORMAT_FULL, None)) logger.addHandler(handler) + set_unhandled_exception_handler() return handler diff --git a/src/qrl/core/misc/set_logger.py b/src/qrl/core/misc/set_logger.py new file mode 100644 index 000000000..a60de08b9 --- /dev/null +++ b/src/qrl/core/misc/set_logger.py @@ -0,0 +1,51 @@ +import logging +import sys +import threading + +from qrl.core.misc import logger, logger_twisted +from qrl.core import config + +LOG_FORMAT_FULL = '%(asctime)s - %(levelname)s - %(message)s' + +LOG_FORMAT_CUSTOM = '%(asctime)s|%(version)s|%(node_state)s|%(thread_id)s| ' \ + '%(levelname)s : %(message)s' + + +class ContextFilter(logging.Filter): + def __init__(self, node_state, version): + super(ContextFilter, self).__init__() + self.node_state = node_state + self.version = version + + def filter(self, record): + record.node_state = "{:<8}".format(self.node_state.state.name) + record.version = self.version + record.thread_id = "{:<11}".format(threading.current_thread().name) + return True + + +def set_logger(args, sync_state): + log_level = logging.INFO + if args.logLevel: + log_level = getattr(logging, args.logLevel) + + logger.initialize_default(force_console_output=not args.quiet).setLevel(log_level) + custom_filter = ContextFilter(sync_state, config.dev.version) + logger.logger.addFilter(custom_filter) + file_handler = logger.log_to_file() + file_handler.addFilter(custom_filter) + file_handler.setLevel(logging.DEBUG) + logger.set_colors(not args.no_colors, LOG_FORMAT_CUSTOM) + logger.set_unhandled_exception_handler() + logger_twisted.enable_twisted_log_observer() + + +def set_logger_default(): + log_level = logging.ERROR + + logger.initialize_default(force_console_output=False).setLevel(log_level) + custom_filter = ContextFilter("TEST", config.dev.version) + logger.logger.addFilter(custom_filter) + logger.set_colors(False, LOG_FORMAT_CUSTOM) + logger.set_unhandled_exception_handler() + logger_twisted.enable_twisted_log_observer() diff --git a/src/qrl/core/node.py b/src/qrl/core/node.py index 89b4ad581..6cde3c8ed 100644 --- a/src/qrl/core/node.py +++ b/src/qrl/core/node.py @@ -45,11 +45,10 @@ def __init__(self, self.p2p_factory = p2p_factory # FIXME: Decouple from p2pFactory. Comms vs node logic self.p2p_factory.pow = self # FIXME: Temporary hack to keep things working while refactoring - self.miner = Miner(self.pre_block_logic, + self.miner = Miner(self.chain_manager, + self.pre_block_logic, self.mining_address, - self.chain_manager, - mining_thread_count, - self.p2p_factory.add_unprocessed_txn) + mining_thread_count) ######## @@ -208,7 +207,8 @@ def process_future_blocks(self): keys = list(self.future_blocks.keys()) for key in keys: block = self.future_blocks[key] - if block.is_future_block(): + dev_config = self.chain_manager.get_config_by_block_number(block.block_number) + if block.is_future_block(dev_config): return self.pre_block_logic(block) del self.future_blocks[key] @@ -220,13 +220,14 @@ def pre_block_logic(self, block: Block): if not block.validate(self.chain_manager, self.future_blocks): logger.warning('Block Validation failed for #%s %s', block.block_number, bin2hstr(block.headerhash)) - return + return False - if block.is_future_block(): + dev_config = self.chain_manager.get_config_by_block_number(block.block_number) + if block.is_future_block(dev_config): delay = abs(block.timestamp - ntp.getTime()) + 1 reactor.callLater(delay, self.process_future_blocks) self.add_future_block(block) - return + return True logger.debug('Inside add_block') result = self.chain_manager.add_block(block) @@ -240,11 +241,13 @@ def pre_block_logic(self, block: Block): if not result: logger.debug('Block Rejected %s %s', block.block_number, bin2hstr(block.headerhash)) - return + return False reactor.callLater(0, self.broadcast_block, block) logger.debug('LOCK - RELEASE - pre_block_logic') + return result + def broadcast_block(self, block): if self.sync_state.state == ESyncState.synced: self.p2p_factory.broadcast_block(block) @@ -263,9 +266,13 @@ def _mine_next(self, parent_block): logger.debug('try get_block_metadata') parent_metadata = self.chain_manager.get_block_metadata(parent_block.headerhash) logger.debug('try prepare_next_unmined_block_template') + dev_config = self.chain_manager.get_config_by_block_number(parent_block.block_number + 1) self.miner.prepare_next_unmined_block_template(mining_address=self.mining_address, tx_pool=self.chain_manager.tx_pool, parent_block=parent_block, - parent_difficulty=parent_metadata.block_difficulty) + parent_difficulty=parent_metadata.block_difficulty, + dev_config=dev_config) logger.info('Mining Block #%s', parent_block.block_number + 1) - self.miner.start_mining(parent_block, parent_metadata.block_difficulty) + self.miner.start_mining(parent_block, + parent_metadata.block_difficulty, + dev_config) diff --git a/src/qrl/core/p2p/p2pTxManagement.py b/src/qrl/core/p2p/p2pTxManagement.py index ace26e440..ea5d0b062 100644 --- a/src/qrl/core/p2p/p2pTxManagement.py +++ b/src/qrl/core/p2p/p2pTxManagement.py @@ -23,6 +23,9 @@ def new_channel(self, channel): channel.register(qrllegacy_pb2.LegacyMessage.MT, self.handle_message_transaction) channel.register(qrllegacy_pb2.LegacyMessage.LT, self.handle_lattice) channel.register(qrllegacy_pb2.LegacyMessage.SL, self.handle_slave) + channel.register(qrllegacy_pb2.LegacyMessage.MC, self.handle_multi_sig_create) + channel.register(qrllegacy_pb2.LegacyMessage.MS, self.handle_multi_sig_spend) + channel.register(qrllegacy_pb2.LegacyMessage.MV, self.handle_multi_sig_vote) @staticmethod def handle_message_received(source, message: qrllegacy_pb2.LegacyMessage): @@ -210,3 +213,63 @@ def handle_slave(source, message: qrllegacy_pb2.LegacyMessage): if source.factory.master_mr.isRequested(tx.get_message_hash(), source): source.factory.add_unprocessed_txn(tx, source.peer.ip) + + @staticmethod + def handle_multi_sig_create(source, message: qrllegacy_pb2.LegacyMessage): + """ + Handles Multi Sig Transaction + :param source: + :param message: + :return: + """ + P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.MC) + try: + tx = Transaction.from_pbdata(message.mcData) + except Exception as e: + logger.error('multi_sig_create txn rejected - unable to decode serialised data - closing connection') + logger.exception(e) + source.loseConnection() + return + + if source.factory.master_mr.isRequested(tx.get_message_hash(), source): + source.factory.add_unprocessed_txn(tx, source.peer.ip) + + @staticmethod + def handle_multi_sig_spend(source, message: qrllegacy_pb2.LegacyMessage): + """ + Handles Multi Sig Transaction + :param source: + :param message: + :return: + """ + P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.MS) + try: + tx = Transaction.from_pbdata(message.msData) + except Exception as e: + logger.error('multi_sig_spend txn rejected - unable to decode serialised data - closing connection') + logger.exception(e) + source.loseConnection() + return + + if source.factory.master_mr.isRequested(tx.get_message_hash(), source): + source.factory.add_unprocessed_txn(tx, source.peer.ip) + + @staticmethod + def handle_multi_sig_vote(source, message: qrllegacy_pb2.LegacyMessage): + """ + Handles Multi Sig Transaction + :param source: + :param message: + :return: + """ + P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.MV) + try: + tx = Transaction.from_pbdata(message.mvData) + except Exception as e: + logger.error('multi_sig_vote txn rejected - unable to decode serialised data - closing connection') + logger.exception(e) + source.loseConnection() + return + + if source.factory.master_mr.isRequested(tx.get_message_hash(), source): + source.factory.add_unprocessed_txn(tx, source.peer.ip) diff --git a/src/qrl/core/p2p/p2pfactory.py b/src/qrl/core/p2p/p2pfactory.py index cfb9781ae..860093bc4 100644 --- a/src/qrl/core/p2p/p2pfactory.py +++ b/src/qrl/core/p2p/p2pfactory.py @@ -20,9 +20,13 @@ from qrl.core.processors.TxnProcessor import TxnProcessor from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.core.txs.SlaveTransaction import SlaveTransaction +from qrl.core.txs.LatticeTransaction import LatticeTransaction from qrl.core.txs.TokenTransaction import TokenTransaction from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction from qrl.core.txs.TransferTransaction import TransferTransaction +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote from qrl.generated import qrllegacy_pb2, qrl_pb2 p2p_msg_priority = { @@ -53,6 +57,10 @@ qrllegacy_pb2.LegacyMessage.CHAINSTATE: 0, qrllegacy_pb2.LegacyMessage.HEADERHASHES: 1, qrllegacy_pb2.LegacyMessage.P2P_ACK: 0, + + qrllegacy_pb2.LegacyMessage.MC: 1, + qrllegacy_pb2.LegacyMessage.MS: 1, + qrllegacy_pb2.LegacyMessage.MV: 1, } @@ -402,6 +410,14 @@ def broadcast_tx(self, tx: TransferTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.TT elif isinstance(tx, SlaveTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.SL + elif isinstance(tx, LatticeTransaction): + legacy_type = qrllegacy_pb2.LegacyMessage.LT + elif isinstance(tx, MultiSigCreate): + legacy_type = qrllegacy_pb2.LegacyMessage.MC + elif isinstance(tx, MultiSigSpend): + legacy_type = qrllegacy_pb2.LegacyMessage.MS + elif isinstance(tx, MultiSigVote): + legacy_type = qrllegacy_pb2.LegacyMessage.MV else: raise ValueError('Invalid Transaction Type') self.register_and_broadcast(legacy_type, tx.get_message_hash(), tx.pbdata) diff --git a/src/qrl/core/processors/TxnProcessor.py b/src/qrl/core/processors/TxnProcessor.py index abe51ed49..2da0b1eab 100644 --- a/src/qrl/core/processors/TxnProcessor.py +++ b/src/qrl/core/processors/TxnProcessor.py @@ -8,6 +8,8 @@ from qrl.core.TransactionPool import TransactionPool from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction +from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction +from qrl.core.txs.SlaveTransaction import SlaveTransaction class TxnProcessor: @@ -30,27 +32,7 @@ def __next__(self): tx, timestamp = tx_timestamp - if not tx.validate(): - return False - - addr_from_state = self.chain_manager.get_address_state(address=tx.addr_from) - addr_from_pk_state = addr_from_state - - addr_from_pk = Transaction.get_slave(tx) - if addr_from_pk: - addr_from_pk_state = self.chain_manager.get_address_state(address=addr_from_pk) - - is_valid_state = tx.validate_extended(addr_from_state=addr_from_state, - addr_from_pk_state=addr_from_pk_state) - - if not is_valid_state: - logger.info('>>>TX %s failed is_valid_state', bin2hstr(tx.txhash)) - return False - - is_valid_pool_state = tx.validate_transaction_pool(self.transaction_pool_obj.transaction_pool) - - if not is_valid_pool_state: - logger.info('>>>TX %s failed is_valid_pool_state', bin2hstr(tx.txhash)) + if not self.chain_manager.validate_all(tx, check_nonce=False): return False logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash)) diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 9e2b83d24..f31eb448c 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -8,7 +8,8 @@ from twisted.internet import reactor from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.Block import Block from qrl.core.ChainManager import ChainManager from qrl.core.ESyncState import ESyncState @@ -20,6 +21,10 @@ from qrl.core.p2p.p2pTxManagement import P2PTxManagement from qrl.core.p2p.p2pfactory import P2PFactory from qrl.core.txs.CoinBase import CoinBase +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote +from qrl.core.txs.LatticeTransaction import LatticeTransaction from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.core.txs.SlaveTransaction import SlaveTransaction from qrl.core.txs.TokenTransaction import TokenTransaction @@ -115,9 +120,10 @@ def block_time_mean(self): prev_block_metadata = self._chain_manager.get_block_metadata(block.prev_headerhash) if prev_block_metadata is None: - return config.dev.mining_setpoint_blocktime + return config.dev.block_timing_in_seconds - movavg = self._chain_manager.get_measurement(block.timestamp, + movavg = self._chain_manager.get_measurement(config.dev, + block.timestamp, block.prev_headerhash, prev_block_metadata) return movavg @@ -215,12 +221,56 @@ def validate_amount(amount_str: str) -> bool: #################################################### #################################################### + @staticmethod + def create_multi_sig_txn(signatories: list, + weights: list, + threshold: int, + fee: int, + xmss_pk: bytes, + master_addr: bytes): + return MultiSigCreate.create(signatories=signatories, + weights=weights, + threshold=threshold, + fee=fee, + xmss_pk=xmss_pk, + master_addr=master_addr) + + @staticmethod + def create_multi_sig_spend_txn(multi_sig_address: bytes, + addrs_to: list, + amounts: list, + expiry_block_number: int, + fee: int, + xmss_pk: bytes, + master_addr: bytes): + return MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=addrs_to, + amounts=amounts, + expiry_block_number=expiry_block_number, + fee=fee, + xmss_pk=xmss_pk, + master_addr=master_addr) + + @staticmethod + def create_multi_sig_vote_txn(shared_key: bytes, + unvote: bool, + fee: int, + xmss_pk: bytes, + master_addr: bytes): + return MultiSigVote.create(shared_key=shared_key, + unvote=unvote, + fee=fee, + xmss_pk=xmss_pk, + master_addr=master_addr) + @staticmethod def create_message_txn(message_hash: bytes, + addr_to: bytes, fee: int, xmss_pk: bytes, master_addr: bytes): return MessageTransaction.create(message_hash=message_hash, + addr_to=addr_to, fee=fee, xmss_pk=xmss_pk, master_addr=master_addr) @@ -260,6 +310,7 @@ def create_transfer_token_txn(addrs_to: list, def create_send_tx(self, addrs_to: list, amounts: list, + message_data: bytes, fee: int, xmss_pk: bytes, master_addr: bytes) -> TransferTransaction: @@ -270,6 +321,7 @@ def create_send_tx(self, return TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, + message_data=message_data, fee=fee, xmss_pk=xmss_pk, master_addr=master_addr) @@ -286,6 +338,22 @@ def create_slave_tx(self, xmss_pk=xmss_pk, master_addr=master_addr) + def create_lattice_tx(self, + pk1: bytes, + pk2: bytes, + pk3: bytes, + pk4: bytes, + fee: int, + xmss_pk: bytes, + master_addr: bytes) -> LatticeTransaction: + return LatticeTransaction.create(pk1=pk1, + pk2=pk2, + pk3=pk3, + pk4=pk4, + fee=fee, + xmss_pk=xmss_pk, + master_addr=master_addr) + # FIXME: Rename this appropriately def submit_send_tx(self, tx) -> bool: if tx is None: @@ -304,27 +372,158 @@ def get_addr_from(xmss_pk, master_addr): return bytes(QRLHelper.getAddress(xmss_pk)) def get_address_is_used(self, address: bytes) -> bool: - if not AddressState.address_is_valid(address): + if not OptimizedAddressState.address_is_valid(address): raise ValueError("Invalid Address") return self._chain_manager.get_address_is_used(address) - def get_address_state(self, address: bytes) -> AddressState: - if address != config.dev.coinbase_address and not AddressState.address_is_valid(address): + def get_address_state(self, address: bytes) -> OptimizedAddressState: + if address != config.dev.coinbase_address and not OptimizedAddressState.address_is_valid(address): raise ValueError("Invalid Address") - address_state = self._chain_manager.get_address_state(address) + address_state = self._chain_manager.get_optimized_address_state(address) return address_state + def get_multi_sig_address_state(self, address: bytes) -> MultiSigAddressState: + if not MultiSigAddressState.address_is_valid(address): + raise ValueError("Invalid Address") + + multi_sig_address_state = self._chain_manager.get_multi_sig_address_state(address) + + return multi_sig_address_state + + def get_ots(self, address: bytes, page_from: int, page_count: int, unused_ots_index_from: int) -> (list, Optional[int], bool): + bitfields = list() + for page in range(page_from, page_from + page_count): + bitfield = self._chain_manager.get_bitfield(address, page) + bitfields.append(qrl_pb2.OTSBitfieldByPage(ots_bitfield=bitfield, page_number=page)) + + unused_ots_index = self._chain_manager.get_unused_ots_index2(address, unused_ots_index_from) + unused_ots_index_found = unused_ots_index is not None + + return bitfields, unused_ots_index, unused_ots_index_found + + def is_slave(self, master_address: bytes, slave_pk: bytes): + return self._chain_manager.is_slave(master_address, slave_pk) + def get_all_address_state(self) -> list: return self._chain_manager.get_all_address_state() - def get_transactions_by_address(self, address: bytes): - address_state = self._chain_manager.get_address_state(address) + def _load_transaction_hashes(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.transaction_hash_count() - item_per_page * page_number) + end_item_index = min(address_state.transaction_hash_count(), start_item_index + item_per_page) + + transaction_hashes = self._chain_manager.get_transaction_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + transaction_hashes.extend(self._chain_manager.get_transaction_hashes(address, + actual_start_item_index)) + return transaction_hashes[:item_per_page][-1::-1] + + def _load_multi_sig_spend_txn_hashes(self, + address: bytes, + item_per_page: int, + page_number: int, + mode: int) -> list: + if OptimizedAddressState.address_is_valid(address): + address_state = self._chain_manager.get_optimized_address_state(address) + elif MultiSigAddressState.address_is_valid(address): + address_state = self._chain_manager.get_multi_sig_address_state(address) + else: + return [] + + start_item_index = max(0, address_state.multi_sig_spend_count() - item_per_page * page_number) + end_item_index = min(address_state.multi_sig_spend_count(), start_item_index + item_per_page) + + if mode > 0: + start_item_index = 0 + end_item_index = address_state.multi_sig_spend_count() + + transaction_hashes = self._chain_manager.get_multi_sig_spend_txn_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + multi_sig_spend_txn_hashes = transaction_hashes[start_item_index - actual_start_item_index:] + while actual_start_item_index < end_item_index and len(multi_sig_spend_txn_hashes) < item_per_page: + actual_start_item_index += config.dev.data_per_page + multi_sig_spend_txn_hashes.extend(self._chain_manager.get_multi_sig_spend_txn_hashes(address, + actual_start_item_index)) + return multi_sig_spend_txn_hashes[:item_per_page][-1::-1] + + def _load_token_transaction_hashes(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.tokens_count() - item_per_page * page_number) + end_item_index = min(address_state.tokens_count(), start_item_index + item_per_page) + + transaction_hashes = self._chain_manager.get_token_transaction_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + token_transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + token_transaction_hashes.extend(self._chain_manager.get_token_transaction_hashes(address, + actual_start_item_index)) + return token_transaction_hashes[:item_per_page][-1::-1] + + def _load_slave_transaction_hashes(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.slaves_count() - item_per_page * page_number) + end_item_index = min(address_state.slaves_count(), start_item_index + item_per_page) + + if start_item_index < 0: + return [] + + transaction_hashes = self._chain_manager.get_slave_transaction_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + token_transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + token_transaction_hashes.extend(self._chain_manager.get_slave_transaction_hashes(address, + actual_start_item_index)) + return token_transaction_hashes[:item_per_page][-1::-1] + + def _load_lattice_pks_transaction_hashes(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.lattice_pk_count() - item_per_page * page_number) + end_item_index = min(address_state.lattice_pk_count(), start_item_index + item_per_page) + + transaction_hashes = self._chain_manager.get_lattice_pks_transaction_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + lattice_pks_transaction_hashes = transaction_hashes[start_item_index - actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + lattice_pks_transaction_hashes.extend(self._chain_manager.get_lattice_pks_transaction_hashes(address, + actual_start_item_index)) + return lattice_pks_transaction_hashes[:item_per_page][-1::-1] + + def _load_multi_sig_addresses(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.multi_sig_address_count() - item_per_page * page_number) + end_item_index = min(address_state.multi_sig_address_count(), start_item_index + item_per_page) + + multi_sig_addresses = self._chain_manager.get_multi_sig_addresses(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + multi_sig_addresses = multi_sig_addresses[start_item_index - actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + multi_sig_addresses.extend(self._chain_manager.get_multi_sig_addresses(address, + actual_start_item_index)) + return multi_sig_addresses[:item_per_page][-1::-1] + + def get_mini_transactions_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page == 0: + return None mini_transactions = [] - balance = 0 - for tx_hash in address_state.transaction_hashes: + transaction_hashes = self._load_transaction_hashes(address, item_per_page, page_number) + response = qrl_pb2.GetMiniTransactionsByAddressResp() + for tx_hash in transaction_hashes: mini_transaction = qrl_pb2.MiniTransaction() mini_transaction.transaction_hash = bin2hstr(tx_hash) tx, _ = self._chain_manager.get_tx_metadata(tx_hash) @@ -348,9 +547,154 @@ def get_transactions_by_address(self, address: bytes): mini_transaction.out = True mini_transaction.amount = abs(amount) mini_transactions.append(mini_transaction) - balance += amount - return mini_transactions, balance + response.mini_transactions.extend(mini_transactions) + response.balance = self._chain_manager.get_address_balance(address) + return response + + def get_transactions_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page == 0: + return None + transaction_hashes = self._load_transaction_hashes(address, + item_per_page, + page_number) + + response = qrl_pb2.GetTransactionsByAddressResp() + for tx_hash in transaction_hashes: + tx, block_number = self._chain_manager.get_tx_metadata(tx_hash) + b = self.get_block_from_index(block_number) + transaction_detail = qrl_pb2.GetTransactionResp(tx=tx.pbdata, + confirmations=self.block_height - block_number + 1, + block_number=block_number, + block_header_hash=b.headerhash, + timestamp=b.timestamp, + addr_from=tx.addr_from) + response.transactions_detail.extend([transaction_detail]) + + return response + + def get_multi_sig_spend_txs_by_address(self, + address: bytes, + item_per_page: int, + page_number: int, + filter_type: int): + # filter_type = 0 | No Filter (default) + # filter_type = 1 | Executed Only (All executed are considered to be expired) + # filter_type = 2 | Non Executed + # filter_type = 3 | Expired + # filter_type = 4 | Non Expired + # filter_type = 5 | Non Executed & Expired + # filter_type = 6 | Non Executed & Non Expired + + if item_per_page == 0: + return None + + transaction_hashes = self._load_multi_sig_spend_txn_hashes(address, + item_per_page, + page_number, + filter_type) + + response = qrl_pb2.GetMultiSigSpendTxsByAddressResp() + + for tx_hash in transaction_hashes: + if filter_type in (1, 2, 5, 6): + vote_stats = self._chain_manager.get_vote_stats(tx_hash) + if filter_type == 1 and not vote_stats.executed: + continue + if filter_type in (2, 5, 6) and vote_stats.executed: + continue + tx, block_number = self._chain_manager.get_tx_metadata(tx_hash) + + current_block_number = self._chain_manager.height + + is_expired = tx.expiry_block_number <= current_block_number + if filter_type in (4, 6): + if is_expired: + continue + + if filter_type in (3, 5): + if not is_expired: + continue + + b = self.get_block_from_index(block_number) + transaction_detail = qrl_pb2.GetTransactionResp(tx=tx.pbdata, + confirmations=self.block_height - block_number + 1, + block_number=block_number, + block_header_hash=b.headerhash, + timestamp=b.timestamp, + addr_from=tx.addr_from) + response.transactions_detail.extend([transaction_detail]) + + return response + + def get_vote_stats(self, multi_sig_spend_tx_hash: bytes): + vote_stats = self._chain_manager.get_vote_stats(multi_sig_spend_tx_hash) + return qrl_pb2.GetVoteStatsResp(vote_stats=vote_stats) + + def get_tokens_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page == 0: + return None + token_hashes = self._load_token_transaction_hashes(address, item_per_page, page_number) + + response = qrl_pb2.GetTokensByAddressResp() + for tx_hash in token_hashes: + tx, _ = self._chain_manager.get_tx_metadata(tx_hash) + balance = self._chain_manager.get_token(address, tx.txhash) + transaction_detail = qrl_pb2.TokenDetail(token_txhash=tx.txhash, + name=tx.name, + symbol=tx.symbol, + balance=balance) + response.tokens_detail.extend([transaction_detail]) + + return response + + def get_slaves_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page > config.dev.data_per_page or item_per_page == 0: + return None + slave_hashes = self._load_slave_transaction_hashes(address, item_per_page, page_number) + + response = qrl_pb2.GetSlavesByAddressResp() + for tx_hash in slave_hashes: + tx, _ = self._chain_manager.get_tx_metadata(tx_hash) + for index in range(0, len(tx.slave_pks)): + transaction_detail = qrl_pb2.SlaveDetail(slave_address=bytes(QRLHelper.getAddress(tx.slave_pks[index])), + access_type=tx.access_types[index]) + response.slaves_detail.extend([transaction_detail]) + + return response + + def get_lattice_pks_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page > config.dev.data_per_page or item_per_page == 0: + return None + lattice_pk_hashes = self._load_lattice_pks_transaction_hashes(address, item_per_page, page_number) + + response = qrl_pb2.GetLatticePKsByAddressResp() + for tx_hash in lattice_pk_hashes: + tx, _ = self._chain_manager.get_tx_metadata(tx_hash) + transaction_detail = qrl_pb2.LatticePKsDetail(pk1=tx.pk1, + pk2=tx.pk2, + pk3=tx.pk3, + pk4=tx.pk4) + response.lattice_pks_detail.extend([transaction_detail]) + + return response + + def get_multi_sig_addresses_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page > config.dev.data_per_page or item_per_page == 0: + return None + multi_sig_addresses = self._load_multi_sig_addresses(address, + item_per_page, + page_number) + + response = qrl_pb2.GetMultiSigAddressesByAddressResp() + for multi_sig_address in multi_sig_addresses: + multi_sig_detail = qrl_pb2.MultiSigDetail( + address=multi_sig_address, + balance=self._chain_manager.get_multi_sig_address_state(multi_sig_address).balance, + ) + response.multi_sig_detail.extend([multi_sig_detail]) + + return response def get_transaction(self, query_hash: bytes): """ diff --git a/src/qrl/core/txs/CoinBase.py b/src/qrl/core/txs/CoinBase.py index 11a7f4517..08ed821da 100644 --- a/src/qrl/core/txs/CoinBase.py +++ b/src/qrl/core/txs/CoinBase.py @@ -1,7 +1,9 @@ from pyqrllib.pyqrllib import bin2hstr -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.config import DevConfig +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction @@ -31,9 +33,9 @@ def get_data_bytes(self): self.amount.to_bytes(8, byteorder='big', signed=False) @staticmethod - def create(amount, miner_address, block_number): + def create(dev_config: DevConfig, amount, miner_address, block_number): transaction = CoinBase() - transaction._data.master_addr = config.dev.coinbase_address + transaction._data.master_addr = dev_config.coinbase_address transaction._data.coinbase.addr_to = miner_address transaction._data.coinbase.amount = amount transaction._data.nonce = block_number + 1 @@ -65,46 +67,57 @@ def _validate_custom(self): return True # noinspection PyBroadException - def validate_extended(self, block_number: int): - if self.master_addr != config.dev.coinbase_address: + # Never change this function name to _validate_extended, to keep difference between other txns & + # Coinbase txn, will hit unimplemented error in case called for an coinbase txn. + def validate_extended(self, block_number, dev_config: DevConfig): + if self.master_addr != dev_config.coinbase_address: logger.warning('Master address doesnt match with coinbase_address') - logger.warning('%s %s', bin2hstr(self.master_addr), bin2hstr(config.dev.coinbase_address)) + logger.warning('%s %s', bin2hstr(self.master_addr), bin2hstr(dev_config.coinbase_address)) return False - if not AddressState.address_is_valid(self.addr_to): - logger.warning('Invalid address addr_from: %s addr_to: %s', bin2hstr(self.master_addr), bin2hstr(self.addr_to)) + if not OptimizedAddressState.address_is_valid(self.addr_to): + logger.warning('Invalid address addr_from: %s addr_to: %s', + bin2hstr(self.master_addr), bin2hstr(self.addr_to)) return False if self.nonce != block_number + 1: - logger.warning('Nonce %s doesnt match with block_number %s', self.nonce, block_number) + logger.warning('Nonce %s doesnt match with block_number %s', + self.nonce, block_number) return False return self._validate_custom() - def apply_state_changes(self, addresses_state): - if self.addr_to in addresses_state: - addresses_state[self.addr_to].balance += self.amount - addresses_state[self.addr_to].transaction_hashes.append(self.txhash) + def _validate_extended(self, state_container: StateContainer): + raise Exception("Should not be called for a Coinbase Transaction") - addr_from = config.dev.coinbase_address + def set_affected_address(self, addresses_set: set): + addresses_set.add(self.master_addr) + addresses_set.add(self.addr_to) - if self.master_addr in addresses_state: - addresses_state[self.master_addr].balance -= self.amount - addresses_state[self.master_addr].transaction_hashes.append(self.txhash) - addresses_state[addr_from].increase_nonce() + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_to] + address_state.update_balance(state_container, self.amount) + state_container.paginated_tx_hash.insert(address_state, self.txhash) - def revert_state_changes(self, addresses_state, chain_manager): - if self.addr_to in addresses_state: - addresses_state[self.addr_to].balance -= self.amount - addresses_state[self.addr_to].transaction_hashes.remove(self.txhash) + address_state = state_container.addresses_state[self.master_addr] + address_state.update_balance(state_container, self.amount, subtract=True) + address_state.increase_nonce() + state_container.paginated_tx_hash.insert(address_state, self.txhash) - addr_from = config.dev.coinbase_address + return True - if self.master_addr in addresses_state: - addresses_state[self.master_addr].balance += self.amount - addresses_state[self.master_addr].transaction_hashes.remove(self.txhash) - addresses_state[addr_from].decrease_nonce() + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_to] + address_state.update_balance(state_container, self.amount, subtract=True) + state_container.paginated_tx_hash.remove(address_state, self.txhash) - def set_affected_address(self, addresses_set: set): - addresses_set.add(self.master_addr) - addresses_set.add(self.addr_to) + address_state = state_container.addresses_state[self.master_addr] + address_state.update_balance(state_container, self.amount) + address_state.decrease_nonce() + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + return True diff --git a/src/qrl/core/txs/LatticeTransaction.py b/src/qrl/core/txs/LatticeTransaction.py new file mode 100644 index 000000000..a1bf77ca2 --- /dev/null +++ b/src/qrl/core/txs/LatticeTransaction.py @@ -0,0 +1,132 @@ +from pyqrllib.pyqrllib import bin2hstr + +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.txs.Transaction import Transaction +from qrl.generated.qrl_pb2 import LatticePKMetadata + + +class LatticeTransaction(Transaction): + + def __init__(self, protobuf_transaction=None): + super(LatticeTransaction, self).__init__(protobuf_transaction) + + @property + def pk1(self): # kyber_pk + return self._data.latticePK.pk1 + + @property + def pk2(self): # dilithium_pk + return self._data.latticePK.pk2 + + @property + def pk3(self): # ecdsa_pk + return self._data.latticePK.pk3 + + @property + def pk4(self): # ecies_pk + return self._data.latticePK.pk4 + + def get_data_bytes(self): + return self.master_addr + \ + self.fee.to_bytes(8, byteorder='big', signed=False) + \ + self.pk1 + \ + self.pk2 + \ + self.pk3 + \ + self.pk4 + + @staticmethod + def create(pk1: bytes, pk2: bytes, pk3: bytes, pk4: bytes, fee: int, xmss_pk: bytes, master_addr: bytes = None): + transaction = LatticeTransaction() + + if master_addr: + transaction._data.master_addr = master_addr + + transaction._data.fee = fee + transaction._data.public_key = xmss_pk + + transaction._data.latticePK.pk1 = bytes(pk1) + transaction._data.latticePK.pk2 = bytes(pk2) + transaction._data.latticePK.pk3 = bytes(pk3) + transaction._data.latticePK.pk4 = bytes(pk4) + + transaction.validate_or_raise(verify_signature=False) + + return transaction + + def _validate_custom(self) -> bool: + return True + + def _validate_extended(self, state_container: StateContainer) -> bool: + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[LatticeTransaction] Hard Fork Feature not yet activated") + return False + + dev_config = state_container.current_dev_config + if len(self.pk1) > dev_config.lattice_pk1_max_length: # TODO: to fix kyber pk value + logger.warning('Kyber PK length cannot be more than %s bytes', dev_config.lattice_pk1_max_length) + logger.warning('Found length %s', len(self.pk1)) + return False + + if len(self.pk2) > dev_config.lattice_pk2_max_length: # TODO: to fix dilithium pk value + logger.warning('Dilithium PK length cannot be more than %s bytes', dev_config.lattice_pk2_max_length) + logger.warning('Found length %s', len(self.pk2)) + return False + + if len(self.pk3) > dev_config.lattice_pk3_max_length: # TODO: to fix ecdsa pk value + logger.warning('ECDSA PK length cannot be more than %s bytes', dev_config.lattice_pk3_max_length) + logger.warning('Found length %s', len(self.pk3)) + return False + + if len(self.pk4) > dev_config.lattice_pk4_max_length: # TODO: to fix ecies pk value + logger.warning('ECIES PK length cannot be more than %s bytes', dev_config.lattice_pk4_max_length) + logger.warning('Found length %s', len(self.pk4)) + return False + + tx_balance = state_container.addresses_state[self.addr_from].balance + + if self.fee < 0: + logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) + return False + + if tx_balance < self.fee: + logger.info('State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) + logger.info('balance: %s, amount: %s', tx_balance, self.fee) + return False + + if (self.addr_from, self.pk1, self.pk2, self.pk3, self.pk4) in state_container.lattice_pk.data: + logger.info('State validation failed for %s because: Lattice PKs already exists for this address', + bin2hstr(self.txhash)) + return False + + return True + + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_lattice_pk.insert(address_state, self.txhash) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + state_container.lattice_pk.data[(self.addr_from, + self.pk1, self.pk2, self.pk3, self.pk4)] = LatticePKMetadata(enabled=True) + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_lattice_pk.remove(address_state, self.txhash) + state_container.paginated_tx_hash.remmove(address_state, self.txhash) + + state_container.lattice_pk.data[(self.addr_from, + self.pk1, self.pk2, self.pk3, self.pk4)] = LatticePKMetadata(enabled=False) + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/MessageTransaction.py b/src/qrl/core/txs/MessageTransaction.py index 0058649a9..50533b813 100644 --- a/src/qrl/core/txs/MessageTransaction.py +++ b/src/qrl/core/txs/MessageTransaction.py @@ -1,6 +1,9 @@ -from pyqrllib.pyqrllib import bin2hstr +from pyqrllib.pyqrllib import bin2hstr, QRLHelper +from typing import Union -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction @@ -14,19 +17,27 @@ def __init__(self, protobuf_transaction=None): def message_hash(self): return self._data.message.message_hash + @property + def addr_to(self): + return self._data.message.addr_to + def get_data_bytes(self): return self.master_addr + \ self.fee.to_bytes(8, byteorder='big', signed=False) + \ - self.message_hash + self.message_hash + \ + self.addr_to @staticmethod - def create(message_hash: bytes, fee: int, xmss_pk: bytes, master_addr: bytes = None): + def create(message_hash: bytes, addr_to: Union[bytes, None], fee: int, xmss_pk: bytes, master_addr: bytes = None): transaction = MessageTransaction() if master_addr: transaction._data.master_addr = master_addr transaction._data.message.message_hash = message_hash + if addr_to: + transaction._data.message.addr_to = addr_to + transaction._data.fee = fee transaction._data.public_key = xmss_pk @@ -36,22 +47,28 @@ def create(message_hash: bytes, fee: int, xmss_pk: bytes, master_addr: bytes = N return transaction def _validate_custom(self) -> bool: - if len(self.message_hash) > 80: - logger.warning('Message length cannot be more than 80') - logger.warning('Found message length %s', len(self.message_hash)) - return False - if len(self.message_hash) == 0: logger.warning('Message cannot be empty') return False + if len(self.addr_to) > 0 and not (OptimizedAddressState.address_is_valid(self.addr_to)): + logger.warning('[MessageTransaction] Invalid address addr_to: %s', bin2hstr(self.addr_to)) + return False + return True - def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: AddressState) -> bool: - if not self.validate_slave(addr_from_state, addr_from_pk_state): + def _validate_extended(self, state_container: StateContainer) -> bool: + if len(self.addr_to) != 0: + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[MessageTransaction] Hard Fork Feature not yet activated") + return False + + if len(self.message_hash) > state_container.current_dev_config.message_max_length: # TODO: Move to dev config + logger.warning('Message length cannot be more than %s', state_container.current_dev_config.message_max_length) + logger.warning('Found message length %s', len(self.message_hash)) return False - tx_balance = addr_from_state.balance + tx_balance = state_container.addresses_state[self.addr_from].balance if self.fee < 0: logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) @@ -62,22 +79,39 @@ def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: A logger.info('balance: %s, amount: %s', tx_balance, self.fee) return False - if addr_from_pk_state.ots_key_reuse(self.ots_key): - logger.info('State validation failed for %s because: OTS Public key re-use detected', bin2hstr(self.txhash)) - return False - return True - def apply_state_changes(self, addresses_state): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance -= self.fee - addresses_state[self.addr_from].transaction_hashes.append(self.txhash) - - self._apply_state_changes_for_PK(addresses_state) - - def revert_state_changes(self, addresses_state, chain_manager): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance += self.fee - addresses_state[self.addr_from].transaction_hashes.remove(self.txhash) - - self._revert_state_changes_for_PK(addresses_state, chain_manager) + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + if self.addr_to: + addresses_set.add(self.addr_to) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + if self.addr_to: + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + address_state = state_container.addresses_state[self.addr_to] + if self.addr_to not in (self.addr_from, addr_from_pk): + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + if self.addr_to: + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + address_state = state_container.addresses_state[self.addr_to] + if self.addr_to not in (self.addr_from, addr_from_pk): + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/SlaveTransaction.py b/src/qrl/core/txs/SlaveTransaction.py index 2b3a74f0a..43f9426a8 100644 --- a/src/qrl/core/txs/SlaveTransaction.py +++ b/src/qrl/core/txs/SlaveTransaction.py @@ -1,9 +1,10 @@ from pyqrllib.pyqrllib import bin2hstr -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction +from qrl.generated.qrl_pb2 import SlaveMetadata class SlaveTransaction(Transaction): @@ -50,17 +51,16 @@ def create(slave_pks: list, access_types: list, fee: int, xmss_pk: bytes, master return transaction def _validate_custom(self) -> bool: - if (len(self.slave_pks) > config.dev.transaction_multi_output_limit or - len(self.access_types) > config.dev.transaction_multi_output_limit): - logger.warning('List has more than 100 slave pks or access_types') + if len(self.slave_pks) != len(self.access_types): + logger.warning('Number of slave pks are not equal to the number of access types provided') logger.warning('Slave pks len %s', len(self.slave_pks)) logger.warning('Access types len %s', len(self.access_types)) return False - if len(self.slave_pks) != len(self.access_types): - logger.warning('Number of slave pks are not equal to the number of access types provided') + if len(set(self.slave_pks)) != len(self.slave_pks): + logger.warning('Duplicate Slave PKS found') + logger.warning('Unique Slave pks len %s', len(set(self.slave_pks))) logger.warning('Slave pks len %s', len(self.slave_pks)) - logger.warning('Access types len %s', len(self.access_types)) return False for access_type in self.access_types: @@ -68,13 +68,20 @@ def _validate_custom(self) -> bool: logger.warning('Invalid Access type %s', access_type) return False + # TODO: Add Maximum PK size limit + return True - def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: AddressState) -> bool: - if not self.validate_slave(addr_from_state, addr_from_pk_state): + def _validate_extended(self, state_container: StateContainer) -> bool: + if (len(self.slave_pks) > state_container.current_dev_config.transaction_multi_output_limit or + len(self.access_types) > state_container.current_dev_config.transaction_multi_output_limit): + logger.warning('List has more than %s slave pks or access_types', + state_container.current_dev_config.transaction_multi_output_limit) + logger.warning('Slave pks len %s', len(self.slave_pks)) + logger.warning('Access types len %s', len(self.access_types)) return False - tx_balance = addr_from_state.balance + tx_balance = state_container.addresses_state[self.addr_from].balance if self.fee < 0: logger.info('Slave: State validation failed for %s because: Negative send', bin2hstr(self.txhash)) @@ -85,28 +92,47 @@ def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: A logger.info('balance: %s, amount: %s', tx_balance, self.fee) return False - if addr_from_pk_state.ots_key_reuse(self.ots_key): - logger.info('Slave: State validation failed for %s because: OTS Public key re-use detected', - bin2hstr(self.txhash)) - return False + for i in range(len(self.slave_pks)): + slave_pk = self.slave_pks[i] + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + if len(slave_pk) > state_container.current_dev_config.slave_pk_max_length: + logger.info("[Slave Transaction] Slave PK length is beyond limit") + return False + if (self.addr_from, slave_pk) in state_container.slaves.data: + logger.info("[Slave Transaction] Invalid slave transaction as %s is already a slave for this address", + slave_pk) + return False return True - def apply_state_changes(self, addresses_state): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance -= self.fee - for index in range(0, len(self.slave_pks)): - addresses_state[self.addr_from].add_slave_pks_access_type(self.slave_pks[index], - self.access_types[index]) - addresses_state[self.addr_from].transaction_hashes.append(self.txhash) - - self._apply_state_changes_for_PK(addresses_state) - - def revert_state_changes(self, addresses_state, chain_manager): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance += self.fee - for index in range(0, len(self.slave_pks)): - addresses_state[self.addr_from].remove_slave_pks_access_type(self.slave_pks[index]) - addresses_state[self.addr_from].transaction_hashes.remove(self.txhash) - - self._revert_state_changes_for_PK(addresses_state, chain_manager) + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + for idx in range(0, len(self.slave_pks)): + state_container.slaves.data[(self.addr_from, + self.slave_pks[idx])] = SlaveMetadata(access_type=self.access_types[idx], + tx_hash=self.txhash) + state_container.paginated_slaves_hash.insert(address_state, self.txhash) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + for idx in range(0, len(self.slave_pks)): + state_container.slaves.data[(self.addr_from, + self.slave_pks[idx])] = SlaveMetadata(access_type=self.access_types[idx], + tx_hash=self.txhash, + delete=True) + state_container.paginated_slaves_hash.remove(address_state, self.txhash) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/TokenTransaction.py b/src/qrl/core/txs/TokenTransaction.py index f058ae86f..6c1a36546 100644 --- a/src/qrl/core/txs/TokenTransaction.py +++ b/src/qrl/core/txs/TokenTransaction.py @@ -1,9 +1,11 @@ from pyqrllib.pyqrllib import bin2hstr, QRLHelper -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction +from qrl.generated.qrl_pb2 import TokenBalance class TokenTransaction(Transaction): @@ -79,18 +81,6 @@ def create(symbol: bytes, return transaction def _validate_custom(self): - if len(self.symbol) > config.dev.max_token_symbol_length: - logger.warning('Token Symbol Length exceeds maximum limit') - logger.warning('Found Symbol Length %s', len(self.symbol)) - logger.warning('Expected Symbol length %s', config.dev.max_token_symbol_length) - return False - - if len(self.name) > config.dev.max_token_name_length: - logger.warning('Token Name Length exceeds maximum limit') - logger.warning('Found Name Length %s', len(self.symbol)) - logger.warning('Expected Name length %s', config.dev.max_token_name_length) - return False - if len(self.symbol) == 0: logger.warning('Missing Token Symbol') return False @@ -107,14 +97,21 @@ def _validate_custom(self): logger.warning('Token decimals cannot be more than 19') return False + addresses = set() sum_of_initial_balances = 0 for initial_balance in self.initial_balances: sum_of_initial_balances += initial_balance.amount + addresses.add(initial_balance.address) # TODO: Hard fork code, check if compatible with older blocks if initial_balance.amount <= 0: logger.warning('Invalid Initial Amount in Token Transaction') logger.warning('Address %s | Amount %s', initial_balance.address, initial_balance.amount) return False + # TODO: Hard fork code, check if compatible with older blocks + if len(addresses) != len(self.initial_balances): + logger.warning('Invalid Token Initialization. Duplicate address found initial_balance') + return False + allowed_decimals = self.calc_allowed_decimals(sum_of_initial_balances // 10 ** self.decimals) if self.decimals > allowed_decimals: @@ -129,38 +126,50 @@ def _validate_custom(self): return True # checks new tx validity based upon node statedb and node mempool. - def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: AddressState): - if not self.validate_slave(addr_from_state, addr_from_pk_state): + def _validate_extended(self, state_container: StateContainer): + if len(self.symbol) > state_container.current_dev_config.max_token_symbol_length: + logger.warning('Token Symbol Length exceeds maximum limit') + logger.warning('Found Symbol Length %s', len(self.symbol)) + logger.warning('Expected Symbol length %s', state_container.current_dev_config.max_token_symbol_length) return False - tx_balance = addr_from_state.balance + if len(self.name) > state_container.current_dev_config.max_token_name_length: + logger.warning('Token Name Length exceeds maximum limit') + logger.warning('Found Name Length %s', len(self.symbol)) + logger.warning('Expected Name length %s', state_container.current_dev_config.max_token_name_length) + return False - if not AddressState.address_is_valid(self.addr_from): + if not OptimizedAddressState.address_is_valid(self.addr_from): logger.warning('Invalid address addr_from: %s', bin2hstr(self.addr_from)) return False - if not AddressState.address_is_valid(self.owner): + tx_balance = state_container.addresses_state[self.addr_from].balance + + if not OptimizedAddressState.address_is_valid(self.owner): logger.warning('Invalid address owner_addr: %s', bin2hstr(self.owner)) return False for address_balance in self.initial_balances: - if not AddressState.address_is_valid(address_balance.address): + if not OptimizedAddressState.address_is_valid(address_balance.address): logger.warning('Invalid address in initial_balances: %s', bin2hstr(address_balance.address)) return False if tx_balance < self.fee: - logger.info('TokenTxn State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) - logger.info('balance: %s, Fee: %s', tx_balance, self.fee) - return False - - if addr_from_pk_state.ots_key_reuse(self.ots_key): - logger.info('TokenTxn State validation failed for %s because: OTS Public key re-use detected', - bin2hstr(self.txhash)) + logger.warning('TokenTxn State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) + logger.warning('balance: %s, Fee: %s', tx_balance, self.fee) return False return True - def apply_state_changes(self, addresses_state): + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + addresses_set.add(self.owner) + for initial_balance in self.initial_balances: + addresses_set.add(initial_balance.address) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) owner_processed = False addr_from_processed = False @@ -173,26 +182,37 @@ def apply_state_changes(self, addresses_state): addr_from_processed = True if initial_balance.address == addr_from_pk: addr_from_pk_processed = True - if initial_balance.address in addresses_state: - addresses_state[initial_balance.address].update_token_balance(self.txhash, initial_balance.amount) - addresses_state[initial_balance.address].transaction_hashes.append(self.txhash) - - if self.owner in addresses_state and not owner_processed: - addresses_state[self.owner].transaction_hashes.append(self.txhash) - - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance -= self.fee - if not addr_from_processed and self.addr_from != self.owner: - addresses_state[self.addr_from].transaction_hashes.append(self.txhash) - - if addr_from_pk in addresses_state: - if self.addr_from != addr_from_pk and addr_from_pk != self.owner: - if not addr_from_pk_processed: - addresses_state[addr_from_pk].transaction_hashes.append(self.txhash) - addresses_state[addr_from_pk].increase_nonce() - addresses_state[addr_from_pk].set_ots_key(self.ots_key) - - def revert_state_changes(self, addresses_state, chain_manager): + + state_container.tokens.data[(initial_balance.address, self.txhash)] = TokenBalance(balance=initial_balance.amount, + decimals=self.decimals, + delete=False) + address_state = state_container.addresses_state[initial_balance.address] + state_container.paginated_tx_hash.insert(address_state, self.txhash) + state_container.paginated_tokens_hash.insert(address_state, self.txhash) + + if not owner_processed: + address_state = state_container.addresses_state[self.owner] + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + if not addr_from_processed and self.addr_from != self.owner: + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + address_state = state_container.addresses_state[addr_from_pk] + if self.addr_from != addr_from_pk and addr_from_pk != self.owner: + if not addr_from_pk_processed: + state_container.paginated_tx_hash.insert(address_state, self.txhash) + address_state.increase_nonce() + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + addr_from_pk, + self.ots_key) + + return True + + def revert(self, + state: State, + state_container: StateContainer) -> bool: addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) owner_processed = False addr_from_processed = False @@ -205,28 +225,27 @@ def revert_state_changes(self, addresses_state, chain_manager): addr_from_processed = True if initial_balance.address == addr_from_pk: addr_from_pk_processed = True - if initial_balance.address in addresses_state: - addresses_state[initial_balance.address].update_token_balance(self.txhash, - initial_balance.amount * -1) - addresses_state[initial_balance.address].transaction_hashes.remove(self.txhash) - - if self.owner in addresses_state and not owner_processed: - addresses_state[self.owner].transaction_hashes.remove(self.txhash) - - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance += self.fee - if not addr_from_processed and self.addr_from != self.owner: - addresses_state[self.addr_from].transaction_hashes.remove(self.txhash) - - if addr_from_pk in addresses_state: - if self.addr_from != addr_from_pk and addr_from_pk != self.owner: - if not addr_from_pk_processed: - addresses_state[addr_from_pk].transaction_hashes.remove(self.txhash) - addresses_state[addr_from_pk].decrease_nonce() - addresses_state[addr_from_pk].unset_ots_key(self.ots_key, chain_manager) - def set_affected_address(self, addresses_set: set): - super().set_affected_address(addresses_set) - addresses_set.add(self.owner) - for initial_balance in self.initial_balances: - addresses_set.add(initial_balance.address) + address_state = state_container.addresses_state[initial_balance.address] + state_container.tokens.data[(initial_balance.address, self.txhash)] = TokenBalance(balance=0, + delete=True) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + state_container.paginated_tokens_hash.remove(address_state, self.txhash) + + if not owner_processed: + address_state = state_container.addresses_state[self.owner] + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + if not addr_from_processed and self.addr_from != self.owner: + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + address_state = state_container.addresses_state[addr_from_pk] + if self.addr_from != addr_from_pk and addr_from_pk != self.owner: + if not addr_from_pk_processed: + state_container.paginated_tx_hash.remove(address_state, self.txhash) + address_state.decrease_nonce() + state_container.paginated_bitfield.unset_ots_key(state_container.addresses_state, addr_from_pk, self.ots_key) + + return True diff --git a/src/qrl/core/txs/Transaction.py b/src/qrl/core/txs/Transaction.py index fa67e069f..5b2d4445e 100644 --- a/src/qrl/core/txs/Transaction.py +++ b/src/qrl/core/txs/Transaction.py @@ -9,9 +9,11 @@ from pyqrllib.pyqrllib import bin2hstr, QRLHelper, XmssFast from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.StateContainer import StateContainer from qrl.core.misc import logger -from qrl.core.txs import build_tx +from qrl.core.txs import build_tx as main_build_tx from qrl.crypto.misc import sha256 from qrl.generated import qrl_pb2 @@ -22,7 +24,10 @@ 'message': 4, 'token': 5, 'transfer_token': 6, - 'slave': 7 + 'slave': 7, + 'multi_sig_create': 8, + 'multi_sig_spend': 9, + 'multi_sig_vote': 10, } @@ -113,7 +118,7 @@ def signature(self): @staticmethod def from_pbdata(pbdata: qrl_pb2.Transaction): - return build_tx(pbdata.WhichOneof('transactionType'), pbdata) + return main_build_tx(pbdata.WhichOneof('transactionType'), pbdata) @staticmethod def from_json(json_data): @@ -160,38 +165,6 @@ def sign(self, object_with_sign_method): self._data.signature = object_with_sign_method.sign(self.get_data_hash()) self.update_txhash() - @abstractmethod - def apply_state_changes(self, addresses_state): - """ - This method, applies the changes on the state caused by txn. - :return: - """ - raise NotImplementedError - - def _apply_state_changes_for_PK(self, addresses_state: dict): - addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) - if addr_from_pk in addresses_state: - if self.addr_from != addr_from_pk: - addresses_state[addr_from_pk].transaction_hashes.append(self.txhash) - addresses_state[addr_from_pk].increase_nonce() - addresses_state[addr_from_pk].set_ots_key(self.ots_key) - - @abstractmethod - def revert_state_changes(self, addresses_state, chain_manager): - """ - This method reverts the changes on the state caused by txn. - :return: - """ - raise NotImplementedError - - def _revert_state_changes_for_PK(self, addresses_state, chain_manager): - addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) - if addr_from_pk in addresses_state: - if self.addr_from != addr_from_pk: - addresses_state[addr_from_pk].transaction_hashes.remove(self.txhash) - addresses_state[addr_from_pk].decrease_nonce() - addresses_state[addr_from_pk].unset_ots_key(self.ots_key, chain_manager) - def set_affected_address(self, addresses_set: set): addresses_set.add(self.addr_from) addresses_set.add(bytes(QRLHelper.getAddress(self.PK))) @@ -204,6 +177,22 @@ def _validate_custom(self) -> bool: """ raise NotImplementedError + @abstractmethod + def _validate_extended(self, state_container: StateContainer) -> bool: + raise NotImplementedError + + @abstractmethod + def apply(self, + state: State, + state_container: StateContainer) -> bool: + raise NotImplementedError + + @abstractmethod + def revert(self, + state: State, + state_container: StateContainer) -> bool: + raise NotImplementedError + def validate_transaction_pool(self, transaction_pool): for tx_set in transaction_pool: txn = tx_set[1].transaction @@ -239,6 +228,37 @@ def validate(self, verify_signature=True) -> bool: return False return True + def validate_all(self, state_container: StateContainer, check_nonce=True) -> bool: + if not self.validate(True): # It also calls _validate_custom + return False + if not self.validate_slave(state_container): + return False + if not self._validate_extended(state_container): + return False + + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + addr_from_pk_state = state_container.addresses_state[addr_from_pk] + + expected_nonce = addr_from_pk_state.nonce + 1 + + if check_nonce and self.nonce != expected_nonce: + logger.warning('nonce incorrect, invalid tx') + logger.warning('subtype: %s', self.type) + logger.warning('%s actual: %s expected: %s', + OptimizedAddressState.bin_to_qaddress(addr_from_pk), + self.nonce, + expected_nonce) + return False + + if state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(addr_from_pk_state.address, + self.ots_key): + logger.warning('pubkey reuse detected: invalid tx %s', bin2hstr(self.txhash)) + logger.warning('subtype: %s', self.type) + return False + + return True + + # TODO: will need state_container def _coinbase_filter(self): if config.dev.coinbase_address in [bytes(QRLHelper.getAddress(self.PK)), self.master_addr]: raise ValueError('Coinbase Address only allowed to do Coinbase Transaction') @@ -249,6 +269,7 @@ def _get_allowed_access_types(self): def _get_master_address(self): return self.addr_from + # TODO: will need state_container def validate_or_raise(self, verify_signature=True) -> bool: """ This method will validate a transaction and raise exception if problems are found @@ -280,7 +301,7 @@ def validate_or_raise(self, verify_signature=True) -> bool: return True - def validate_slave(self, addr_from_state: AddressState, addr_from_pk_state: AddressState): + def validate_slave(self, state_container: StateContainer) -> bool: addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) master_address = self._get_master_address() @@ -291,13 +312,13 @@ def validate_slave(self, addr_from_state: AddressState, addr_from_pk_state: Addr return False if addr_from_pk != master_address: - if str(self.PK) not in addr_from_state.slave_pks_access_type: - logger.warning("Public key and address don't match") + if (self.addr_from, self.PK) not in state_container.slaves.data: + logger.warning("Public key and address doesn't match") return False - access_type = addr_from_pk_state.slave_pks_access_type[str(self.PK)] - if access_type not in allowed_access_types: - logger.warning('Access Type %s', access_type) + slave_access_type = state_container.slaves.data[(self.addr_from, self.PK)].access_type + if slave_access_type not in allowed_access_types: + logger.warning('Access Type %s', slave_access_type) logger.warning('Slave Address doesnt have sufficient permission') return False @@ -320,3 +341,25 @@ def deserialize(data): pbdata.ParseFromString(bytes(data)) tx = Transaction(pbdata) return tx + + def _apply_state_changes_for_PK(self, + state_container: StateContainer) -> bool: + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + address_state = state_container.addresses_state[addr_from_pk] + if self.addr_from != addr_from_pk: + state_container.paginated_tx_hash.insert(address_state, self.txhash) + address_state.increase_nonce() + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, addr_from_pk, self.ots_key) + + return True + + def _revert_state_changes_for_PK(self, + state_container: StateContainer) -> bool: + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + address_state = state_container.addresses_state[addr_from_pk] + if self.addr_from != addr_from_pk: + state_container.paginated_tx_hash.remove(address_state, self.txhash) + address_state.decrease_nonce() + state_container.paginated_bitfield.unset_ots_key(state_container.addresses_state, addr_from_pk, self.ots_key) + + return True diff --git a/src/qrl/core/txs/TransferTokenTransaction.py b/src/qrl/core/txs/TransferTokenTransaction.py index ff3dbe601..8436f08fe 100644 --- a/src/qrl/core/txs/TransferTokenTransaction.py +++ b/src/qrl/core/txs/TransferTokenTransaction.py @@ -1,7 +1,8 @@ from pyqrllib.pyqrllib import bin2hstr -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction @@ -84,53 +85,54 @@ def _validate_custom(self): if self.fee < 0: raise ValueError('TransferTokenTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) - if (len(self.addrs_to) > config.dev.transaction_multi_output_limit or - len(self.amounts) > config.dev.transaction_multi_output_limit): - logger.warning('[TransferTokenTransaction] Number of addresses or amounts exceeds max limit') - logger.warning('Number of addresses %s', len(self.addrs_to)) - logger.warning('Number of amounts %s', len(self.amounts)) - return False - if len(self.addrs_to) != len(self.amounts): logger.warning('[TransferTokenTransaction] Mismatch number of addresses to & amounts') logger.warning('>> Length of addresses_to %s', len(self.addrs_to)) logger.warning('>> Length of amounts %s', len(self.amounts)) return False - if not AddressState.address_is_valid(self.addr_from): + if not OptimizedAddressState.address_is_valid(self.addr_from): logger.warning('[TransferTokenTransaction] Invalid address addr_from: %s', bin2hstr(self.addr_from)) return False for addr_to in self.addrs_to: - if not AddressState.address_is_valid(addr_to): + if not OptimizedAddressState.address_is_valid(addr_to): logger.warning('[TransferTokenTransaction] Invalid address addr_to: %s', bin2hstr(addr_to)) return False return True # checks new tx validity based upon node statedb and node mempool. - def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: AddressState): - if not self.validate_slave(addr_from_state, addr_from_pk_state): + def _validate_extended(self, state_container: StateContainer): + if (len(self.addrs_to) > state_container.current_dev_config.transaction_multi_output_limit or + len(self.amounts) > state_container.current_dev_config.transaction_multi_output_limit): + logger.warning('[TransferTokenTransaction] Number of addresses or amounts exceeds max limit') + logger.warning('Number of addresses %s', len(self.addrs_to)) + logger.warning('Number of amounts %s', len(self.amounts)) + return False + + if len(self.addrs_to) == 0: + logger.warning("[TransferTokenTransaction] No Addrs To found") return False - tx_balance = addr_from_state.balance + tx_balance = state_container.addresses_state[self.addr_from].balance total_amount = self.total_amount if self.fee < 0 or total_amount < 0: - logger.info('TransferTokenTransaction State validation failed for %s because: ', bin2hstr(self.txhash)) + logger.info('[TransferTokenTransaction] State validation failed for %s because: ', bin2hstr(self.txhash)) logger.info('Txn amount: %s, Fee: %s', total_amount, self.fee) return False if tx_balance < self.fee: - logger.info('TransferTokenTransaction State validation failed for %s because: Insufficient funds', + logger.info('[TransferTokenTransaction] State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, Fee: %s', tx_balance, self.fee) return False - if not addr_from_state.is_token_exists(self.token_txhash): + if (self.addr_from, self.token_txhash) not in state_container.tokens.data: logger.info('%s doesnt own any such token %s ', bin2hstr(self.addr_from), bin2hstr(self.token_txhash)) return False - token_balance = addr_from_state.get_token_balance(self.token_txhash) + token_balance = state_container.tokens.data[(self.addr_from, self.token_txhash)] if token_balance < total_amount: logger.info('Insufficient amount of token') logger.info('Token Balance: %s, Sent Token Amount: %s', @@ -138,47 +140,49 @@ def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: A total_amount) return False - if addr_from_pk_state.ots_key_reuse(self.ots_key): - logger.info( - 'TransferTokenTransaction State validation failed for %s because: OTS Public key re-use detected', - bin2hstr(self.txhash)) - return False - return True - def apply_state_changes(self, addresses_state): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].update_token_balance(self.token_txhash, self.total_amount * -1) - addresses_state[self.addr_from].balance -= self.fee - addresses_state[self.addr_from].transaction_hashes.append(self.txhash) + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + for addr_to in self.addrs_to: + addresses_set.add(addr_to) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + state_container.tokens.data[(self.addr_from, self.token_txhash)].balance -= self.total_amount + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) for index in range(0, len(self.addrs_to)): addr_to = self.addrs_to[index] amount = self.amounts[index] - if addr_to in addresses_state: - if self.addr_from != addr_to: - addresses_state[addr_to].transaction_hashes.append(self.txhash) - addresses_state[addr_to].update_token_balance(self.token_txhash, amount) + address_state = state_container.addresses_state[addr_to] + + state_container.tokens.data[(addr_to, self.token_txhash)].balance += amount - self._apply_state_changes_for_PK(addresses_state) + if self.addr_from != addr_to: + state_container.paginated_tx_hash.insert(address_state, self.txhash) - def revert_state_changes(self, addresses_state, chain_manager): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].update_token_balance(self.token_txhash, self.total_amount) - addresses_state[self.addr_from].balance += self.fee - addresses_state[self.addr_from].transaction_hashes.remove(self.txhash) + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + state_container.tokens.data[(self.addr_from, self.token_txhash)].balance += self.total_amount + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) for index in range(0, len(self.addrs_to)): addr_to = self.addrs_to[index] amount = self.amounts[index] - if addr_to in addresses_state: - if self.addr_from != addr_to: - addresses_state[addr_to].transaction_hashes.remove(self.txhash) - addresses_state[addr_to].update_token_balance(self.token_txhash, amount * -1) + address_state = state_container.addresses_state[addr_to] - self._revert_state_changes_for_PK(addresses_state, chain_manager) + state_container.tokens.data[(addr_to, self.token_txhash)].balance -= amount - def set_affected_address(self, addresses_set: set): - super().set_affected_address(addresses_set) - for addr_to in self.addrs_to: - addresses_set.add(addr_to) + if self.addr_from != addr_to: + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/TransferTransaction.py b/src/qrl/core/txs/TransferTransaction.py index 68775a6c3..b1cdb6e3d 100644 --- a/src/qrl/core/txs/TransferTransaction.py +++ b/src/qrl/core/txs/TransferTransaction.py @@ -1,10 +1,12 @@ -from pyqrllib.pyqrllib import bin2hstr +from pyqrllib.pyqrllib import bin2hstr, QRLHelper +from typing import Union -from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction -from qrl.crypto.misc import sha256 class TransferTransaction(Transaction): @@ -30,19 +32,24 @@ def total_amount(self): def amounts(self): return self._data.transfer.amounts - def get_data_hash(self): + @property + def message_data(self): + return self._data.transfer.message_data + + def get_data_bytes(self): tmptxhash = (self.master_addr + - self.fee.to_bytes(8, byteorder='big', signed=False)) + self.fee.to_bytes(8, byteorder='big', signed=False) + + self.message_data) for index in range(0, len(self.addrs_to)): tmptxhash = (tmptxhash + self.addrs_to[index] + self.amounts[index].to_bytes(8, byteorder='big', signed=False)) - return sha256(tmptxhash) + return tmptxhash @staticmethod - def create(addrs_to: list, amounts: list, fee, xmss_pk, master_addr: bytes = None): + def create(addrs_to: list, amounts: list, message_data: Union[bytes, None], fee: int, xmss_pk, master_addr: bytes = None): transaction = TransferTransaction() if master_addr: @@ -56,6 +63,9 @@ def create(addrs_to: list, amounts: list, fee, xmss_pk, master_addr: bytes = Non for amount in amounts: transaction._data.transfer.amounts.append(amount) + if message_data: + transaction._data.transfer.message_data = message_data + transaction._data.fee = int(fee) # FIXME: Review conversions for quantities transaction.validate_or_raise(verify_signature=False) @@ -72,10 +82,8 @@ def _validate_custom(self): if self.fee < 0: raise ValueError('TransferTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) - if len(self.addrs_to) > config.dev.transaction_multi_output_limit: - logger.warning('[TransferTransaction] Number of addresses exceeds max limit') - logger.warning('Number of addresses %s', len(self.addrs_to)) - logger.warning('Number of amounts %s', len(self.amounts)) + if len(self.addrs_to) == 0: + logger.warning("[TransferTransaction] No Addrs To found") return False if len(self.addrs_to) != len(self.amounts): @@ -84,69 +92,92 @@ def _validate_custom(self): logger.warning('>> Length of amounts %s', len(self.amounts)) return False - if not AddressState.address_is_valid(self.addr_from): + if not OptimizedAddressState.address_is_valid(self.addr_from): logger.warning('[TransferTransaction] Invalid address addr_from: %s', bin2hstr(self.addr_from)) return False for addr_to in self.addrs_to: - if not AddressState.address_is_valid(addr_to): + if not (OptimizedAddressState.address_is_valid(addr_to) or MultiSigAddressState.address_is_valid(addr_to)): logger.warning('[TransferTransaction] Invalid address addr_to: %s', bin2hstr(addr_to)) return False return True # checks new tx validity based upon node statedb and node mempool. - def validate_extended(self, addr_from_state: AddressState, addr_from_pk_state: AddressState): - if not self.validate_slave(addr_from_state, addr_from_pk_state): + def _validate_extended(self, state_container: StateContainer): + if len(self.message_data) > 0: + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[TransferTransaction] Hard Fork Feature not yet activated") + return False + + if len(self.addrs_to) > state_container.current_dev_config.transaction_multi_output_limit: + logger.warning('[TransferTransaction] Number of addresses exceeds max limit') + logger.warning('Number of addresses %s', len(self.addrs_to)) + logger.warning('Number of amounts %s', len(self.amounts)) return False - tx_balance = addr_from_state.balance + if len(self.message_data) > state_container.current_dev_config.message_max_length: + logger.warning("[TransferTransaction] Message data is greater than message max length limit") + logger.warning("Message data length %s", len(self.message_data)) + logger.warning("Message data length limit %s", state_container.current_dev_config.message_max_length) + return False + + tx_balance = state_container.addresses_state[self.addr_from].balance total_amount = self.total_amount + for addr_to in self.addrs_to: + if MultiSigAddressState.address_is_valid(addr_to): + if addr_to not in state_container.addresses_state: + logger.warning('[TransferTransaction] Multi Sig Address doesnt exist: %s', bin2hstr(addr_to)) + return False + if tx_balance < total_amount + self.fee: logger.info('State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, fee: %s, amount: %s', tx_balance, self.fee, total_amount) return False - if addr_from_pk_state.ots_key_reuse(self.ots_key): - logger.info('State validation failed for %s because: OTS Public key re-use detected', bin2hstr(self.txhash)) - return False - return True - def apply_state_changes(self, addresses_state: dict): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance -= (self.total_amount + self.fee) - addresses_state[self.addr_from].transaction_hashes.append(self.txhash) + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + for addr_to in self.addrs_to: + addresses_set.add(addr_to) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.total_amount + self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) for index in range(0, len(self.addrs_to)): addr_to = self.addrs_to[index] amount = self.amounts[index] - if addr_to in addresses_state: - addresses_state[addr_to].balance += amount - if addr_to == self.addr_from: - continue - addresses_state[addr_to].transaction_hashes.append(self.txhash) - - self._apply_state_changes_for_PK(addresses_state) - - def revert_state_changes(self, addresses_state, chain_manager): - if self.addr_from in addresses_state: - addresses_state[self.addr_from].balance += (self.total_amount + self.fee) - addresses_state[self.addr_from].transaction_hashes.remove(self.txhash) - + address_state = state_container.addresses_state[addr_to] + address_state.update_balance(state_container, amount) + if addr_to in (self.addr_from, addr_from_pk): + continue + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, + self.total_amount + self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) for index in range(0, len(self.addrs_to)): addr_to = self.addrs_to[index] amount = self.amounts[index] - if addr_to in addresses_state: - addresses_state[addr_to].balance -= amount - if addr_to == self.addr_from: - continue - addresses_state[addr_to].transaction_hashes.remove(self.txhash) + address_state = state_container.addresses_state[addr_to] + address_state.update_balance(state_container, amount, subtract=True) + if addr_to in (self.addr_from, addr_from_pk): + continue + state_container.paginated_tx_hash.remove(address_state, self.txhash) - self._revert_state_changes_for_PK(addresses_state, chain_manager) - - def set_affected_address(self, addresses_set: set): - super().set_affected_address(addresses_set) - for addr_to in self.addrs_to: - addresses_set.add(addr_to) + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/__init__.py b/src/qrl/core/txs/__init__.py index a08548510..744fd1de0 100644 --- a/src/qrl/core/txs/__init__.py +++ b/src/qrl/core/txs/__init__.py @@ -3,18 +3,39 @@ TYPENAME_MAP = { 'transfer': 'TransferTransaction', 'coinbase': 'CoinBase', - 'latticePK': 'LatticePublicKey', + 'latticePK': 'LatticeTransaction', 'message': 'MessageTransaction', 'token': 'TokenTransaction', 'transfer_token': 'TransferTokenTransaction', - 'slave': 'SlaveTransaction' + 'slave': 'SlaveTransaction', + + 'multi_sig_create': 'MultiSigCreate', + 'multi_sig_spend': 'MultiSigSpend', + 'multi_sig_vote': 'MultiSigVote', +} + +TYPENAME_PACKAGE = { + 'transfer': 'qrl.core.txs', + 'coinbase': 'qrl.core.txs', + 'latticePK': 'qrl.core.txs', + 'message': 'qrl.core.txs', + 'token': 'qrl.core.txs', + 'transfer_token': 'qrl.core.txs', + 'slave': 'qrl.core.txs', + + 'multi_sig_create': 'qrl.core.txs.multisig', + 'multi_sig_spend': 'qrl.core.txs.multisig', + 'multi_sig_vote': 'qrl.core.txs.multisig', + + 'proposal_vote': 'qrl.core.txs.proposal', } def build_tx(pb_tx_type, *args, **kwargs): try: tx_class_name = TYPENAME_MAP[pb_tx_type] - tx_module = import_module('.' + tx_class_name, package='qrl.core.txs') + package = TYPENAME_PACKAGE[pb_tx_type] + tx_module = import_module('.' + tx_class_name, package=package) tx_class = getattr(tx_module, tx_class_name) return tx_class(*args, **kwargs) diff --git a/src/qrl/core/txs/multisig/MultiSigCreate.py b/src/qrl/core/txs/multisig/MultiSigCreate.py new file mode 100644 index 000000000..d12922dc0 --- /dev/null +++ b/src/qrl/core/txs/multisig/MultiSigCreate.py @@ -0,0 +1,185 @@ +from pyqrllib.pyqrllib import QRLHelper, bin2hstr + +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.misc import logger +from qrl.core.txs.Transaction import Transaction +from qrl.crypto.misc import sha256 + + +class MultiSigCreate(Transaction): + """ + MultiSigCreate for the creation of multi sig wallet. + """ + + def __init__(self, protobuf_transaction=None): + super(MultiSigCreate, self).__init__(protobuf_transaction) + + @property + def signatories(self): + return self._data.multi_sig_create.signatories + + @property + def weights(self): + return self._data.multi_sig_create.weights + + @property + def total_weight(self): + total_weight = 0 + for weight in self.weights: + total_weight += weight + return total_weight + + @property + def threshold(self): + return self._data.multi_sig_create.threshold + + def get_data_hash(self): + tmptxhash = (self.master_addr + + self.fee.to_bytes(8, byteorder='big', signed=False) + + self.threshold.to_bytes(8, byteorder='big', signed=False)) + + for index in range(0, len(self.signatories)): + tmptxhash = (tmptxhash + + self.signatories[index] + + self.weights[index].to_bytes(8, byteorder='big', signed=False)) + + return sha256(tmptxhash) + + @staticmethod + def create(signatories: list, weights: list, threshold: int, fee, xmss_pk, master_addr: bytes = None): + multi_sig_create = MultiSigCreate() + + if master_addr: + multi_sig_create._data.master_addr = master_addr + + multi_sig_create._data.public_key = bytes(xmss_pk) + + for signatory in signatories: + multi_sig_create._data.multi_sig_create.signatories.append(signatory) + + for weight in weights: + multi_sig_create._data.multi_sig_create.weights.append(weight) + + multi_sig_create._data.multi_sig_create.threshold = threshold + multi_sig_create._data.fee = int(fee) + + multi_sig_create.validate_or_raise(verify_signature=False) + + return multi_sig_create + + def _validate_custom(self): + if len(self.signatories) == 0: + logger.warning("[MultiSigCreate] No Signatories found") + return False + + for weight in self.weights: + if weight == 0: + logger.warning('Weight cannot be 0 - %s', weight) + logger.warning('Invalid MultiSigCreate Transaction') + return False + + if self.fee < 0: + raise ValueError('MultiSigCreate [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + + if self.total_weight < self.threshold: + logger.warning('[MultiSigCreate] Validation failed for %s because: Insufficient weight', + bin2hstr(self.txhash)) + logger.warning('Total weight: %s, Threshold: %s', self.total_weight, self.threshold) + return False + + if len(set(self.signatories)) != len(self.signatories): + logger.warning('[MultiSigCreate] Signatories list include duplicate signatories') + return False + + if len(self.signatories) != len(self.weights): + logger.warning('[MultiSigCreate] Mismatch number of signatories & weights') + logger.warning('>> Length of signatories %s', len(self.signatories)) + logger.warning('>> Length of weights %s', len(self.weights)) + return False + + if not OptimizedAddressState.address_is_valid(self.addr_from): + logger.warning('[MultiSigCreate] Invalid address addr_from: %s', bin2hstr(self.addr_from)) + return False + + for signatory in self.signatories: + if not OptimizedAddressState.address_is_valid(signatory): + logger.warning('[MultiSigCreate] Invalid address addr_to: %s', bin2hstr(signatory)) + return False + + return True + + # checks new tx validity based upon node statedb and node mempool. + def _validate_extended(self, state_container: StateContainer): + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[MultiSigCreate] Hard Fork Feature not yet activated") + return False + + if len(self.signatories) > state_container.current_dev_config.transaction_multi_output_limit: + logger.warning('[MultiSigCreate] Number of signatories exceeds max limit') + logger.warning('Number of Signatories %s', len(self.signatories)) + logger.warning('Number of Weights %s', len(self.weights)) + return False + + tx_balance = state_container.addresses_state[self.addr_from].balance + + if tx_balance < self.fee: + logger.info('State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) + logger.info('balance: %s, fee: %s, amount: %s', tx_balance, self.fee) + return False + + return True + + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + for signatory in self.signatories: + addresses_set.add(signatory) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + multi_sig_address_state = MultiSigAddressState.get_default(self.txhash, + self.signatories, + self.weights, + self.threshold) + state_container.addresses_state[multi_sig_address_state.address] = multi_sig_address_state + state_container.paginated_tx_hash.insert(multi_sig_address_state, self.txhash) + + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + for index in range(0, len(self.signatories)): + signatory = self.signatories[index] + address_state = state_container.addresses_state[signatory] + if signatory not in (self.addr_from, addr_from_pk): + state_container.paginated_tx_hash.insert(address_state, self.txhash) + state_container.paginated_multisig_address.insert(address_state, multi_sig_address_state.address) + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(self.txhash) + MultiSigAddressState.remove_multi_sig_address_state(state, multi_sig_address, state_container.batch) + + addr_from_pk = bytes(QRLHelper.getAddress(self.PK)) + for index in range(0, len(self.signatories)): + signatory = self.signatories[index] + address_state = state_container.addresses_state[signatory] + if signatory not in (self.addr_from, addr_from_pk): + state_container.paginated_tx_hash.remove(address_state, self.txhash) + state_container.paginated_multisig_address.remove(address_state, multi_sig_address) + + if multi_sig_address in state_container.addresses_state: + del state_container.addresses_state[multi_sig_address] + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/multisig/MultiSigSpend.py b/src/qrl/core/txs/multisig/MultiSigSpend.py new file mode 100644 index 000000000..8775b74c8 --- /dev/null +++ b/src/qrl/core/txs/multisig/MultiSigSpend.py @@ -0,0 +1,242 @@ +from pyqrllib.pyqrllib import bin2hstr + +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.VoteStats import VoteStats +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.misc import logger +from qrl.core.txs.Transaction import Transaction +from qrl.crypto.misc import sha256 + + +class MultiSigSpend(Transaction): + """ + MultiSigSpend for the transaction of QRL from a multi sig wallet to another wallet. + """ + + def __init__(self, protobuf_transaction=None): + super(MultiSigSpend, self).__init__(protobuf_transaction) + + @property + def multi_sig_address(self): + return self._data.multi_sig_spend.multi_sig_address + + @property + def addrs_to(self): + return self._data.multi_sig_spend.addrs_to + + @property + def total_amount(self): + total_amount = 0 + for amount in self.amounts: + total_amount += amount + return total_amount + + @property + def amounts(self): + return self._data.multi_sig_spend.amounts + + @property + def expiry_block_number(self): + return self._data.multi_sig_spend.expiry_block_number + + def get_data_hash(self): + tmp_tx_hash = (self.master_addr + + self.fee.to_bytes(8, byteorder='big', signed=False) + + self.multi_sig_address + + self.expiry_block_number.to_bytes(8, byteorder='big', signed=False)) + + for index in range(0, len(self.addrs_to)): + tmp_tx_hash = (tmp_tx_hash + + self.addrs_to[index] + + self.amounts[index].to_bytes(8, byteorder='big', signed=False)) + + return sha256(tmp_tx_hash) + + @staticmethod + def create(multi_sig_address: bytes, + addrs_to: list, + amounts: list, + expiry_block_number: int, + fee: int, + xmss_pk, + master_addr: bytes = None): + multi_sig_spend = MultiSigSpend() + + if master_addr: + multi_sig_spend._data.master_addr = master_addr + + multi_sig_spend._data.public_key = bytes(xmss_pk) + + multi_sig_spend._data.multi_sig_spend.multi_sig_address = multi_sig_address + + for addr_to in addrs_to: + multi_sig_spend._data.multi_sig_spend.addrs_to.append(addr_to) + + for amount in amounts: + multi_sig_spend._data.multi_sig_spend.amounts.append(amount) + + multi_sig_spend._data.multi_sig_spend.expiry_block_number = expiry_block_number + + multi_sig_spend._data.fee = int(fee) + + multi_sig_spend.validate_or_raise(verify_signature=False) + + return multi_sig_spend + + def _validate_custom(self): + for amount in self.amounts: + if amount == 0: + logger.warning('Amount cannot be 0 - %s', self.amounts) + logger.warning('Invalid TransferTransaction') + return False + + if self.fee < 0: + raise ValueError('MultiSigSpend [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + + if len(self.addrs_to) == 0: + logger.warning('[MultiSigSpend] No addrs_to found') + return False + + if len(self.addrs_to) != len(self.amounts): + logger.warning('[MultiSigSpend] Mismatch number of addresses to & amounts') + logger.warning('>> Length of addrs_to %s', len(self.addrs_to)) + logger.warning('>> Length of amounts %s', len(self.amounts)) + return False + + if not MultiSigAddressState.address_is_valid(self.multi_sig_address): + logger.warning('[MultiSigSpend] Invalid MultiSig Address') + logger.warning('Multi Sig Address %s', self.multi_sig_address) + return False + + if not OptimizedAddressState.address_is_valid(self.addr_from): + logger.warning('[MultiSigSpend] Invalid address addr_from: %s', bin2hstr(self.addr_from)) + return False + + for addr_to in self.addrs_to: + if not (OptimizedAddressState.address_is_valid(addr_to) or MultiSigAddressState.address_is_valid(addr_to)): + logger.warning('[MultiSigSpend] Invalid address addr_to: %s', bin2hstr(addr_to)) + return False + + return True + + def _validate_extended(self, state_container: StateContainer): + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[MultiSigSpend] Hard Fork Feature not yet activated") + return False + + if len(self.addrs_to) > state_container.current_dev_config.transaction_multi_output_limit: + logger.warning('[MultiSigSpend] Number of addresses exceeds max limit') + logger.warning('Number of addresses %s', len(self.addrs_to)) + logger.warning('Number of amounts %s', len(self.amounts)) + return False + + addr_from_state = state_container.addresses_state[self.addr_from] + if self.multi_sig_address not in state_container.addresses_state: + logger.error("[MultiSigSpend] Multi Sig address state not found in state_container %s", + self.multi_sig_address) + return False + + multi_sig_address_state = state_container.addresses_state[self.multi_sig_address] + block_number = state_container.block_number + + if addr_from_state.address != self.addr_from: + logger.error("[MultiSigSpend] Unexpected addr_from_state") + logger.error("Expecting State for address %s, but got state for address %s", + bin2hstr(self.addr_from), + bin2hstr(addr_from_state.address)) + return False + + if multi_sig_address_state.address != self.multi_sig_address: + logger.error("[MultiSigSpend] Unexpected multi sig address state") + logger.error("Expecting State for address %s, but got state for address %s", + bin2hstr(self.multi_sig_address), + bin2hstr(multi_sig_address_state.address)) + return False + + tx_balance = addr_from_state.balance + total_amount = self.total_amount + + if tx_balance < self.fee: + logger.info('[MultiSigSpend] State validation failed for %s because: Insufficient funds', + bin2hstr(self.txhash)) + logger.info('address: %s, balance: %s, fee: %s', bin2hstr(self.addr_from), tx_balance, self.fee) + return False + + if multi_sig_address_state.balance < total_amount: + logger.info('[MultiSigSpend] State validation failed for %s because: Insufficient funds', + bin2hstr(self.txhash)) + logger.info('address: %s, balance: %s, fee: %s', bin2hstr(self.multi_sig_address), tx_balance, self.fee) + return False + + # Multi Sig Spend considered to be expired after block having block number equals to + # self.expiry_block_number gets added into the main chain + if self.expiry_block_number <= block_number: + logger.info('[MultiSigSpend] State validation failed due to invalid expiry_block_number', + bin2hstr(self.txhash)) + logger.info('Chain Height: %s, Expiry Block Number: %s', + block_number, + self.expiry_block_number) + return False + + if self.addr_from not in multi_sig_address_state.signatories: + logger.info('[MultiSigSpend] Address is not in the signatories list', + bin2hstr(self.addr_from)) + return False + + return True + + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + addresses_set.add(self.multi_sig_address) + for addrs_to in self.addrs_to: + addresses_set.add(addrs_to) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + + # TODO: Following line might not be needed + state_container.multi_sig_spend_txs[self.txhash] = self + + multi_sig_address_state = state_container.addresses_state[self.multi_sig_address] + for signatory_address in multi_sig_address_state.signatories: + signatory_address_state = state_container.addresses_state[signatory_address] + state_container.paginated_multi_sig_spend.insert(signatory_address_state, self.txhash) + + state_container.paginated_tx_hash.insert(multi_sig_address_state, self.txhash) + state_container.paginated_multi_sig_spend.insert(multi_sig_address_state, self.txhash) + + vote_stats = VoteStats.create(self.multi_sig_address, + self.txhash, + state_container.addresses_state[self.multi_sig_address].signatories, + self.expiry_block_number) + state_container.votes_stats[self.txhash] = vote_stats + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + + multi_sig_address_state = state_container.addresses_state[self.multi_sig_address] + for signatory_address in multi_sig_address_state.signatories: + signatory_address_state = state_container.addresses_state[signatory_address] + state_container.paginated_multi_sig_spend.remove(signatory_address_state, self.txhash) + + state_container.paginated_tx_hash.remove(multi_sig_address_state, self.txhash) + state_container.paginated_multi_sig_spend.remove(multi_sig_address_state, self.txhash) + + VoteStats.delete_state(state, self.txhash, state_container.batch) + + if self.txhash in state_container.votes_stats: + del state_container.votes_stats[self.txhash] + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/multisig/MultiSigVote.py b/src/qrl/core/txs/multisig/MultiSigVote.py new file mode 100644 index 000000000..535ba8e06 --- /dev/null +++ b/src/qrl/core/txs/multisig/MultiSigVote.py @@ -0,0 +1,160 @@ +from pyqrllib.pyqrllib import bin2hstr + +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.txs.Transaction import Transaction +from qrl.crypto.misc import sha256 + + +class MultiSigVote(Transaction): + """ + MultiSigSpend for the transaction of QRL from a multi sig wallet to another wallet. + """ + + def __init__(self, protobuf_transaction=None): + super(MultiSigVote, self).__init__(protobuf_transaction) + + @property + def shared_key(self): + return self._data.multi_sig_vote.shared_key + + @property + def unvote(self): + return self._data.multi_sig_vote.unvote + + @property + def prev_tx_hash(self): + return self._data.multi_sig_vote.prev_tx_hash + + def set_prev_tx_hash(self, prev_tx_hash: bytes): + self._data.multi_sig_vote.prev_tx_hash = prev_tx_hash + + def get_data_hash(self): + tmp_tx_hash = (self.master_addr + + self.fee.to_bytes(8, byteorder='big', signed=False) + + self.shared_key + + self.unvote.to_bytes(1, byteorder='big', signed=False)) + + return sha256(tmp_tx_hash) + + @staticmethod + def create(shared_key: bytes, + unvote: bool, + fee: int, + xmss_pk, + master_addr: bytes = None): + multi_sig_vote = MultiSigVote() + + if master_addr: + multi_sig_vote._data.master_addr = master_addr + + multi_sig_vote._data.public_key = bytes(xmss_pk) + + multi_sig_vote._data.multi_sig_vote.shared_key = shared_key + multi_sig_vote._data.multi_sig_vote.unvote = unvote + + multi_sig_vote._data.fee = int(fee) + + multi_sig_vote.validate_or_raise(verify_signature=False) + + return multi_sig_vote + + def _validate_custom(self): + if self.fee < 0: + raise ValueError('MultiSigVote [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + + return True + + def _validate_extended(self, state_container: StateContainer): + if state_container.block_number < state_container.current_dev_config.hard_fork_heights[0]: + logger.warning("[MultiSigVote] Hard Fork Feature not yet activated") + return False + + addr_from_state = state_container.addresses_state[self.addr_from] + vote_stats = state_container.votes_stats[self.shared_key] + multi_sig_spend_tx = state_container.multi_sig_spend_txs[self.shared_key] + block_number = state_container.block_number + if vote_stats.executed: + logger.warning("[MultiSigVote] Invalid Tx as MultiSigSpend has already been executed") + return False + + if multi_sig_spend_tx is None: + logger.warning("MultiSigSpend not found, Shared Key %s", bin2hstr(self.shared_key)) + return False + + if block_number > multi_sig_spend_tx.expiry_block_number: + logger.warning("[MultiSigVote] Voted for expired Multi Sig Spend Txn") + logger.warning("Expiry Block Number: %s, Current Block Number: %s", + multi_sig_spend_tx.expiry_block_number, + block_number) + return False + + if self.addr_from not in vote_stats.signatories: + logger.warning("Address not found in signatory list") + logger.warning("Address %s Shared Key %s", + bin2hstr(self.addr_from), + bin2hstr(self.shared_key), + bin2hstr(vote_stats.multi_sig_address)) + return False + + index = vote_stats.get_address_index(self.addr_from) + if vote_stats.unvotes[index] == self.unvote: + logger.warning("[MultiSigVote] Invalid as Vote type already executed") + logger.warning("Vote type %s", self.unvote) + return False + + tx_balance = addr_from_state.balance + + if tx_balance < self.fee: + logger.warning('[MultiSigVote] State validation failed for %s because: Insufficient funds', + bin2hstr(self.txhash)) + logger.warning('balance: %s, fee: %s', tx_balance, self.fee) + return False + + return True + + def set_affected_address(self, addresses_set: set): + super().set_affected_address(addresses_set) + + def apply(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee, subtract=True) + state_container.paginated_tx_hash.insert(address_state, self.txhash) + vote_stats = state_container.votes_stats[self.shared_key] + multi_sig_address = vote_stats.multi_sig_address + + weight, found = state_container.addresses_state[multi_sig_address].get_weight_by_signatory(self.addr_from) + if not found: + logger.info("[MultiSigVote] Address is not the signatory for the multi sig address") + return False + + self.set_prev_tx_hash(vote_stats.get_vote_tx_hash_by_signatory_address(self.addr_from)) + + if not vote_stats.apply_vote_stats(self, weight, state_container): + logger.info("[MultiSigVote] Failed to apply vote_stats") + return False + + return self._apply_state_changes_for_PK(state_container) + + def revert(self, + state: State, + state_container: StateContainer) -> bool: + address_state = state_container.addresses_state[self.addr_from] + address_state.update_balance(state_container, self.fee) + state_container.paginated_tx_hash.remove(address_state, self.txhash) + vote_stats = state_container.votes_stats[self.shared_key] + multi_sig_address = vote_stats.multi_sig_address + + weight, found = state_container.addresses_state[multi_sig_address].get_weight_by_signatory(self.addr_from) + if not found: + logger.info("[MultiSigVote] Address is not the signatory for the multi sig address") + return False + + if not vote_stats.revert_vote_stats(self, weight, state_container): + logger.info("[MultiSigVote] Failed to revert vote_stats") + return False + + return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/core/txs/multisig/__init__.py b/src/qrl/core/txs/multisig/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/qrl/crypto/QRandomX.py b/src/qrl/crypto/QRandomX.py new file mode 100644 index 000000000..c0451ae62 --- /dev/null +++ b/src/qrl/crypto/QRandomX.py @@ -0,0 +1,22 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import threading + +from qrl.core.Singleton import Singleton +from pyqrandomx import pyqrandomx + + +class QRandomX(object, metaclass=Singleton): + + def __init__(self): + self.lock = threading.Lock() + self._qrx = pyqrandomx.ThreadedQRandomX() + + def get_seed_height(self, block_number): + return self._qrx.getSeedHeight(block_number) + + def hash(self, block_height, seed_height, seed_hash, blob): + with self.lock: + return bytes(self._qrx.hash(block_height, seed_height, seed_hash, blob, 0)) + diff --git a/src/qrl/crypto/Qryptonight.py b/src/qrl/crypto/Qryptonight.py index 0cca56fef..6c5ab3a7a 100644 --- a/src/qrl/crypto/Qryptonight.py +++ b/src/qrl/crypto/Qryptonight.py @@ -3,16 +3,31 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import threading +from qrl.core import config from qrl.core.Singleton import Singleton -from pyqryptonight import pyqryptonight +from qrl.crypto.Qryptonight7 import Qryptonight7 +from qrl.crypto.QRandomX import QRandomX class Qryptonight(object, metaclass=Singleton): def __init__(self): self.lock = threading.Lock() - self._qn = pyqryptonight.Qryptonight() + self._qryptonight_7 = Qryptonight7() + self._qrandom_x = QRandomX() - def hash(self, blob): + def get_qn(self, block_number): + if block_number < config.dev.hard_fork_heights[0]: + return self._qryptonight_7 + else: + return self._qrandom_x + + def get_seed_height(self, block_number): + return self._qrandom_x.get_seed_height(block_number) + + def hash(self, block_number, seed_height, seed_hash, blob): with self.lock: - return bytes(self._qn.hash(blob)) + if block_number < config.dev.hard_fork_heights[0]: + return bytes(self._qryptonight_7.hash(blob)) + else: + return bytes(self._qrandom_x.hash(block_number, seed_height, seed_hash, blob)) diff --git a/src/qrl/crypto/Qryptonight7.py b/src/qrl/crypto/Qryptonight7.py new file mode 100644 index 000000000..93a4fa0ff --- /dev/null +++ b/src/qrl/crypto/Qryptonight7.py @@ -0,0 +1,18 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import threading + +from qrl.core.Singleton import Singleton +from pyqryptonight import pyqryptonight + + +class Qryptonight7(object, metaclass=Singleton): + + def __init__(self): + self.lock = threading.Lock() + self._qn = pyqryptonight.Qryptonight() + + def hash(self, blob): + with self.lock: + return bytes(self._qn.hash(blob)) diff --git a/src/qrl/daemon/walletd.py b/src/qrl/daemon/walletd.py index 90392e49d..efaa34795 100644 --- a/src/qrl/daemon/walletd.py +++ b/src/qrl/daemon/walletd.py @@ -6,6 +6,7 @@ import os import logging import grpc +from typing import Optional from time import sleep from daemonize import Daemonize @@ -332,7 +333,7 @@ def try_txn_with_last_slave(self, item, index, group_index, xmss=None): ots_index = slave_address_state.get_unused_ots_index(slave.index) - if ots_index == None: # noqa + if ots_index is None: # noqa self._wallet.set_slave_ots_index(index, group_index, slave_index, @@ -348,6 +349,21 @@ def try_txn_with_last_slave(self, item, index, group_index, xmss=None): return xmss + def is_slave(self, master_address: bytes, slave_pk: bytes) -> bool: + request = qrl_pb2.IsSlaveReq(master_address=master_address, + slave_pk=slave_pk) + + resp = self._public_stub.IsSlave(request=request) + return resp.result + + def get_unused_ots_index(self, address: bytes, unused_ots_index_from: int) -> Optional[int]: + request = qrl_pb2.GetOTSReq(address=address, + unused_ots_index_from=unused_ots_index_from) + resp = self._public_stub.GetOTS(request=request) + if not resp.unused_ots_index_found: + return None + return resp.next_unused_ots_index + def get_slave(self, master_qaddress): index, item = self._wallet.get_address_item(master_qaddress) if index is None: @@ -356,106 +372,182 @@ def get_slave(self, master_qaddress): # Should we check available OTS for master # Get slave list using address state address_state = self.get_address_state(master_qaddress) - - slave = item.slaves[-1][0] - if not address_state.validate_slave_with_access_type(str(bytes(hstr2bin(slave.pk))), [0]): - if len(item.slaves) == 1: - qaddress = item.qaddress - target_address_item = item - group_index = None - else: - qaddress = item.slaves[-2][-1].qaddress - target_address_item = item.slaves[-2][-1] - group_index = -2 - - address_state = self.get_address_state(qaddress) - ots_index = address_state.get_unused_ots_index() - - if ots_index >= UNRESERVED_OTS_INDEX_START: - raise Exception('Fatal Error!!! No reserved OTS index found') + group_index = len(item.slaves) - 1 + slave_group = None + while group_index >= 0: + slave = item.slaves[group_index][0] + if self.is_slave(address_state.address, bytes(hstr2bin(slave.pk))): + slave_group = item.slaves[group_index] + break + group_index -= 1 + if group_index > 0: + xmss = self.try_txn_with_last_slave(item, index, group_index - 1) + if xmss: + return index, group_index - 1, len(item.slaves[group_index - 1]) - 1, xmss + + if slave_group is None: + # Relay slave txn using master address using ots index 0 + return index, -1, -1, None + + for slave_index in range(len(slave_group)): + slave = slave_group[slave_index] + + if slave.index > 2 ** slave.height - 1: + continue + + if slave_index + 1 == len(slave_group) and slave.index >= 2 ** slave.height - 5: + continue if self._passphrase: - target_address_item = self._wallet.decrypt_address_item(target_address_item, self._passphrase) - - xmss = self._wallet.get_xmss_by_item(target_address_item, ots_index) - - slaves_pk = [bytes(hstr2bin(slave_item.pk)) for slave_item in item.slaves[-1]] - tx = self.generate_slave_tx(xmss.pk, - slaves_pk, - self.qaddress_to_address(master_qaddress)) + slave = self._wallet.decrypt_address_item(slave, self._passphrase) - self.sign_and_push_transaction(tx, - xmss, - index, - enable_save=False) + slave_address_state = self.get_address_state(slave.qaddress) - if len(item.slaves) > 1: - if self.try_txn_with_last_slave(item, index, group_index, xmss): - return index, len(item.slaves) - 2, len(item.slaves[group_index]) - 1, xmss + ots_index = self.get_unused_ots_index(slave_address_state.address, slave.index) + if slave_index + 1 == len(slave_group) and max(ots_index, slave.index) > 2 ** slave.height - 100: + ots_index_reserved = self.get_unused_ots_index(slave_address_state.address, 0) + if ots_index_reserved >= UNRESERVED_OTS_INDEX_START: + raise Exception("Fatal Error, no unused reserved OTS index", ots_index_reserved) - else: - if len(item.slaves) > 1: - group_index = len(item.slaves) - 2 - xmss = self.try_txn_with_last_slave(item, index, group_index) - if xmss: - return index, group_index, len(item.slaves[group_index]) - 1, xmss - group_index = len(item.slaves) - 1 - last_slaves = item.slaves[-1] - for slave_index in range(len(last_slaves)): - slave = last_slaves[slave_index] - - # Check if all ots index has been marked as used - if slave.index > 2 ** slave.height - 1: - continue - - # Ignore usage of last 5 ots indexes for the last slave in slave group - if slave_index + 1 == len(last_slaves) and slave.index >= 2 ** slave.height - 5: - continue - - if self._passphrase: - slave = self._wallet.decrypt_address_item(slave, self._passphrase) - - slave_address_state = self.get_address_state(slave.qaddress) - - if slave_index + 1 == len(last_slaves) and slave.index > 2 ** slave.height - 100: + curr_slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index_reserved) - ots_index = slave_address_state.get_unused_ots_index(0) - if ots_index >= UNRESERVED_OTS_INDEX_START: - raise Exception("Fatal Error, no unused reserved OTS index") + slave_xmss_list = self._wallet.add_slave(index=index, + height=slave.height, + number_of_slaves=config.user.number_of_slaves, + passphrase=self._passphrase, + force=True) + slave_pk_list = self.get_pk_list_from_xmss_list(slave_xmss_list) - curr_slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index) + tx = self.generate_slave_tx(bytes(hstr2bin(slave.pk)), + slave_pk_list, + self.qaddress_to_address(item.qaddress)) - slave_xmss_list = self._wallet.add_slave(index=index, - height=slave.height, - number_of_slaves=config.user.number_of_slaves, - passphrase=self._passphrase, - force=True) - slave_pk_list = self.get_pk_list_from_xmss_list(slave_xmss_list) + self.sign_and_push_transaction(tx, + curr_slave_xmss, + index, + enable_save=False) - tx = self.generate_slave_tx(bytes(hstr2bin(slave.pk)), - slave_pk_list, - self.qaddress_to_address(item.qaddress)) + if ots_index is None: + self._wallet.set_slave_ots_index(index, + group_index, + slave_index, + 2 ** slave.height) + continue - self.sign_and_push_transaction(tx, - curr_slave_xmss, - index, - enable_save=False) + slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index) - ots_index = slave_address_state.get_unused_ots_index(slave.index) - - if ots_index == None: # noqa - self._wallet.set_slave_ots_index(index, - group_index, - slave_index, - 2 ** slave.height) - continue - - slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index) - - return index, group_index, slave_index, slave_xmss + return index, group_index, slave_index, slave_xmss return index, -1, -1, None + # def get_slave(self, master_qaddress): + # index, item = self._wallet.get_address_item(master_qaddress) + # if index is None: + # raise Exception("Signer Address Not Found ", master_qaddress) + # + # # Should we check available OTS for master + # # Get slave list using address state + # address_state = self.get_address_state(master_qaddress) + # + # slave = item.slaves[-1][0] + # if not address_state.validate_slave_with_access_type(str(bytes(hstr2bin(slave.pk))), [0]): + # if len(item.slaves) == 1: + # qaddress = item.qaddress + # target_address_item = item + # group_index = None + # else: + # qaddress = item.slaves[-2][-1].qaddress + # target_address_item = item.slaves[-2][-1] + # group_index = -2 + # + # address_state = self.get_address_state(qaddress) + # ots_index = address_state.get_unused_ots_index() + # + # if ots_index >= UNRESERVED_OTS_INDEX_START: + # raise Exception('Fatal Error!!! No reserved OTS index found') + # + # if self._passphrase: + # target_address_item = self._wallet.decrypt_address_item(target_address_item, self._passphrase) + # + # xmss = self._wallet.get_xmss_by_item(target_address_item, ots_index) + # + # slaves_pk = [bytes(hstr2bin(slave_item.pk)) for slave_item in item.slaves[-1]] + # tx = self.generate_slave_tx(xmss.pk, + # slaves_pk, + # self.qaddress_to_address(master_qaddress)) + # + # self.sign_and_push_transaction(tx, + # xmss, + # index, + # enable_save=False) + # + # if len(item.slaves) > 1: + # if self.try_txn_with_last_slave(item, index, group_index, xmss): + # return index, len(item.slaves) - 2, len(item.slaves[group_index]) - 1, xmss + # + # else: + # if len(item.slaves) > 1: + # group_index = len(item.slaves) - 2 + # xmss = self.try_txn_with_last_slave(item, index, group_index) + # if xmss: + # return index, group_index, len(item.slaves[group_index]) - 1, xmss + # group_index = len(item.slaves) - 1 + # last_slaves = item.slaves[-1] + # for slave_index in range(len(last_slaves)): + # slave = last_slaves[slave_index] + # + # # Check if all ots index has been marked as used + # if slave.index > 2 ** slave.height - 1: + # continue + # + # # Ignore usage of last 5 ots indexes for the last slave in slave group + # if slave_index + 1 == len(last_slaves) and slave.index >= 2 ** slave.height - 5: + # continue + # + # if self._passphrase: + # slave = self._wallet.decrypt_address_item(slave, self._passphrase) + # + # slave_address_state = self.get_address_state(slave.qaddress) + # + # if slave_index + 1 == len(last_slaves) and slave.index > 2 ** slave.height - 100: + # + # ots_index = slave_address_state.get_unused_ots_index(0) + # if ots_index >= UNRESERVED_OTS_INDEX_START: + # raise Exception("Fatal Error, no unused reserved OTS index") + # + # curr_slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index) + # + # slave_xmss_list = self._wallet.add_slave(index=index, + # height=slave.height, + # number_of_slaves=config.user.number_of_slaves, + # passphrase=self._passphrase, + # force=True) + # slave_pk_list = self.get_pk_list_from_xmss_list(slave_xmss_list) + # + # tx = self.generate_slave_tx(bytes(hstr2bin(slave.pk)), + # slave_pk_list, + # self.qaddress_to_address(item.qaddress)) + # + # self.sign_and_push_transaction(tx, + # curr_slave_xmss, + # index, + # enable_save=False) + # + # ots_index = slave_address_state.get_unused_ots_index(slave.index) + # + # if ots_index == None: # noqa + # self._wallet.set_slave_ots_index(index, + # group_index, + # slave_index, + # 2 ** slave.height) + # continue + # + # slave_xmss = self._wallet.get_xmss_by_item(slave, ots_index) + # + # return index, group_index, slave_index, slave_xmss + # + # return index, -1, -1, None + def get_slave_xmss(self, master_qaddress): index, group_index, slave_index, slave_xmss = self.get_slave(master_qaddress) @@ -470,9 +562,10 @@ def get_slave_list(self, qaddress) -> list: def verify_ots(self, signer_address, xmss, user_ots_index): addr_state = self.get_address_state(signer_address) - verified_ots_index = addr_state.get_unused_ots_index(xmss.ots_index) - if verified_ots_index == None: # noqa + verified_ots_index = self.get_unused_ots_index(addr_state.address, xmss.ots_index) + + if verified_ots_index is None: # noqa raise Exception("No Unused OTS key found") if user_ots_index > 0: @@ -494,6 +587,7 @@ def relay_transfer_txn(self, tx = TransferTransaction.create(addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, + message_data=None, fee=fee, xmss_pk=xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) @@ -514,6 +608,7 @@ def relay_transfer_txn_by_slave(self, tx = TransferTransaction.create(addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, + message_data=None, fee=fee, xmss_pk=slave_xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) @@ -533,6 +628,7 @@ def relay_message_txn(self, self.verify_ots(signer_address, xmss, user_ots_index=ots_index) tx = MessageTransaction.create(message_hash=message.encode(), + addr_to=None, fee=fee, xmss_pk=xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) @@ -551,6 +647,7 @@ def relay_message_txn_by_slave(self, raise Exception("No Slave Found") tx = MessageTransaction.create(message_hash=message.encode(), + addr_to=None, fee=fee, xmss_pk=slave_xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) @@ -767,9 +864,12 @@ def change_passphrase(self, old_passphrase: str, new_passphrase: str): self.lock_wallet() logger.info("Passphrase Changed") - def get_transactions_by_address(self, qaddress: str) -> tuple: + def get_mini_transactions_by_address(self, qaddress: str, item_per_page: int, page_number: int) -> tuple: address = self.qaddress_to_address(qaddress) - response = self._public_stub.GetTransactionsByAddress(qrl_pb2.GetTransactionsByAddressReq(address=address)) + response = self._public_stub.GetMiniTransactionsByAddress( + qrl_pb2.GetMiniTransactionsByAddressReq(address=address, + item_per_page=item_per_page, + page_number=page_number)) return response.mini_transactions, response.balance def get_transaction(self, tx_hash: str): @@ -798,7 +898,7 @@ def get_total_balance(self) -> int: def get_ots(self, qaddress: str): address = self.qaddress_to_address(qaddress) response = self._public_stub.GetOTS(qrl_pb2.GetOTSReq(address=address)) - return response.ots_bitfield, response.next_unused_ots_index + return response.ots_bitfield_by_page, response.next_unused_ots_index, response.unused_ots_index_found def get_height(self) -> int: response = self._public_stub.GetHeight(qrl_pb2.GetHeightReq()) diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index bb77820a0..6f3aa15c8 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xb3\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12*\n\raddress_state\x18\x02 \x01(\x0b\x32\x11.qrl.AddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"l\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"S\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x04 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\".\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"`\n\x1cGetTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"z\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\x1c\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"A\n\nGetOTSResp\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"C\n\tLatticePK\x12\x0e\n\x06txhash\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\x12\x10\n\x08kyber_pk\x18\x03 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\x8c\x07\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x1a-\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a:\n\x10LatticePublicKey\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\x1a\x1f\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\rB\x11\n\x0ftransactionType\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"a\n\x0bStateLoader\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x02 \x03(\x0c\x12\x0e\n\x06txhash\x18\x03 \x03(\x0c\x12\x19\n\x11total_coin_supply\x18\x04 \x01(\x04\"%\n\x0cStateObjects\x12\x15\n\rstate_loaders\x18\x01 \x03(\x0c\"\x0f\n\rLRUStateCache\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo2\xee\x0b\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"@\n\x13GetAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"F\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\x9b\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -49,8 +49,8 @@ ], containing_type=None, options=None, - serialized_start=1534, - serialized_end=1617, + serialized_start=1759, + serialized_end=1842, ) _sym_db.RegisterEnumDescriptor(_GETLATESTDATAREQ_FILTER) @@ -79,11 +79,53 @@ ], containing_type=None, options=None, - serialized_start=2188, - serialized_end=2264, + serialized_start=2436, + serialized_end=2512, ) _sym_db.RegisterEnumDescriptor(_PUSHTRANSACTIONRESP_RESPONSECODE) +_GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE = _descriptor.EnumDescriptor( + name='FilterType', + full_name='qrl.GetMultiSigSpendTxsByAddressReq.FilterType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NONE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='EXECUTED_ONLY', index=1, number=1, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NON_EXECUTED', index=2, number=2, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='EXPIRED', index=3, number=3, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NON_EXPIRED', index=4, number=4, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NON_EXECUTED_EXPIRED', index=5, number=5, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NON_EXECUTED_NON_EXPIRED', index=6, number=6, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4382, + serialized_end=4527, +) +_sym_db.RegisterEnumDescriptor(_GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE) + _NODEINFO_STATE = _descriptor.EnumDescriptor( name='State', full_name='qrl.NodeInfo.State', @@ -113,8 +155,8 @@ ], containing_type=None, options=None, - serialized_start=3890, - serialized_end=3961, + serialized_start=6230, + serialized_end=6301, ) _sym_db.RegisterEnumDescriptor(_NODEINFO_STATE) @@ -716,7 +758,138 @@ oneofs=[ ], serialized_start=1051, - serialized_end=1106, + serialized_end=1115, +) + + +_GETMULTISIGADDRESSSTATEREQ = _descriptor.Descriptor( + name='GetMultiSigAddressStateReq', + full_name='qrl.GetMultiSigAddressStateReq', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.GetMultiSigAddressStateReq.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1117, + serialized_end=1162, +) + + +_GETMULTISIGADDRESSSTATERESP = _descriptor.Descriptor( + name='GetMultiSigAddressStateResp', + full_name='qrl.GetMultiSigAddressStateResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='state', full_name='qrl.GetMultiSigAddressStateResp.state', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1164, + serialized_end=1235, +) + + +_ISSLAVEREQ = _descriptor.Descriptor( + name='IsSlaveReq', + full_name='qrl.IsSlaveReq', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='master_address', full_name='qrl.IsSlaveReq.master_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='slave_pk', full_name='qrl.IsSlaveReq.slave_pk', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1237, + serialized_end=1291, +) + + +_ISSLAVERESP = _descriptor.Descriptor( + name='IsSlaveResp', + full_name='qrl.IsSlaveResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='result', full_name='qrl.IsSlaveResp.result', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1293, + serialized_end=1322, ) @@ -746,8 +919,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1108, - serialized_end=1142, + serialized_start=1324, + serialized_end=1358, ) @@ -784,8 +957,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1144, - serialized_end=1218, + serialized_start=1360, + serialized_end=1434, ) @@ -815,8 +988,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1220, - serialized_end=1249, + serialized_start=1436, + serialized_end=1465, ) @@ -870,8 +1043,8 @@ name='result', full_name='qrl.GetObjectResp.result', index=0, containing_type=None, fields=[]), ], - serialized_start=1252, - serialized_end=1431, + serialized_start=1468, + serialized_end=1656, ) @@ -916,8 +1089,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1434, - serialized_end=1617, + serialized_start=1659, + serialized_end=1842, ) @@ -961,8 +1134,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1620, - serialized_end=1795, + serialized_start=1845, + serialized_end=2020, ) @@ -995,15 +1168,22 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fee', full_name='qrl.TransferCoinsReq.fee', index=3, - number=4, type=4, cpp_type=4, label=1, + name='message_data', full_name='qrl.TransferCoinsReq.message_data', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.TransferCoinsReq.fee', index=4, + number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.TransferCoinsReq.xmss_pk', index=4, - number=5, type=12, cpp_type=9, label=1, + name='xmss_pk', full_name='qrl.TransferCoinsReq.xmss_pk', index=5, + number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1020,8 +1200,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1797, - serialized_end=1905, + serialized_start=2023, + serialized_end=2153, ) @@ -1051,8 +1231,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1907, - serialized_end=1991, + serialized_start=2155, + serialized_end=2239, ) @@ -1082,8 +1262,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1993, - serialized_end=2059, + serialized_start=2241, + serialized_end=2307, ) @@ -1128,42 +1308,56 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2062, - serialized_end=2264, + serialized_start=2310, + serialized_end=2512, ) -_MESSAGETXNREQ = _descriptor.Descriptor( - name='MessageTxnReq', - full_name='qrl.MessageTxnReq', +_MULTISIGCREATETXNREQ = _descriptor.Descriptor( + name='MultiSigCreateTxnReq', + full_name='qrl.MultiSigCreateTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='master_addr', full_name='qrl.MessageTxnReq.master_addr', index=0, + name='master_addr', full_name='qrl.MultiSigCreateTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='message', full_name='qrl.MessageTxnReq.message', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='signatories', full_name='qrl.MultiSigCreateTxnReq.signatories', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fee', full_name='qrl.MessageTxnReq.fee', index=2, - number=3, type=4, cpp_type=4, label=1, + name='weights', full_name='qrl.MultiSigCreateTxnReq.weights', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='threshold', full_name='qrl.MultiSigCreateTxnReq.threshold', index=3, + number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.MessageTxnReq.xmss_pk', index=3, - number=4, type=12, cpp_type=9, label=1, + name='fee', full_name='qrl.MultiSigCreateTxnReq.fee', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='xmss_pk', full_name='qrl.MultiSigCreateTxnReq.xmss_pk', index=5, + number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1180,70 +1374,63 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2266, - serialized_end=2349, + serialized_start=2515, + serialized_end=2645, ) -_TOKENTXNREQ = _descriptor.Descriptor( - name='TokenTxnReq', - full_name='qrl.TokenTxnReq', +_MULTISIGSPENDTXNREQ = _descriptor.Descriptor( + name='MultiSigSpendTxnReq', + full_name='qrl.MultiSigSpendTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='master_addr', full_name='qrl.TokenTxnReq.master_addr', index=0, + name='master_addr', full_name='qrl.MultiSigSpendTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='symbol', full_name='qrl.TokenTxnReq.symbol', index=1, + name='multi_sig_address', full_name='qrl.MultiSigSpendTxnReq.multi_sig_address', index=1, number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='name', full_name='qrl.TokenTxnReq.name', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='addrs_to', full_name='qrl.MultiSigSpendTxnReq.addrs_to', index=2, + number=3, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='owner', full_name='qrl.TokenTxnReq.owner', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='amounts', full_name='qrl.MultiSigSpendTxnReq.amounts', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='decimals', full_name='qrl.TokenTxnReq.decimals', index=4, + name='expiry_block_number', full_name='qrl.MultiSigSpendTxnReq.expiry_block_number', index=4, number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='initial_balances', full_name='qrl.TokenTxnReq.initial_balances', index=5, - number=6, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='fee', full_name='qrl.TokenTxnReq.fee', index=6, - number=7, type=4, cpp_type=4, label=1, + name='fee', full_name='qrl.MultiSigSpendTxnReq.fee', index=5, + number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.TokenTxnReq.xmss_pk', index=7, - number=8, type=12, cpp_type=9, label=1, + name='xmss_pk', full_name='qrl.MultiSigSpendTxnReq.xmss_pk', index=6, + number=7, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1260,56 +1447,49 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2352, - serialized_end=2525, + serialized_start=2648, + serialized_end=2811, ) -_TRANSFERTOKENTXNREQ = _descriptor.Descriptor( - name='TransferTokenTxnReq', - full_name='qrl.TransferTokenTxnReq', +_MULTISIGVOTETXNREQ = _descriptor.Descriptor( + name='MultiSigVoteTxnReq', + full_name='qrl.MultiSigVoteTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='master_addr', full_name='qrl.TransferTokenTxnReq.master_addr', index=0, + name='master_addr', full_name='qrl.MultiSigVoteTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='addresses_to', full_name='qrl.TransferTokenTxnReq.addresses_to', index=1, - number=2, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='token_txhash', full_name='qrl.TransferTokenTxnReq.token_txhash', index=2, - number=3, type=12, cpp_type=9, label=1, + name='shared_key', full_name='qrl.MultiSigVoteTxnReq.shared_key', index=1, + number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='amounts', full_name='qrl.TransferTokenTxnReq.amounts', index=3, - number=4, type=4, cpp_type=4, label=3, - has_default_value=False, default_value=[], + name='unvote', full_name='qrl.MultiSigVoteTxnReq.unvote', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fee', full_name='qrl.TransferTokenTxnReq.fee', index=4, - number=5, type=4, cpp_type=4, label=1, + name='fee', full_name='qrl.MultiSigVoteTxnReq.fee', index=3, + number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.TransferTokenTxnReq.xmss_pk', index=5, - number=6, type=12, cpp_type=9, label=1, + name='xmss_pk', full_name='qrl.MultiSigVoteTxnReq.xmss_pk', index=4, + number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1326,48 +1506,48 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2528, - serialized_end=2661, + serialized_start=2813, + serialized_end=2920, ) -_SLAVETXNREQ = _descriptor.Descriptor( - name='SlaveTxnReq', - full_name='qrl.SlaveTxnReq', +_MESSAGETXNREQ = _descriptor.Descriptor( + name='MessageTxnReq', + full_name='qrl.MessageTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='master_addr', full_name='qrl.SlaveTxnReq.master_addr', index=0, + name='master_addr', full_name='qrl.MessageTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='slave_pks', full_name='qrl.SlaveTxnReq.slave_pks', index=1, - number=2, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='message', full_name='qrl.MessageTxnReq.message', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='access_types', full_name='qrl.SlaveTxnReq.access_types', index=2, - number=3, type=13, cpp_type=3, label=3, - has_default_value=False, default_value=[], + name='addr_to', full_name='qrl.MessageTxnReq.addr_to', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fee', full_name='qrl.SlaveTxnReq.fee', index=3, + name='fee', full_name='qrl.MessageTxnReq.fee', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.SlaveTxnReq.xmss_pk', index=4, + name='xmss_pk', full_name='qrl.MessageTxnReq.xmss_pk', index=4, number=5, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, @@ -1385,39 +1565,74 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2663, - serialized_end=2768, + serialized_start=2922, + serialized_end=3022, ) -_MINITRANSACTION = _descriptor.Descriptor( - name='MiniTransaction', - full_name='qrl.MiniTransaction', +_TOKENTXNREQ = _descriptor.Descriptor( + name='TokenTxnReq', + full_name='qrl.TokenTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='transaction_hash', full_name='qrl.MiniTransaction.transaction_hash', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, + name='master_addr', full_name='qrl.TokenTxnReq.master_addr', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='out', full_name='qrl.MiniTransaction.out', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, + name='symbol', full_name='qrl.TokenTxnReq.symbol', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='amount', full_name='qrl.MiniTransaction.amount', index=2, - number=3, type=4, cpp_type=4, label=1, + name='name', full_name='qrl.TokenTxnReq.name', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='owner', full_name='qrl.TokenTxnReq.owner', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='decimals', full_name='qrl.TokenTxnReq.decimals', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='initial_balances', full_name='qrl.TokenTxnReq.initial_balances', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.TokenTxnReq.fee', index=6, + number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='xmss_pk', full_name='qrl.TokenTxnReq.xmss_pk', index=7, + number=8, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1430,25 +1645,60 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2770, - serialized_end=2842, + serialized_start=3025, + serialized_end=3198, ) -_GETTRANSACTIONSBYADDRESSREQ = _descriptor.Descriptor( - name='GetTransactionsByAddressReq', - full_name='qrl.GetTransactionsByAddressReq', +_TRANSFERTOKENTXNREQ = _descriptor.Descriptor( + name='TransferTokenTxnReq', + full_name='qrl.TransferTokenTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.GetTransactionsByAddressReq.address', index=0, + name='master_addr', full_name='qrl.TransferTokenTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addresses_to', full_name='qrl.TransferTokenTxnReq.addresses_to', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='token_txhash', full_name='qrl.TransferTokenTxnReq.token_txhash', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amounts', full_name='qrl.TransferTokenTxnReq.amounts', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.TransferTokenTxnReq.fee', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='xmss_pk', full_name='qrl.TransferTokenTxnReq.xmss_pk', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1461,32 +1711,53 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2844, - serialized_end=2890, + serialized_start=3201, + serialized_end=3334, ) -_GETTRANSACTIONSBYADDRESSRESP = _descriptor.Descriptor( - name='GetTransactionsByAddressResp', - full_name='qrl.GetTransactionsByAddressResp', +_SLAVETXNREQ = _descriptor.Descriptor( + name='SlaveTxnReq', + full_name='qrl.SlaveTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='mini_transactions', full_name='qrl.GetTransactionsByAddressResp.mini_transactions', index=0, - number=1, type=11, cpp_type=10, label=3, + name='master_addr', full_name='qrl.SlaveTxnReq.master_addr', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='slave_pks', full_name='qrl.SlaveTxnReq.slave_pks', index=1, + number=2, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='balance', full_name='qrl.GetTransactionsByAddressResp.balance', index=1, - number=2, type=4, cpp_type=4, label=1, + name='access_types', full_name='qrl.SlaveTxnReq.access_types', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.SlaveTxnReq.fee', index=3, + number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='xmss_pk', full_name='qrl.SlaveTxnReq.xmss_pk', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1499,25 +1770,67 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2892, - serialized_end=2988, + serialized_start=3336, + serialized_end=3441, ) -_GETTRANSACTIONREQ = _descriptor.Descriptor( - name='GetTransactionReq', - full_name='qrl.GetTransactionReq', +_LATTICETXNREQ = _descriptor.Descriptor( + name='LatticeTxnReq', + full_name='qrl.LatticeTxnReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='tx_hash', full_name='qrl.GetTransactionReq.tx_hash', index=0, + name='master_addr', full_name='qrl.LatticeTxnReq.master_addr', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk1', full_name='qrl.LatticeTxnReq.pk1', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk2', full_name='qrl.LatticeTxnReq.pk2', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk3', full_name='qrl.LatticeTxnReq.pk3', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk4', full_name='qrl.LatticeTxnReq.pk4', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.LatticeTxnReq.fee', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='xmss_pk', full_name='qrl.LatticeTxnReq.xmss_pk', index=6, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1530,46 +1843,39 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2990, - serialized_end=3026, + serialized_start=3443, + serialized_end=3561, ) -_GETTRANSACTIONRESP = _descriptor.Descriptor( - name='GetTransactionResp', - full_name='qrl.GetTransactionResp', +_MINITRANSACTION = _descriptor.Descriptor( + name='MiniTransaction', + full_name='qrl.MiniTransaction', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='tx', full_name='qrl.GetTransactionResp.tx', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='transaction_hash', full_name='qrl.MiniTransaction.transaction_hash', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='confirmations', full_name='qrl.GetTransactionResp.confirmations', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='out', full_name='qrl.MiniTransaction.out', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.GetTransactionResp.block_number', index=2, + name='amount', full_name='qrl.MiniTransaction.amount', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='block_header_hash', full_name='qrl.GetTransactionResp.block_header_hash', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1582,20 +1888,20 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3028, - serialized_end=3150, + serialized_start=3563, + serialized_end=3635, ) -_GETBALANCEREQ = _descriptor.Descriptor( - name='GetBalanceReq', - full_name='qrl.GetBalanceReq', +_GETTRANSACTIONREQ = _descriptor.Descriptor( + name='GetTransactionReq', + full_name='qrl.GetTransactionReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.GetBalanceReq.address', index=0, + name='tx_hash', full_name='qrl.GetTransactionReq.tx_hash', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, @@ -1613,25 +1919,60 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3152, - serialized_end=3184, + serialized_start=3637, + serialized_end=3673, ) -_GETBALANCERESP = _descriptor.Descriptor( - name='GetBalanceResp', - full_name='qrl.GetBalanceResp', +_GETTRANSACTIONRESP = _descriptor.Descriptor( + name='GetTransactionResp', + full_name='qrl.GetTransactionResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='balance', full_name='qrl.GetBalanceResp.balance', index=0, - number=1, type=4, cpp_type=4, label=1, + name='tx', full_name='qrl.GetTransactionResp.tx', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='confirmations', full_name='qrl.GetTransactionResp.confirmations', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_number', full_name='qrl.GetTransactionResp.block_number', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_header_hash', full_name='qrl.GetTransactionResp.block_header_hash', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='qrl.GetTransactionResp.timestamp', index=4, + number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addr_from', full_name='qrl.GetTransactionResp.addr_from', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1644,29 +1985,43 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3186, - serialized_end=3219, + serialized_start=3676, + serialized_end=3836, ) -_GETTOTALBALANCEREQ = _descriptor.Descriptor( - name='GetTotalBalanceReq', - full_name='qrl.GetTotalBalanceReq', +_GETMINITRANSACTIONSBYADDRESSREQ = _descriptor.Descriptor( + name='GetMiniTransactionsByAddressReq', + full_name='qrl.GetMiniTransactionsByAddressReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addresses', full_name='qrl.GetTotalBalanceReq.addresses', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='address', full_name='qrl.GetMiniTransactionsByAddressReq.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], + _descriptor.FieldDescriptor( + name='item_per_page', full_name='qrl.GetMiniTransactionsByAddressReq.item_per_page', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='page_number', full_name='qrl.GetMiniTransactionsByAddressReq.page_number', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], enum_types=[ ], options=None, @@ -1675,21 +2030,28 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3221, - serialized_end=3260, + serialized_start=3838, + serialized_end=3932, ) -_GETTOTALBALANCERESP = _descriptor.Descriptor( - name='GetTotalBalanceResp', - full_name='qrl.GetTotalBalanceResp', +_GETMINITRANSACTIONSBYADDRESSRESP = _descriptor.Descriptor( + name='GetMiniTransactionsByAddressResp', + full_name='qrl.GetMiniTransactionsByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='balance', full_name='qrl.GetTotalBalanceResp.balance', index=0, - number=1, type=4, cpp_type=4, label=1, + name='mini_transactions', full_name='qrl.GetMiniTransactionsByAddressResp.mini_transactions', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.GetMiniTransactionsByAddressResp.balance', index=1, + number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1706,25 +2068,39 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3262, - serialized_end=3300, + serialized_start=3934, + serialized_end=4034, ) -_GETOTSREQ = _descriptor.Descriptor( - name='GetOTSReq', - full_name='qrl.GetOTSReq', +_GETTRANSACTIONSBYADDRESSREQ = _descriptor.Descriptor( + name='GetTransactionsByAddressReq', + full_name='qrl.GetTransactionsByAddressReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.GetOTSReq.address', index=0, + name='address', full_name='qrl.GetTransactionsByAddressReq.address', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='item_per_page', full_name='qrl.GetTransactionsByAddressReq.item_per_page', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='page_number', full_name='qrl.GetTransactionsByAddressReq.page_number', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1737,32 +2113,25 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3302, - serialized_end=3330, + serialized_start=4036, + serialized_end=4126, ) -_GETOTSRESP = _descriptor.Descriptor( - name='GetOTSResp', - full_name='qrl.GetOTSResp', +_GETTRANSACTIONSBYADDRESSRESP = _descriptor.Descriptor( + name='GetTransactionsByAddressResp', + full_name='qrl.GetTransactionsByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='ots_bitfield', full_name='qrl.GetOTSResp.ots_bitfield', index=0, - number=1, type=12, cpp_type=9, label=3, + name='transactions_detail', full_name='qrl.GetTransactionsByAddressResp.transactions_detail', index=0, + number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='next_unused_ots_index', full_name='qrl.GetOTSResp.next_unused_ots_index', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1775,23 +2144,52 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3332, - serialized_end=3397, + serialized_start=4128, + serialized_end=4212, ) -_GETHEIGHTREQ = _descriptor.Descriptor( - name='GetHeightReq', - full_name='qrl.GetHeightReq', +_GETMULTISIGSPENDTXSBYADDRESSREQ = _descriptor.Descriptor( + name='GetMultiSigSpendTxsByAddressReq', + full_name='qrl.GetMultiSigSpendTxsByAddressReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.GetMultiSigSpendTxsByAddressReq.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='item_per_page', full_name='qrl.GetMultiSigSpendTxsByAddressReq.item_per_page', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='page_number', full_name='qrl.GetMultiSigSpendTxsByAddressReq.page_number', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='filter_type', full_name='qrl.GetMultiSigSpendTxsByAddressReq.filter_type', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ + _GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE, ], options=None, is_extendable=False, @@ -1799,22 +2197,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3399, - serialized_end=3413, + serialized_start=4215, + serialized_end=4527, ) -_GETHEIGHTRESP = _descriptor.Descriptor( - name='GetHeightResp', - full_name='qrl.GetHeightResp', +_GETMULTISIGSPENDTXSBYADDRESSRESP = _descriptor.Descriptor( + name='GetMultiSigSpendTxsByAddressResp', + full_name='qrl.GetMultiSigSpendTxsByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='height', full_name='qrl.GetHeightResp.height', index=0, - number=1, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='transactions_detail', full_name='qrl.GetMultiSigSpendTxsByAddressResp.transactions_detail', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -1830,20 +2228,20 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3415, - serialized_end=3446, + serialized_start=4529, + serialized_end=4617, ) -_GETBLOCKREQ = _descriptor.Descriptor( - name='GetBlockReq', - full_name='qrl.GetBlockReq', +_GETVOTESTATSREQ = _descriptor.Descriptor( + name='GetVoteStatsReq', + full_name='qrl.GetVoteStatsReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='header_hash', full_name='qrl.GetBlockReq.header_hash', index=0, + name='multi_sig_spend_tx_hash', full_name='qrl.GetVoteStatsReq.multi_sig_spend_tx_hash', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, @@ -1861,20 +2259,20 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3448, - serialized_end=3482, + serialized_start=4619, + serialized_end=4669, ) -_GETBLOCKRESP = _descriptor.Descriptor( - name='GetBlockResp', - full_name='qrl.GetBlockResp', +_GETVOTESTATSRESP = _descriptor.Descriptor( + name='GetVoteStatsResp', + full_name='qrl.GetVoteStatsResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block', full_name='qrl.GetBlockResp.block', index=0, + name='vote_stats', full_name='qrl.GetVoteStatsResp.vote_stats', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, @@ -1892,21 +2290,42 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3484, - serialized_end=3525, + serialized_start=4671, + serialized_end=4725, ) -_GETBLOCKBYNUMBERREQ = _descriptor.Descriptor( - name='GetBlockByNumberReq', - full_name='qrl.GetBlockByNumberReq', +_TOKENDETAIL = _descriptor.Descriptor( + name='TokenDetail', + full_name='qrl.TokenDetail', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.GetBlockByNumberReq.block_number', index=0, - number=1, type=4, cpp_type=4, label=1, + name='token_txhash', full_name='qrl.TokenDetail.token_txhash', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='qrl.TokenDetail.name', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='symbol', full_name='qrl.TokenDetail.symbol', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.TokenDetail.balance', index=3, + number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1923,22 +2342,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3527, - serialized_end=3570, + serialized_start=4727, + serialized_end=4809, ) -_GETBLOCKBYNUMBERRESP = _descriptor.Descriptor( - name='GetBlockByNumberResp', - full_name='qrl.GetBlockByNumberResp', +_GETTOKENSBYADDRESSRESP = _descriptor.Descriptor( + name='GetTokensByAddressResp', + full_name='qrl.GetTokensByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block', full_name='qrl.GetBlockByNumberResp.block', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='tokens_detail', full_name='qrl.GetTokensByAddressResp.tokens_detail', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -1954,18 +2373,32 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3572, - serialized_end=3621, + serialized_start=4811, + serialized_end=4876, ) -_GETLOCALADDRESSESREQ = _descriptor.Descriptor( - name='GetLocalAddressesReq', - full_name='qrl.GetLocalAddressesReq', +_SLAVEDETAIL = _descriptor.Descriptor( + name='SlaveDetail', + full_name='qrl.SlaveDetail', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ + _descriptor.FieldDescriptor( + name='slave_address', full_name='qrl.SlaveDetail.slave_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='access_type', full_name='qrl.SlaveDetail.access_type', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1978,21 +2411,21 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3623, - serialized_end=3645, + serialized_start=4878, + serialized_end=4935, ) -_GETLOCALADDRESSESRESP = _descriptor.Descriptor( - name='GetLocalAddressesResp', - full_name='qrl.GetLocalAddressesResp', +_GETSLAVESBYADDRESSRESP = _descriptor.Descriptor( + name='GetSlavesByAddressResp', + full_name='qrl.GetSlavesByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addresses', full_name='qrl.GetLocalAddressesResp.addresses', index=0, - number=1, type=12, cpp_type=9, label=3, + name='slaves_detail', full_name='qrl.GetSlavesByAddressResp.slaves_detail', index=0, + number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -2009,71 +2442,43 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3647, - serialized_end=3689, + serialized_start=4937, + serialized_end=5002, ) -_NODEINFO = _descriptor.Descriptor( - name='NodeInfo', - full_name='qrl.NodeInfo', +_LATTICEPKSDETAIL = _descriptor.Descriptor( + name='LatticePKsDetail', + full_name='qrl.LatticePKsDetail', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='version', full_name='qrl.NodeInfo.version', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='qrl.NodeInfo.state', index=1, - number=2, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='num_connections', full_name='qrl.NodeInfo.num_connections', index=2, - number=3, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='num_known_peers', full_name='qrl.NodeInfo.num_known_peers', index=3, - number=4, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='uptime', full_name='qrl.NodeInfo.uptime', index=4, - number=5, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='pk1', full_name='qrl.LatticePKsDetail.pk1', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='block_height', full_name='qrl.NodeInfo.block_height', index=5, - number=6, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='pk2', full_name='qrl.LatticePKsDetail.pk2', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='block_last_hash', full_name='qrl.NodeInfo.block_last_hash', index=6, - number=7, type=12, cpp_type=9, label=1, + name='pk3', full_name='qrl.LatticePKsDetail.pk3', index=2, + number=3, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='network_id', full_name='qrl.NodeInfo.network_id', index=7, - number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='pk4', full_name='qrl.LatticePKsDetail.pk4', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2082,7 +2487,6 @@ ], nested_types=[], enum_types=[ - _NODEINFO_STATE, ], options=None, is_extendable=False, @@ -2090,50 +2494,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3692, - serialized_end=3961, + serialized_start=5004, + serialized_end=5074, ) -_ADDRESSDESCRIPTOR = _descriptor.Descriptor( - name='AddressDescriptor', - full_name='qrl.AddressDescriptor', +_GETLATTICEPKSBYADDRESSRESP = _descriptor.Descriptor( + name='GetLatticePKsByAddressResp', + full_name='qrl.GetLatticePKsByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='hash_function', full_name='qrl.AddressDescriptor.hash_function', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='signature_scheme', full_name='qrl.AddressDescriptor.signature_scheme', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='tree_height', full_name='qrl.AddressDescriptor.tree_height', index=2, - number=3, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='signatures', full_name='qrl.AddressDescriptor.signatures', index=3, - number=4, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='address_format', full_name='qrl.AddressDescriptor.address_format', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='lattice_pks_detail', full_name='qrl.GetLatticePKsByAddressResp.lattice_pks_detail', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2149,29 +2525,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3964, - serialized_end=4097, + serialized_start=5076, + serialized_end=5155, ) -_STOREDPEERS = _descriptor.Descriptor( - name='StoredPeers', - full_name='qrl.StoredPeers', +_MULTISIGDETAIL = _descriptor.Descriptor( + name='MultiSigDetail', + full_name='qrl.MultiSigDetail', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='peers', full_name='qrl.StoredPeers.peers', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='address', full_name='qrl.MultiSigDetail.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.MultiSigDetail.balance', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], enum_types=[ ], options=None, @@ -2180,22 +2563,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4099, - serialized_end=4138, + serialized_start=5157, + serialized_end=5207, ) -_PEER = _descriptor.Descriptor( - name='Peer', - full_name='qrl.Peer', +_GETMULTISIGADDRESSESBYADDRESSRESP = _descriptor.Descriptor( + name='GetMultiSigAddressesByAddressResp', + full_name='qrl.GetMultiSigAddressesByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='ip', full_name='qrl.Peer.ip', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='multi_sig_detail', full_name='qrl.GetMultiSigAddressesByAddressResp.multi_sig_detail', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2211,28 +2594,52 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4140, - serialized_end=4158, + serialized_start=5209, + serialized_end=5291, ) -_ADDRESSSTATE_TOKENSENTRY = _descriptor.Descriptor( - name='TokensEntry', - full_name='qrl.AddressState.TokensEntry', +_GETBALANCEREQ = _descriptor.Descriptor( + name='GetBalanceReq', + full_name='qrl.GetBalanceReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='key', full_name='qrl.AddressState.TokensEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='address', full_name='qrl.GetBalanceReq.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5293, + serialized_end=5325, +) + + +_GETBALANCERESP = _descriptor.Descriptor( + name='GetBalanceResp', + full_name='qrl.GetBalanceResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='value', full_name='qrl.AddressState.TokensEntry.value', index=1, - number=2, type=4, cpp_type=4, label=1, + name='balance', full_name='qrl.GetBalanceResp.balance', index=0, + number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -2243,33 +2650,58 @@ nested_types=[], enum_types=[ ], - options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], - serialized_start=4458, - serialized_end=4503, + serialized_start=5327, + serialized_end=5360, ) -_ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( - name='SlavePksAccessTypeEntry', - full_name='qrl.AddressState.SlavePksAccessTypeEntry', + +_GETTOTALBALANCEREQ = _descriptor.Descriptor( + name='GetTotalBalanceReq', + full_name='qrl.GetTotalBalanceReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='key', full_name='qrl.AddressState.SlavePksAccessTypeEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='addresses', full_name='qrl.GetTotalBalanceReq.addresses', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5362, + serialized_end=5401, +) + + +_GETTOTALBALANCERESP = _descriptor.Descriptor( + name='GetTotalBalanceResp', + full_name='qrl.GetTotalBalanceResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='value', full_name='qrl.AddressState.SlavePksAccessTypeEntry.value', index=1, - number=2, type=13, cpp_type=3, label=1, + name='balance', full_name='qrl.GetTotalBalanceResp.balance', index=0, + number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -2280,90 +2712,139 @@ nested_types=[], enum_types=[ ], - options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + options=None, is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], - serialized_start=4505, - serialized_end=4562, + serialized_start=5403, + serialized_end=5441, ) -_ADDRESSSTATE = _descriptor.Descriptor( - name='AddressState', - full_name='qrl.AddressState', + +_GETOTSREQ = _descriptor.Descriptor( + name='GetOTSReq', + full_name='qrl.GetOTSReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.AddressState.address', index=0, + name='address', full_name='qrl.GetOTSReq.address', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='balance', full_name='qrl.AddressState.balance', index=1, + name='page_from', full_name='qrl.GetOTSReq.page_from', index=1, number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='nonce', full_name='qrl.AddressState.nonce', index=2, + name='page_count', full_name='qrl.GetOTSReq.page_count', index=2, number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ots_bitfield', full_name='qrl.AddressState.ots_bitfield', index=3, - number=4, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='unused_ots_index_from', full_name='qrl.GetOTSReq.unused_ots_index_from', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5443, + serialized_end=5541, +) + + +_OTSBITFIELDBYPAGE = _descriptor.Descriptor( + name='OTSBitfieldByPage', + full_name='qrl.OTSBitfieldByPage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='transaction_hashes', full_name='qrl.AddressState.transaction_hashes', index=4, - number=5, type=12, cpp_type=9, label=3, + name='ots_bitfield', full_name='qrl.OTSBitfieldByPage.ots_bitfield', index=0, + number=1, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='tokens', full_name='qrl.AddressState.tokens', index=5, - number=6, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='page_number', full_name='qrl.OTSBitfieldByPage.page_number', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5543, + serialized_end=5605, +) + + +_GETOTSRESP = _descriptor.Descriptor( + name='GetOTSResp', + full_name='qrl.GetOTSResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='latticePK_list', full_name='qrl.AddressState.latticePK_list', index=6, - number=7, type=11, cpp_type=10, label=3, + name='ots_bitfield_by_page', full_name='qrl.GetOTSResp.ots_bitfield_by_page', index=0, + number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='slave_pks_access_type', full_name='qrl.AddressState.slave_pks_access_type', index=7, - number=8, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='next_unused_ots_index', full_name='qrl.GetOTSResp.next_unused_ots_index', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ots_counter', full_name='qrl.AddressState.ots_counter', index=8, - number=9, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='unused_ots_index_found', full_name='qrl.GetOTSResp.unused_ots_index_found', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), ], extensions=[ ], - nested_types=[_ADDRESSSTATE_TOKENSENTRY, _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY, ], + nested_types=[], enum_types=[ ], options=None, @@ -2372,36 +2853,46 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4161, - serialized_end=4562, + serialized_start=5608, + serialized_end=5737, ) -_LATTICEPK = _descriptor.Descriptor( - name='LatticePK', - full_name='qrl.LatticePK', +_GETHEIGHTREQ = _descriptor.Descriptor( + name='GetHeightReq', + full_name='qrl.GetHeightReq', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5739, + serialized_end=5753, +) + + +_GETHEIGHTRESP = _descriptor.Descriptor( + name='GetHeightResp', + full_name='qrl.GetHeightResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='txhash', full_name='qrl.LatticePK.txhash', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='dilithium_pk', full_name='qrl.LatticePK.dilithium_pk', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='kyber_pk', full_name='qrl.LatticePK.kyber_pk', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='height', full_name='qrl.GetHeightResp.height', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2417,32 +2908,25 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4564, - serialized_end=4631, + serialized_start=5755, + serialized_end=5786, ) -_ADDRESSAMOUNT = _descriptor.Descriptor( - name='AddressAmount', - full_name='qrl.AddressAmount', +_GETBLOCKREQ = _descriptor.Descriptor( + name='GetBlockReq', + full_name='qrl.GetBlockReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.AddressAmount.address', index=0, + name='header_hash', full_name='qrl.GetBlockReq.header_hash', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='amount', full_name='qrl.AddressAmount.amount', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -2455,115 +2939,2344 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4633, - serialized_end=4681, + serialized_start=5788, + serialized_end=5822, ) -_BLOCKHEADER = _descriptor.Descriptor( - name='BlockHeader', - full_name='qrl.BlockHeader', +_GETBLOCKRESP = _descriptor.Descriptor( + name='GetBlockResp', + full_name='qrl.GetBlockResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='hash_header', full_name='qrl.BlockHeader.hash_header', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='block', full_name='qrl.GetBlockResp.block', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5824, + serialized_end=5865, +) + + +_GETBLOCKBYNUMBERREQ = _descriptor.Descriptor( + name='GetBlockByNumberReq', + full_name='qrl.GetBlockByNumberReq', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='block_number', full_name='qrl.GetBlockByNumberReq.block_number', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5867, + serialized_end=5910, +) + + +_GETBLOCKBYNUMBERRESP = _descriptor.Descriptor( + name='GetBlockByNumberResp', + full_name='qrl.GetBlockByNumberResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='block', full_name='qrl.GetBlockByNumberResp.block', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5912, + serialized_end=5961, +) + + +_GETLOCALADDRESSESREQ = _descriptor.Descriptor( + name='GetLocalAddressesReq', + full_name='qrl.GetLocalAddressesReq', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5963, + serialized_end=5985, +) + + +_GETLOCALADDRESSESRESP = _descriptor.Descriptor( + name='GetLocalAddressesResp', + full_name='qrl.GetLocalAddressesResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='addresses', full_name='qrl.GetLocalAddressesResp.addresses', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5987, + serialized_end=6029, +) + + +_NODEINFO = _descriptor.Descriptor( + name='NodeInfo', + full_name='qrl.NodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='version', full_name='qrl.NodeInfo.version', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='qrl.NodeInfo.state', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='num_connections', full_name='qrl.NodeInfo.num_connections', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='num_known_peers', full_name='qrl.NodeInfo.num_known_peers', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uptime', full_name='qrl.NodeInfo.uptime', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_height', full_name='qrl.NodeInfo.block_height', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_last_hash', full_name='qrl.NodeInfo.block_last_hash', index=6, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='network_id', full_name='qrl.NodeInfo.network_id', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _NODEINFO_STATE, + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6032, + serialized_end=6301, +) + + +_ADDRESSDESCRIPTOR = _descriptor.Descriptor( + name='AddressDescriptor', + full_name='qrl.AddressDescriptor', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='hash_function', full_name='qrl.AddressDescriptor.hash_function', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='signature_scheme', full_name='qrl.AddressDescriptor.signature_scheme', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tree_height', full_name='qrl.AddressDescriptor.tree_height', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='signatures', full_name='qrl.AddressDescriptor.signatures', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='address_format', full_name='qrl.AddressDescriptor.address_format', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6304, + serialized_end=6437, +) + + +_STOREDPEERS = _descriptor.Descriptor( + name='StoredPeers', + full_name='qrl.StoredPeers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='peers', full_name='qrl.StoredPeers.peers', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6439, + serialized_end=6478, +) + + +_PEER = _descriptor.Descriptor( + name='Peer', + full_name='qrl.Peer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ip', full_name='qrl.Peer.ip', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6480, + serialized_end=6498, +) + + +_ADDRESSSTATE_TOKENSENTRY = _descriptor.Descriptor( + name='TokensEntry', + full_name='qrl.AddressState.TokensEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='qrl.AddressState.TokensEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='qrl.AddressState.TokensEntry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6798, + serialized_end=6843, +) + +_ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( + name='SlavePksAccessTypeEntry', + full_name='qrl.AddressState.SlavePksAccessTypeEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='qrl.AddressState.SlavePksAccessTypeEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='qrl.AddressState.SlavePksAccessTypeEntry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6845, + serialized_end=6902, +) + +_ADDRESSSTATE = _descriptor.Descriptor( + name='AddressState', + full_name='qrl.AddressState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.AddressState.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.AddressState.balance', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nonce', full_name='qrl.AddressState.nonce', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ots_bitfield', full_name='qrl.AddressState.ots_bitfield', index=3, + number=4, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_hashes', full_name='qrl.AddressState.transaction_hashes', index=4, + number=5, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tokens', full_name='qrl.AddressState.tokens', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='latticePK_list', full_name='qrl.AddressState.latticePK_list', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='slave_pks_access_type', full_name='qrl.AddressState.slave_pks_access_type', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ots_counter', full_name='qrl.AddressState.ots_counter', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_ADDRESSSTATE_TOKENSENTRY, _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6501, + serialized_end=6902, +) + + +_OPTIMIZEDADDRESSSTATE = _descriptor.Descriptor( + name='OptimizedAddressState', + full_name='qrl.OptimizedAddressState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.OptimizedAddressState.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.OptimizedAddressState.balance', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nonce', full_name='qrl.OptimizedAddressState.nonce', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ots_bitfield_used_page', full_name='qrl.OptimizedAddressState.ots_bitfield_used_page', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='used_ots_key_count', full_name='qrl.OptimizedAddressState.used_ots_key_count', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_hash_count', full_name='qrl.OptimizedAddressState.transaction_hash_count', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tokens_count', full_name='qrl.OptimizedAddressState.tokens_count', index=6, + number=7, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='slaves_count', full_name='qrl.OptimizedAddressState.slaves_count', index=7, + number=8, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lattice_pk_count', full_name='qrl.OptimizedAddressState.lattice_pk_count', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi_sig_address_count', full_name='qrl.OptimizedAddressState.multi_sig_address_count', index=9, + number=10, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi_sig_spend_count', full_name='qrl.OptimizedAddressState.multi_sig_spend_count', index=10, + number=11, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foundation_multi_sig_spend_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_spend_txn_hash', index=11, + number=12, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foundation_multi_sig_vote_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_vote_txn_hash', index=12, + number=13, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unvotes', full_name='qrl.OptimizedAddressState.unvotes', index=13, + number=14, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_vote_stats', full_name='qrl.OptimizedAddressState.proposal_vote_stats', index=14, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6905, + serialized_end=7356, +) + + +_MULTISIGADDRESSSTATE = _descriptor.Descriptor( + name='MultiSigAddressState', + full_name='qrl.MultiSigAddressState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.MultiSigAddressState.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='creation_tx_hash', full_name='qrl.MultiSigAddressState.creation_tx_hash', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nonce', full_name='qrl.MultiSigAddressState.nonce', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.MultiSigAddressState.balance', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='signatories', full_name='qrl.MultiSigAddressState.signatories', index=4, + number=5, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weights', full_name='qrl.MultiSigAddressState.weights', index=5, + number=6, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='threshold', full_name='qrl.MultiSigAddressState.threshold', index=6, + number=7, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_hash_count', full_name='qrl.MultiSigAddressState.transaction_hash_count', index=7, + number=8, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi_sig_spend_count', full_name='qrl.MultiSigAddressState.multi_sig_spend_count', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi_sig_address_count', full_name='qrl.MultiSigAddressState.multi_sig_address_count', index=9, + number=10, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foundation_multi_sig_spend_txn_hash', full_name='qrl.MultiSigAddressState.foundation_multi_sig_spend_txn_hash', index=10, + number=11, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foundation_multi_sig_vote_txn_hash', full_name='qrl.MultiSigAddressState.foundation_multi_sig_vote_txn_hash', index=11, + number=12, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unvotes', full_name='qrl.MultiSigAddressState.unvotes', index=12, + number=13, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_vote_stats', full_name='qrl.MultiSigAddressState.proposal_vote_stats', index=13, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7359, + serialized_end=7762, +) + + +_MULTISIGADDRESSESLIST = _descriptor.Descriptor( + name='MultiSigAddressesList', + full_name='qrl.MultiSigAddressesList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='hashes', full_name='qrl.MultiSigAddressesList.hashes', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7764, + serialized_end=7803, +) + + +_DATALIST = _descriptor.Descriptor( + name='DataList', + full_name='qrl.DataList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='values', full_name='qrl.DataList.values', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7805, + serialized_end=7831, +) + + +_BITFIELD = _descriptor.Descriptor( + name='Bitfield', + full_name='qrl.Bitfield', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bitfields', full_name='qrl.Bitfield.bitfields', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7833, + serialized_end=7862, +) + + +_TRANSACTIONHASHLIST = _descriptor.Descriptor( + name='TransactionHashList', + full_name='qrl.TransactionHashList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='hashes', full_name='qrl.TransactionHashList.hashes', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7864, + serialized_end=7901, +) + + +_LATTICEPK = _descriptor.Descriptor( + name='LatticePK', + full_name='qrl.LatticePK', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='kyber_pk', full_name='qrl.LatticePK.kyber_pk', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dilithium_pk', full_name='qrl.LatticePK.dilithium_pk', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7903, + serialized_end=7954, +) + + +_ADDRESSAMOUNT = _descriptor.Descriptor( + name='AddressAmount', + full_name='qrl.AddressAmount', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.AddressAmount.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='qrl.AddressAmount.amount', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7956, + serialized_end=8004, +) + + +_BLOCKHEADER = _descriptor.Descriptor( + name='BlockHeader', + full_name='qrl.BlockHeader', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='hash_header', full_name='qrl.BlockHeader.hash_header', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_number', full_name='qrl.BlockHeader.block_number', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp_seconds', full_name='qrl.BlockHeader.timestamp_seconds', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hash_header_prev', full_name='qrl.BlockHeader.hash_header_prev', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reward_block', full_name='qrl.BlockHeader.reward_block', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reward_fee', full_name='qrl.BlockHeader.reward_fee', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='merkle_root', full_name='qrl.BlockHeader.merkle_root', index=6, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mining_nonce', full_name='qrl.BlockHeader.mining_nonce', index=7, + number=8, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extra_nonce', full_name='qrl.BlockHeader.extra_nonce', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8007, + serialized_end=8222, +) + + +_BLOCKHEADEREXTENDED = _descriptor.Descriptor( + name='BlockHeaderExtended', + full_name='qrl.BlockHeaderExtended', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='header', full_name='qrl.BlockHeaderExtended.header', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_count', full_name='qrl.BlockHeaderExtended.transaction_count', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8224, + serialized_end=8329, +) + + +_TRANSACTIONCOUNT_COUNTENTRY = _descriptor.Descriptor( + name='CountEntry', + full_name='qrl.TransactionCount.CountEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='qrl.TransactionCount.CountEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='qrl.TransactionCount.CountEntry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8400, + serialized_end=8444, +) + +_TRANSACTIONCOUNT = _descriptor.Descriptor( + name='TransactionCount', + full_name='qrl.TransactionCount', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='count', full_name='qrl.TransactionCount.count', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TRANSACTIONCOUNT_COUNTENTRY, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8331, + serialized_end=8444, +) + + +_TRANSACTIONEXTENDED = _descriptor.Descriptor( + name='TransactionExtended', + full_name='qrl.TransactionExtended', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='header', full_name='qrl.TransactionExtended.header', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tx', full_name='qrl.TransactionExtended.tx', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addr_from', full_name='qrl.TransactionExtended.addr_from', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='size', full_name='qrl.TransactionExtended.size', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp_seconds', full_name='qrl.TransactionExtended.timestamp_seconds', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8447, + serialized_end=8592, +) + + +_BLOCKEXTENDED = _descriptor.Descriptor( + name='BlockExtended', + full_name='qrl.BlockExtended', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='header', full_name='qrl.BlockExtended.header', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extended_transactions', full_name='qrl.BlockExtended.extended_transactions', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='genesis_balance', full_name='qrl.BlockExtended.genesis_balance', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='size', full_name='qrl.BlockExtended.size', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8595, + serialized_end=8761, +) + + +_BLOCK = _descriptor.Descriptor( + name='Block', + full_name='qrl.Block', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='header', full_name='qrl.Block.header', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transactions', full_name='qrl.Block.transactions', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='genesis_balance', full_name='qrl.Block.genesis_balance', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8763, + serialized_end=8890, +) + + +_GENESISBALANCE = _descriptor.Descriptor( + name='GenesisBalance', + full_name='qrl.GenesisBalance', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='qrl.GenesisBalance.address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='balance', full_name='qrl.GenesisBalance.balance', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8892, + serialized_end=8942, +) + + +_BLOCKMETADATALIST = _descriptor.Descriptor( + name='BlockMetaDataList', + full_name='qrl.BlockMetaDataList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='block_number_hashes', full_name='qrl.BlockMetaDataList.block_number_hashes', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8944, + serialized_end=9012, +) + + +_TRANSACTION_TRANSFER = _descriptor.Descriptor( + name='Transfer', + full_name='qrl.Transaction.Transfer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='addrs_to', full_name='qrl.Transaction.Transfer.addrs_to', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amounts', full_name='qrl.Transaction.Transfer.amounts', index=1, + number=2, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_data', full_name='qrl.Transaction.Transfer.message_data', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9772, + serialized_end=9839, +) + +_TRANSACTION_COINBASE = _descriptor.Descriptor( + name='CoinBase', + full_name='qrl.Transaction.CoinBase', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='addr_to', full_name='qrl.Transaction.CoinBase.addr_to', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='qrl.Transaction.CoinBase.amount', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9841, + serialized_end=9884, +) + +_TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( + name='LatticePublicKey', + full_name='qrl.Transaction.LatticePublicKey', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='pk1', full_name='qrl.Transaction.LatticePublicKey.pk1', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk2', full_name='qrl.Transaction.LatticePublicKey.pk2', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk3', full_name='qrl.Transaction.LatticePublicKey.pk3', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pk4', full_name='qrl.Transaction.LatticePublicKey.pk4', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9886, + serialized_end=9956, +) + +_TRANSACTION_MESSAGE = _descriptor.Descriptor( + name='Message', + full_name='qrl.Transaction.Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_hash', full_name='qrl.Transaction.Message.message_hash', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addr_to', full_name='qrl.Transaction.Message.addr_to', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9958, + serialized_end=10006, +) + +_TRANSACTION_TOKEN = _descriptor.Descriptor( + name='Token', + full_name='qrl.Transaction.Token', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='symbol', full_name='qrl.Transaction.Token.symbol', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='qrl.Transaction.Token.name', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='owner', full_name='qrl.Transaction.Token.owner', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='decimals', full_name='qrl.Transaction.Token.decimals', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='initial_balances', full_name='qrl.Transaction.Token.initial_balances', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10008, + serialized_end=10124, +) + +_TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( + name='TransferToken', + full_name='qrl.Transaction.TransferToken', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='token_txhash', full_name='qrl.Transaction.TransferToken.token_txhash', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addrs_to', full_name='qrl.Transaction.TransferToken.addrs_to', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amounts', full_name='qrl.Transaction.TransferToken.amounts', index=2, + number=3, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10126, + serialized_end=10198, +) + +_TRANSACTION_SLAVE = _descriptor.Descriptor( + name='Slave', + full_name='qrl.Transaction.Slave', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='slave_pks', full_name='qrl.Transaction.Slave.slave_pks', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='access_types', full_name='qrl.Transaction.Slave.access_types', index=1, + number=2, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10200, + serialized_end=10248, +) + +_TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( + name='MultiSigCreate', + full_name='qrl.Transaction.MultiSigCreate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='signatories', full_name='qrl.Transaction.MultiSigCreate.signatories', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weights', full_name='qrl.Transaction.MultiSigCreate.weights', index=1, + number=2, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='threshold', full_name='qrl.Transaction.MultiSigCreate.threshold', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10250, + serialized_end=10323, +) + +_TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( + name='MultiSigSpend', + full_name='qrl.Transaction.MultiSigSpend', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='multi_sig_address', full_name='qrl.Transaction.MultiSigSpend.multi_sig_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='addrs_to', full_name='qrl.Transaction.MultiSigSpend.addrs_to', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amounts', full_name='qrl.Transaction.MultiSigSpend.amounts', index=2, + number=3, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='expiry_block_number', full_name='qrl.Transaction.MultiSigSpend.expiry_block_number', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10325, + serialized_end=10431, +) + +_TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( + name='MultiSigVote', + full_name='qrl.Transaction.MultiSigVote', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='shared_key', full_name='qrl.Transaction.MultiSigVote.shared_key', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unvote', full_name='qrl.Transaction.MultiSigVote.unvote', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='prev_tx_hash', full_name='qrl.Transaction.MultiSigVote.prev_tx_hash', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10433, + serialized_end=10505, +) + +_TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( + name='QIP', + full_name='qrl.Transaction.ProposalCreate.QIP', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='qip_link', full_name='qrl.Transaction.ProposalCreate.QIP.qip_link', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10742, + serialized_end=10765, +) + +_TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( + name='Config', + full_name='qrl.Transaction.ProposalCreate.Config', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='changes_bitfield', full_name='qrl.Transaction.ProposalCreate.Config.changes_bitfield', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reorg_limit', full_name='qrl.Transaction.ProposalCreate.Config.reorg_limit', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_coin_supply', full_name='qrl.Transaction.ProposalCreate.Config.max_coin_supply', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='complete_emission_time_span_in_years', full_name='qrl.Transaction.ProposalCreate.Config.complete_emission_time_span_in_years', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mining_nonce_offset', full_name='qrl.Transaction.ProposalCreate.Config.mining_nonce_offset', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extra_nonce_offset', full_name='qrl.Transaction.ProposalCreate.Config.extra_nonce_offset', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mining_blob_size_in_bytes', full_name='qrl.Transaction.ProposalCreate.Config.mining_blob_size_in_bytes', index=6, + number=7, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_timing_in_seconds', full_name='qrl.Transaction.ProposalCreate.Config.block_timing_in_seconds', index=7, + number=8, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number_of_blocks_analyze', full_name='qrl.Transaction.ProposalCreate.Config.number_of_blocks_analyze', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_size_multiplier', full_name='qrl.Transaction.ProposalCreate.Config.block_size_multiplier', index=9, + number=10, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_min_size_limit_in_bytes', full_name='qrl.Transaction.ProposalCreate.Config.block_min_size_limit_in_bytes', index=10, + number=11, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_multi_output_limit', full_name='qrl.Transaction.ProposalCreate.Config.transaction_multi_output_limit', index=11, + number=12, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_max_length', full_name='qrl.Transaction.ProposalCreate.Config.message_max_length', index=12, + number=13, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='token_symbol_max_length', full_name='qrl.Transaction.ProposalCreate.Config.token_symbol_max_length', index=13, + number=14, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='token_name_max_length', full_name='qrl.Transaction.ProposalCreate.Config.token_name_max_length', index=14, + number=15, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lattice_pk1_max_length', full_name='qrl.Transaction.ProposalCreate.Config.lattice_pk1_max_length', index=15, + number=16, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lattice_pk2_max_length', full_name='qrl.Transaction.ProposalCreate.Config.lattice_pk2_max_length', index=16, + number=17, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lattice_pk3_max_length', full_name='qrl.Transaction.ProposalCreate.Config.lattice_pk3_max_length', index=17, + number=18, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lattice_pk4_max_length', full_name='qrl.Transaction.ProposalCreate.Config.lattice_pk4_max_length', index=18, + number=19, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foundation_multi_sig_address_threshold_percentage', full_name='qrl.Transaction.ProposalCreate.Config.foundation_multi_sig_address_threshold_percentage', index=19, + number=20, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_threshold_per', full_name='qrl.Transaction.ProposalCreate.Config.proposal_threshold_per', index=20, + number=21, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_default_options', full_name='qrl.Transaction.ProposalCreate.Config.proposal_default_options', index=21, + number=22, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='description_max_length', full_name='qrl.Transaction.ProposalCreate.Config.description_max_length', index=22, + number=23, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options_max_number', full_name='qrl.Transaction.ProposalCreate.Config.options_max_number', index=23, + number=24, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='option_max_text_length', full_name='qrl.Transaction.ProposalCreate.Config.option_max_text_length', index=24, + number=25, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_config_activation_delay', full_name='qrl.Transaction.ProposalCreate.Config.proposal_config_activation_delay', index=25, + number=26, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='N_measurement', full_name='qrl.Transaction.ProposalCreate.Config.N_measurement', index=26, + number=27, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='kp', full_name='qrl.Transaction.ProposalCreate.Config.kp', index=27, + number=28, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10768, + serialized_end=11677, +) + +_TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( + name='Other', + full_name='qrl.Transaction.ProposalCreate.Other', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='options', full_name='qrl.Transaction.ProposalCreate.Other.options', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11679, + serialized_end=11703, +) + +_TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( + name='ProposalCreate', + full_name='qrl.Transaction.ProposalCreate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='expiry_block_number', full_name='qrl.Transaction.ProposalCreate.expiry_block_number', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='description', full_name='qrl.Transaction.ProposalCreate.description', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='qip', full_name='qrl.Transaction.ProposalCreate.qip', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='config', full_name='qrl.Transaction.ProposalCreate.config', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='other', full_name='qrl.Transaction.ProposalCreate.other', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TRANSACTION_PROPOSALCREATE_QIP, _TRANSACTION_PROPOSALCREATE_CONFIG, _TRANSACTION_PROPOSALCREATE_OTHER, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', + index=0, containing_type=None, fields=[]), + ], + serialized_start=10508, + serialized_end=11719, +) + +_TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( + name='ProposalVote', + full_name='qrl.Transaction.ProposalVote', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='shared_key', full_name='qrl.Transaction.ProposalVote.shared_key', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='option', full_name='qrl.Transaction.ProposalVote.option', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11721, + serialized_end=11771, +) + +_TRANSACTION = _descriptor.Descriptor( + name='Transaction', + full_name='qrl.Transaction', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='master_addr', full_name='qrl.Transaction.master_addr', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='qrl.Transaction.fee', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='public_key', full_name='qrl.Transaction.public_key', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='signature', full_name='qrl.Transaction.signature', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nonce', full_name='qrl.Transaction.nonce', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction_hash', full_name='qrl.Transaction.transaction_hash', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transfer', full_name='qrl.Transaction.transfer', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='coinbase', full_name='qrl.Transaction.coinbase', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.BlockHeader.block_number', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='latticePK', full_name='qrl.Transaction.latticePK', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timestamp_seconds', full_name='qrl.BlockHeader.timestamp_seconds', index=2, - number=3, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='message', full_name='qrl.Transaction.message', index=9, + number=10, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='hash_header_prev', full_name='qrl.BlockHeader.hash_header_prev', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='token', full_name='qrl.Transaction.token', index=10, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='reward_block', full_name='qrl.BlockHeader.reward_block', index=4, - number=5, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='transfer_token', full_name='qrl.Transaction.transfer_token', index=11, + number=12, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='reward_fee', full_name='qrl.BlockHeader.reward_fee', index=5, - number=6, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='slave', full_name='qrl.Transaction.slave', index=12, + number=13, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='merkle_root', full_name='qrl.BlockHeader.merkle_root', index=6, - number=7, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='multi_sig_create', full_name='qrl.Transaction.multi_sig_create', index=13, + number=14, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='mining_nonce', full_name='qrl.BlockHeader.mining_nonce', index=7, - number=8, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, + name='multi_sig_spend', full_name='qrl.Transaction.multi_sig_spend', index=14, + number=15, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='extra_nonce', full_name='qrl.BlockHeader.extra_nonce', index=8, - number=9, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='multi_sig_vote', full_name='qrl.Transaction.multi_sig_vote', index=15, + number=16, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=4684, - serialized_end=4899, -) - - -_BLOCKHEADEREXTENDED = _descriptor.Descriptor( - name='BlockHeaderExtended', - full_name='qrl.BlockHeaderExtended', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ _descriptor.FieldDescriptor( - name='header', full_name='qrl.BlockHeaderExtended.header', index=0, - number=1, type=11, cpp_type=10, label=1, + name='proposal_create', full_name='qrl.Transaction.proposal_create', index=16, + number=17, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='transaction_count', full_name='qrl.BlockHeaderExtended.transaction_count', index=1, - number=2, type=11, cpp_type=10, label=1, + name='proposal_vote', full_name='qrl.Transaction.proposal_vote', index=17, + number=18, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -2571,7 +5284,7 @@ ], extensions=[ ], - nested_types=[], + nested_types=[_TRANSACTION_TRANSFER, _TRANSACTION_COINBASE, _TRANSACTION_LATTICEPUBLICKEY, _TRANSACTION_MESSAGE, _TRANSACTION_TOKEN, _TRANSACTION_TRANSFERTOKEN, _TRANSACTION_SLAVE, _TRANSACTION_MULTISIGCREATE, _TRANSACTION_MULTISIGSPEND, _TRANSACTION_MULTISIGVOTE, _TRANSACTION_PROPOSALCREATE, _TRANSACTION_PROPOSALVOTE, ], enum_types=[ ], options=None, @@ -2579,119 +5292,75 @@ syntax='proto3', extension_ranges=[], oneofs=[ + _descriptor.OneofDescriptor( + name='transactionType', full_name='qrl.Transaction.transactionType', + index=0, containing_type=None, fields=[]), ], - serialized_start=4901, - serialized_end=5006, + serialized_start=9015, + serialized_end=11790, ) -_TRANSACTIONCOUNT_COUNTENTRY = _descriptor.Descriptor( - name='CountEntry', - full_name='qrl.TransactionCount.CountEntry', +_VOTESTATS = _descriptor.Descriptor( + name='VoteStats', + full_name='qrl.VoteStats', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='key', full_name='qrl.TransactionCount.CountEntry.key', index=0, - number=1, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, + name='multi_sig_address', full_name='qrl.VoteStats.multi_sig_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='value', full_name='qrl.TransactionCount.CountEntry.value', index=1, - number=2, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, + name='shared_key', full_name='qrl.VoteStats.shared_key', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=5077, - serialized_end=5121, -) - -_TRANSACTIONCOUNT = _descriptor.Descriptor( - name='TransactionCount', - full_name='qrl.TransactionCount', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ _descriptor.FieldDescriptor( - name='count', full_name='qrl.TransactionCount.count', index=0, - number=1, type=11, cpp_type=10, label=3, + name='signatories', full_name='qrl.VoteStats.signatories', index=2, + number=3, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[_TRANSACTIONCOUNT_COUNTENTRY, ], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=5008, - serialized_end=5121, -) - - -_TRANSACTIONEXTENDED = _descriptor.Descriptor( - name='TransactionExtended', - full_name='qrl.TransactionExtended', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ _descriptor.FieldDescriptor( - name='header', full_name='qrl.TransactionExtended.header', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='tx_hashes', full_name='qrl.VoteStats.tx_hashes', index=3, + number=4, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='tx', full_name='qrl.TransactionExtended.tx', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='unvotes', full_name='qrl.VoteStats.unvotes', index=4, + number=5, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='addr_from', full_name='qrl.TransactionExtended.addr_from', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='expiry_block_number', full_name='qrl.VoteStats.expiry_block_number', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='size', full_name='qrl.TransactionExtended.size', index=3, - number=4, type=4, cpp_type=4, label=1, + name='total_weight', full_name='qrl.VoteStats.total_weight', index=6, + number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timestamp_seconds', full_name='qrl.TransactionExtended.timestamp_seconds', index=4, - number=5, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='executed', full_name='qrl.VoteStats.executed', index=7, + number=8, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2707,42 +5376,63 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5124, - serialized_end=5269, + serialized_start=11793, + serialized_end=11977, ) -_BLOCKEXTENDED = _descriptor.Descriptor( - name='BlockExtended', - full_name='qrl.BlockExtended', +_PROPOSALVOTESTATS = _descriptor.Descriptor( + name='ProposalVoteStats', + full_name='qrl.ProposalVoteStats', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='header', full_name='qrl.BlockExtended.header', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='addr_from', full_name='qrl.ProposalVoteStats.addr_from', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='extended_transactions', full_name='qrl.BlockExtended.extended_transactions', index=1, - number=2, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='shared_key', full_name='qrl.ProposalVoteStats.shared_key', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='genesis_balance', full_name='qrl.BlockExtended.genesis_balance', index=2, - number=3, type=11, cpp_type=10, label=3, + name='proposal_type', full_name='qrl.ProposalVoteStats.proposal_type', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weight_by_option', full_name='qrl.ProposalVoteStats.weight_by_option', index=3, + number=4, type=4, cpp_type=4, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='size', full_name='qrl.BlockExtended.size', index=3, - number=4, type=4, cpp_type=4, label=1, + name='expiry_block_number', full_name='qrl.ProposalVoteStats.expiry_block_number', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='executed', full_name='qrl.ProposalVoteStats.executed', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number_of_tx_hashes', full_name='qrl.ProposalVoteStats.number_of_tx_hashes', index=6, + number=7, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -2759,36 +5449,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5272, - serialized_end=5438, + serialized_start=11980, + serialized_end=12163, ) -_BLOCK = _descriptor.Descriptor( - name='Block', - full_name='qrl.Block', +_PROPOSALRECORD = _descriptor.Descriptor( + name='ProposalRecord', + full_name='qrl.ProposalRecord', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='header', full_name='qrl.Block.header', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='transactions', full_name='qrl.Block.transactions', index=1, - number=2, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='genesis_balance', full_name='qrl.Block.genesis_balance', index=2, - number=3, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='number_of_tx_hashes', full_name='qrl.ProposalRecord.number_of_tx_hashes', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2804,29 +5480,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5440, - serialized_end=5567, + serialized_start=12165, + serialized_end=12210, ) -_GENESISBALANCE = _descriptor.Descriptor( - name='GenesisBalance', - full_name='qrl.GenesisBalance', +_TOKENLIST = _descriptor.Descriptor( + name='TokenList', + full_name='qrl.TokenList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.GenesisBalance.address', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='balance', full_name='qrl.GenesisBalance.balance', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='token_txhash', full_name='qrl.TokenList.token_txhash', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2842,22 +5511,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5569, - serialized_end=5619, + serialized_start=12212, + serialized_end=12245, ) -_BLOCKMETADATALIST = _descriptor.Descriptor( - name='BlockMetaDataList', - full_name='qrl.BlockMetaDataList', +_TOKENBALANCE = _descriptor.Descriptor( + name='TokenBalance', + full_name='qrl.TokenBalance', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block_number_hashes', full_name='qrl.BlockMetaDataList.block_number_hashes', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='balance', full_name='qrl.TokenBalance.balance', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='decimals', full_name='qrl.TokenBalance.decimals', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='delete', full_name='qrl.TokenBalance.delete', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2873,29 +5556,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5621, - serialized_end=5689, + serialized_start=12247, + serialized_end=12312, ) - - -_TRANSACTION_TRANSFER = _descriptor.Descriptor( - name='Transfer', - full_name='qrl.Transaction.Transfer', + + +_SLAVEMETADATA = _descriptor.Descriptor( + name='SlaveMetadata', + full_name='qrl.SlaveMetadata', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addrs_to', full_name='qrl.Transaction.Transfer.addrs_to', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='access_type', full_name='qrl.SlaveMetadata.access_type', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='amounts', full_name='qrl.Transaction.Transfer.amounts', index=1, - number=2, type=4, cpp_type=4, label=3, - has_default_value=False, default_value=[], + name='tx_hash', full_name='qrl.SlaveMetadata.tx_hash', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='delete', full_name='qrl.SlaveMetadata.delete', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2911,28 +5601,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6156, - serialized_end=6201, + serialized_start=12314, + serialized_end=12383, ) -_TRANSACTION_COINBASE = _descriptor.Descriptor( - name='CoinBase', - full_name='qrl.Transaction.CoinBase', + +_LATTICEPKMETADATA = _descriptor.Descriptor( + name='LatticePKMetadata', + full_name='qrl.LatticePKMetadata', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addr_to', full_name='qrl.Transaction.CoinBase.addr_to', index=0, - number=1, type=12, cpp_type=9, label=1, + name='enabled', full_name='qrl.LatticePKMetadata.enabled', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tx_hash', full_name='qrl.LatticePKMetadata.tx_hash', index=1, + number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='amount', full_name='qrl.Transaction.CoinBase.amount', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='delete', full_name='qrl.LatticePKMetadata.delete', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2948,28 +5646,29 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6203, - serialized_end=6246, + serialized_start=12385, + serialized_end=12454, ) -_TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( - name='LatticePublicKey', - full_name='qrl.Transaction.LatticePublicKey', + +_TOKENMETADATA = _descriptor.Descriptor( + name='TokenMetadata', + full_name='qrl.TokenMetadata', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='kyber_pk', full_name='qrl.Transaction.LatticePublicKey.kyber_pk', index=0, + name='token_txhash', full_name='qrl.TokenMetadata.token_txhash', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='dilithium_pk', full_name='qrl.Transaction.LatticePublicKey.dilithium_pk', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='transfer_token_tx_hashes', full_name='qrl.TokenMetadata.transfer_token_tx_hashes', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -2985,20 +5684,21 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6248, - serialized_end=6306, + serialized_start=12456, + serialized_end=12527, ) -_TRANSACTION_MESSAGE = _descriptor.Descriptor( - name='Message', - full_name='qrl.Transaction.Message', + +_ENCRYPTEDEPHEMERALMESSAGE_CHANNEL = _descriptor.Descriptor( + name='Channel', + full_name='qrl.EncryptedEphemeralMessage.Channel', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='message_hash', full_name='qrl.Transaction.Message.message_hash', index=0, - number=1, type=12, cpp_type=9, label=1, + name='enc_aes256_symkey', full_name='qrl.EncryptedEphemeralMessage.Channel.enc_aes256_symkey', index=0, + number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3015,56 +5715,63 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6308, - serialized_end=6339, + serialized_start=12690, + serialized_end=12726, ) -_TRANSACTION_TOKEN = _descriptor.Descriptor( - name='Token', - full_name='qrl.Transaction.Token', +_ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( + name='EncryptedEphemeralMessage', + full_name='qrl.EncryptedEphemeralMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='symbol', full_name='qrl.Transaction.Token.symbol', index=0, + name='msg_id', full_name='qrl.EncryptedEphemeralMessage.msg_id', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='name', full_name='qrl.Transaction.Token.name', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='ttl', full_name='qrl.EncryptedEphemeralMessage.ttl', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='owner', full_name='qrl.Transaction.Token.owner', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='ttr', full_name='qrl.EncryptedEphemeralMessage.ttr', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='decimals', full_name='qrl.Transaction.Token.decimals', index=3, - number=4, type=4, cpp_type=4, label=1, + name='channel', full_name='qrl.EncryptedEphemeralMessage.channel', index=3, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nonce', full_name='qrl.EncryptedEphemeralMessage.nonce', index=4, + number=6, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='initial_balances', full_name='qrl.Transaction.Token.initial_balances', index=4, - number=5, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='payload', full_name='qrl.EncryptedEphemeralMessage.payload', index=5, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), ], extensions=[ ], - nested_types=[], + nested_types=[_ENCRYPTEDEPHEMERALMESSAGE_CHANNEL, ], enum_types=[ ], options=None, @@ -3073,34 +5780,21 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6341, - serialized_end=6457, + serialized_start=12530, + serialized_end=12726, ) -_TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( - name='TransferToken', - full_name='qrl.Transaction.TransferToken', + +_ADDRESSLIST = _descriptor.Descriptor( + name='AddressList', + full_name='qrl.AddressList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='token_txhash', full_name='qrl.Transaction.TransferToken.token_txhash', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='addrs_to', full_name='qrl.Transaction.TransferToken.addrs_to', index=1, - number=2, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='amounts', full_name='qrl.Transaction.TransferToken.amounts', index=2, - number=3, type=4, cpp_type=4, label=3, + name='addresses', full_name='qrl.AddressList.addresses', index=0, + number=1, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3117,28 +5811,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6459, - serialized_end=6531, + serialized_start=12728, + serialized_end=12760, ) -_TRANSACTION_SLAVE = _descriptor.Descriptor( - name='Slave', - full_name='qrl.Transaction.Slave', + +_BLOCKHEIGHTDATA = _descriptor.Descriptor( + name='BlockHeightData', + full_name='qrl.BlockHeightData', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='slave_pks', full_name='qrl.Transaction.Slave.slave_pks', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='block_number', full_name='qrl.BlockHeightData.block_number', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='access_types', full_name='qrl.Transaction.Slave.access_types', index=1, - number=2, type=13, cpp_type=3, label=3, - has_default_value=False, default_value=[], + name='block_headerhash', full_name='qrl.BlockHeightData.block_headerhash', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cumulative_difficulty', full_name='qrl.BlockHeightData.cumulative_difficulty', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3154,104 +5856,125 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6533, - serialized_end=6581, + serialized_start=12762, + serialized_end=12858, ) -_TRANSACTION = _descriptor.Descriptor( - name='Transaction', - full_name='qrl.Transaction', + +_BLOCKMETADATA = _descriptor.Descriptor( + name='BlockMetaData', + full_name='qrl.BlockMetaData', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='master_addr', full_name='qrl.Transaction.master_addr', index=0, + name='block_difficulty', full_name='qrl.BlockMetaData.block_difficulty', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='fee', full_name='qrl.Transaction.fee', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='public_key', full_name='qrl.Transaction.public_key', index=2, - number=3, type=12, cpp_type=9, label=1, + name='cumulative_difficulty', full_name='qrl.BlockMetaData.cumulative_difficulty', index=1, + number=2, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='signature', full_name='qrl.Transaction.signature', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='child_headerhashes', full_name='qrl.BlockMetaData.child_headerhashes', index=2, + number=3, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='nonce', full_name='qrl.Transaction.nonce', index=4, - number=5, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='last_N_headerhashes', full_name='qrl.BlockMetaData.last_N_headerhashes', index=3, + number=4, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12861, + serialized_end=12990, +) + + +_BLOCKNUMBERMAPPING = _descriptor.Descriptor( + name='BlockNumberMapping', + full_name='qrl.BlockNumberMapping', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='transaction_hash', full_name='qrl.Transaction.transaction_hash', index=5, - number=6, type=12, cpp_type=9, label=1, + name='headerhash', full_name='qrl.BlockNumberMapping.headerhash', index=0, + number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='transfer', full_name='qrl.Transaction.transfer', index=6, - number=7, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='coinbase', full_name='qrl.Transaction.coinbase', index=7, - number=8, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='latticePK', full_name='qrl.Transaction.latticePK', index=8, - number=9, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='message', full_name='qrl.Transaction.message', index=9, - number=10, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='prev_headerhash', full_name='qrl.BlockNumberMapping.prev_headerhash', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12992, + serialized_end=13057, +) + + +_PEERSTAT = _descriptor.Descriptor( + name='PeerStat', + full_name='qrl.PeerStat', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='token', full_name='qrl.Transaction.token', index=10, - number=11, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='peer_ip', full_name='qrl.PeerStat.peer_ip', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='transfer_token', full_name='qrl.Transaction.transfer_token', index=11, - number=12, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='port', full_name='qrl.PeerStat.port', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='slave', full_name='qrl.Transaction.slave', index=12, - number=13, type=11, cpp_type=10, label=1, + name='node_chain_state', full_name='qrl.PeerStat.node_chain_state', index=2, + number=3, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3259,7 +5982,7 @@ ], extensions=[ ], - nested_types=[_TRANSACTION_TRANSFER, _TRANSACTION_COINBASE, _TRANSACTION_LATTICEPUBLICKEY, _TRANSACTION_MESSAGE, _TRANSACTION_TOKEN, _TRANSACTION_TRANSFERTOKEN, _TRANSACTION_SLAVE, ], + nested_types=[], enum_types=[ ], options=None, @@ -3267,26 +5990,51 @@ syntax='proto3', extension_ranges=[], oneofs=[ - _descriptor.OneofDescriptor( - name='transactionType', full_name='qrl.Transaction.transactionType', - index=0, containing_type=None, fields=[]), ], - serialized_start=5692, - serialized_end=6600, + serialized_start=13059, + serialized_end=13147, ) -_TOKENLIST = _descriptor.Descriptor( - name='TokenList', - full_name='qrl.TokenList', +_NODECHAINSTATE = _descriptor.Descriptor( + name='NodeChainState', + full_name='qrl.NodeChainState', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='token_txhash', full_name='qrl.TokenList.token_txhash', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='block_number', full_name='qrl.NodeChainState.block_number', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='header_hash', full_name='qrl.NodeChainState.header_hash', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cumulative_difficulty', full_name='qrl.NodeChainState.cumulative_difficulty', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='qrl.NodeChainState.version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='qrl.NodeChainState.timestamp', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3302,27 +6050,27 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6602, - serialized_end=6635, + serialized_start=13149, + serialized_end=13275, ) -_TOKENMETADATA = _descriptor.Descriptor( - name='TokenMetadata', - full_name='qrl.TokenMetadata', +_NODEHEADERHASH = _descriptor.Descriptor( + name='NodeHeaderHash', + full_name='qrl.NodeHeaderHash', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='token_txhash', full_name='qrl.TokenMetadata.token_txhash', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='block_number', full_name='qrl.NodeHeaderHash.block_number', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='transfer_token_tx_hashes', full_name='qrl.TokenMetadata.transfer_token_tx_hashes', index=1, + name='headerhashes', full_name='qrl.NodeHeaderHash.headerhashes', index=1, number=2, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, @@ -3340,22 +6088,22 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6637, - serialized_end=6708, + serialized_start=13277, + serialized_end=13337, ) -_ENCRYPTEDEPHEMERALMESSAGE_CHANNEL = _descriptor.Descriptor( - name='Channel', - full_name='qrl.EncryptedEphemeralMessage.Channel', +_P2PACKNOWLEDGEMENT = _descriptor.Descriptor( + name='P2PAcknowledgement', + full_name='qrl.P2PAcknowledgement', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='enc_aes256_symkey', full_name='qrl.EncryptedEphemeralMessage.Channel.enc_aes256_symkey', index=0, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='bytes_processed', full_name='qrl.P2PAcknowledgement.bytes_processed', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3371,63 +6119,57 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6871, - serialized_end=6907, + serialized_start=13339, + serialized_end=13384, ) -_ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( - name='EncryptedEphemeralMessage', - full_name='qrl.EncryptedEphemeralMessage', + +_PEERINFO = _descriptor.Descriptor( + name='PeerInfo', + full_name='qrl.PeerInfo', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='msg_id', full_name='qrl.EncryptedEphemeralMessage.msg_id', index=0, + name='peer_ip', full_name='qrl.PeerInfo.peer_ip', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ttl', full_name='qrl.EncryptedEphemeralMessage.ttl', index=1, - number=2, type=4, cpp_type=4, label=1, + name='port', full_name='qrl.PeerInfo.port', index=1, + number=2, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ttr', full_name='qrl.EncryptedEphemeralMessage.ttr', index=2, - number=3, type=4, cpp_type=4, label=1, + name='banned_timestamp', full_name='qrl.PeerInfo.banned_timestamp', index=2, + number=3, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='channel', full_name='qrl.EncryptedEphemeralMessage.channel', index=3, - number=5, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='nonce', full_name='qrl.EncryptedEphemeralMessage.nonce', index=4, - number=6, type=4, cpp_type=4, label=1, + name='credibility', full_name='qrl.PeerInfo.credibility', index=3, + number=4, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='payload', full_name='qrl.EncryptedEphemeralMessage.payload', index=5, - number=7, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='last_connections_timestamp', full_name='qrl.PeerInfo.last_connections_timestamp', index=4, + number=5, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), ], extensions=[ ], - nested_types=[_ENCRYPTEDEPHEMERALMESSAGE_CHANNEL, ], + nested_types=[], enum_types=[ ], options=None, @@ -3436,21 +6178,21 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6711, - serialized_end=6907, + serialized_start=13386, + serialized_end=13510, ) -_ADDRESSLIST = _descriptor.Descriptor( - name='AddressList', - full_name='qrl.AddressList', +_PEERS = _descriptor.Descriptor( + name='Peers', + full_name='qrl.Peers', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addresses', full_name='qrl.AddressList.addresses', index=0, - number=1, type=12, cpp_type=9, label=3, + name='peer_info_list', full_name='qrl.Peers.peer_info_list', index=0, + number=1, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3467,36 +6209,36 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6909, - serialized_end=6941, + serialized_start=13512, + serialized_end=13558, ) -_BLOCKHEIGHTDATA = _descriptor.Descriptor( - name='BlockHeightData', - full_name='qrl.BlockHeightData', +_DEVCONFIG_CHAIN = _descriptor.Descriptor( + name='Chain', + full_name='qrl.DevConfig.Chain', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.BlockHeightData.block_number', index=0, + name='reorg_limit', full_name='qrl.DevConfig.Chain.reorg_limit', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='block_headerhash', full_name='qrl.BlockHeightData.block_headerhash', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='max_coin_supply', full_name='qrl.DevConfig.Chain.max_coin_supply', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='cumulative_difficulty', full_name='qrl.BlockHeightData.cumulative_difficulty', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='complete_emission_time_span_in_years', full_name='qrl.DevConfig.Chain.complete_emission_time_span_in_years', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3512,43 +6254,153 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6943, - serialized_end=7039, + serialized_start=13846, + serialized_end=13945, ) +_DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( + name='BlockSizeController', + full_name='qrl.DevConfig.Block.BlockSizeController', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='number_of_blocks_analyze', full_name='qrl.DevConfig.Block.BlockSizeController.number_of_blocks_analyze', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='size_multiplier', full_name='qrl.DevConfig.Block.BlockSizeController.size_multiplier', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_min_size_limit_in_bytes', full_name='qrl.DevConfig.Block.BlockSizeController.block_min_size_limit_in_bytes', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14155, + serialized_end=14274, +) -_BLOCKMETADATA = _descriptor.Descriptor( - name='BlockMetaData', - full_name='qrl.BlockMetaData', +_DEVCONFIG_BLOCK = _descriptor.Descriptor( + name='Block', + full_name='qrl.DevConfig.Block', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block_difficulty', full_name='qrl.BlockMetaData.block_difficulty', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='mining_nonce_offset', full_name='qrl.DevConfig.Block.mining_nonce_offset', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='cumulative_difficulty', full_name='qrl.BlockMetaData.cumulative_difficulty', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='extra_nonce_offset', full_name='qrl.DevConfig.Block.extra_nonce_offset', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='child_headerhashes', full_name='qrl.BlockMetaData.child_headerhashes', index=2, - number=3, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='mining_blob_size_in_bytes', full_name='qrl.DevConfig.Block.mining_blob_size_in_bytes', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_timing_in_seconds', full_name='qrl.DevConfig.Block.block_timing_in_seconds', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_size_controller', full_name='qrl.DevConfig.Block.block_size_controller', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13948, + serialized_end=14274, +) + +_DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( + name='Message', + full_name='qrl.DevConfig.Transaction.Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='max_length', full_name='qrl.DevConfig.Transaction.Message.max_length', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14656, + serialized_end=14685, +) + +_DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( + name='Slave', + full_name='qrl.DevConfig.Transaction.Slave', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ _descriptor.FieldDescriptor( - name='last_N_headerhashes', full_name='qrl.BlockMetaData.last_N_headerhashes', index=3, - number=4, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='slave_pk_max_length', full_name='qrl.DevConfig.Transaction.Slave.slave_pk_max_length', index=0, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3564,29 +6416,28 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7042, - serialized_end=7171, + serialized_start=14687, + serialized_end=14723, ) - -_BLOCKNUMBERMAPPING = _descriptor.Descriptor( - name='BlockNumberMapping', - full_name='qrl.BlockNumberMapping', +_DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( + name='Token', + full_name='qrl.DevConfig.Transaction.Token', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='headerhash', full_name='qrl.BlockNumberMapping.headerhash', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='symbol_max_length', full_name='qrl.DevConfig.Transaction.Token.symbol_max_length', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='prev_headerhash', full_name='qrl.BlockNumberMapping.prev_headerhash', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='name_max_length', full_name='qrl.DevConfig.Transaction.Token.name_max_length', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3602,41 +6453,40 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7173, - serialized_end=7238, + serialized_start=14725, + serialized_end=14784, ) - -_STATELOADER = _descriptor.Descriptor( - name='StateLoader', - full_name='qrl.StateLoader', +_DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( + name='Lattice', + full_name='qrl.DevConfig.Transaction.Lattice', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='addresses', full_name='qrl.StateLoader.addresses', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='pk1_max_length', full_name='qrl.DevConfig.Transaction.Lattice.pk1_max_length', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='token_txhash', full_name='qrl.StateLoader.token_txhash', index=1, - number=2, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='pk2_max_length', full_name='qrl.DevConfig.Transaction.Lattice.pk2_max_length', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='txhash', full_name='qrl.StateLoader.txhash', index=2, - number=3, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='pk3_max_length', full_name='qrl.DevConfig.Transaction.Lattice.pk3_max_length', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='total_coin_supply', full_name='qrl.StateLoader.total_coin_supply', index=3, + name='pk4_max_length', full_name='qrl.DevConfig.Transaction.Lattice.pk4_max_length', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, @@ -3654,22 +6504,21 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7240, - serialized_end=7337, + serialized_start=14786, + serialized_end=14891, ) - -_STATEOBJECTS = _descriptor.Descriptor( - name='StateObjects', - full_name='qrl.StateObjects', +_DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( + name='FoundationMultiSig', + full_name='qrl.DevConfig.Transaction.FoundationMultiSig', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='state_loaders', full_name='qrl.StateObjects.state_loaders', index=0, - number=1, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='threshold_percentage', full_name='qrl.DevConfig.Transaction.FoundationMultiSig.threshold_percentage', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3685,60 +6534,56 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7339, - serialized_end=7376, -) - - -_LRUSTATECACHE = _descriptor.Descriptor( - name='LRUStateCache', - full_name='qrl.LRUStateCache', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=7378, - serialized_end=7393, + serialized_start=14893, + serialized_end=14943, ) - -_PEERSTAT = _descriptor.Descriptor( - name='PeerStat', - full_name='qrl.PeerStat', +_DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( + name='Proposal', + full_name='qrl.DevConfig.Transaction.Proposal', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='peer_ip', full_name='qrl.PeerStat.peer_ip', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='threshold_per', full_name='qrl.DevConfig.Transaction.Proposal.threshold_per', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='port', full_name='qrl.PeerStat.port', index=1, - number=2, type=13, cpp_type=3, label=1, + name='default_options', full_name='qrl.DevConfig.Transaction.Proposal.default_options', index=1, + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='description_max_length', full_name='qrl.DevConfig.Transaction.Proposal.description_max_length', index=2, + number=3, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='node_chain_state', full_name='qrl.PeerStat.node_chain_state', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='options_max_number', full_name='qrl.DevConfig.Transaction.Proposal.options_max_number', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='option_max_text_length', full_name='qrl.DevConfig.Transaction.Proposal.option_max_text_length', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_config_activation_delay', full_name='qrl.DevConfig.Transaction.Proposal.proposal_config_activation_delay', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -3754,95 +6599,70 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7395, - serialized_end=7483, + serialized_start=14946, + serialized_end=15138, ) - -_NODECHAINSTATE = _descriptor.Descriptor( - name='NodeChainState', - full_name='qrl.NodeChainState', +_DEVCONFIG_TRANSACTION = _descriptor.Descriptor( + name='Transaction', + full_name='qrl.DevConfig.Transaction', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.NodeChainState.block_number', index=0, + name='multi_output_limit', full_name='qrl.DevConfig.Transaction.multi_output_limit', index=0, number=1, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='header_hash', full_name='qrl.NodeChainState.header_hash', index=1, - number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='message', full_name='qrl.DevConfig.Transaction.message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='cumulative_difficulty', full_name='qrl.NodeChainState.cumulative_difficulty', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), + name='slave', full_name='qrl.DevConfig.Transaction.slave', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='version', full_name='qrl.NodeChainState.version', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + name='token', full_name='qrl.DevConfig.Transaction.token', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='timestamp', full_name='qrl.NodeChainState.timestamp', index=4, - number=5, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='lattice', full_name='qrl.DevConfig.Transaction.lattice', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=7485, - serialized_end=7611, -) - - -_NODEHEADERHASH = _descriptor.Descriptor( - name='NodeHeaderHash', - full_name='qrl.NodeHeaderHash', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ _descriptor.FieldDescriptor( - name='block_number', full_name='qrl.NodeHeaderHash.block_number', index=0, - number=1, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='foundation_multi_sig', full_name='qrl.DevConfig.Transaction.foundation_multi_sig', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='headerhashes', full_name='qrl.NodeHeaderHash.headerhashes', index=1, - number=2, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='proposal', full_name='qrl.DevConfig.Transaction.proposal', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), ], extensions=[ ], - nested_types=[], + nested_types=[_DEVCONFIG_TRANSACTION_MESSAGE, _DEVCONFIG_TRANSACTION_SLAVE, _DEVCONFIG_TRANSACTION_TOKEN, _DEVCONFIG_TRANSACTION_LATTICE, _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG, _DEVCONFIG_TRANSACTION_PROPOSAL, ], enum_types=[ ], options=None, @@ -3851,21 +6671,27 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7613, - serialized_end=7673, + serialized_start=14277, + serialized_end=15138, ) - -_P2PACKNOWLEDGEMENT = _descriptor.Descriptor( - name='P2PAcknowledgement', - full_name='qrl.P2PAcknowledgement', +_DEVCONFIG_POW = _descriptor.Descriptor( + name='POW', + full_name='qrl.DevConfig.POW', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='bytes_processed', full_name='qrl.P2PAcknowledgement.bytes_processed', index=0, - number=1, type=13, cpp_type=3, label=1, + name='N_measurement', full_name='qrl.DevConfig.POW.N_measurement', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='kp', full_name='qrl.DevConfig.POW.kp', index=1, + number=2, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3882,88 +6708,77 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7675, - serialized_end=7720, + serialized_start=15140, + serialized_end=15180, ) - -_PEERINFO = _descriptor.Descriptor( - name='PeerInfo', - full_name='qrl.PeerInfo', +_DEVCONFIG = _descriptor.Descriptor( + name='DevConfig', + full_name='qrl.DevConfig', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='peer_ip', full_name='qrl.PeerInfo.peer_ip', index=0, + name='prev_state_key', full_name='qrl.DevConfig.prev_state_key', index=0, number=1, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='port', full_name='qrl.PeerInfo.port', index=1, - number=2, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, + name='current_state_key', full_name='qrl.DevConfig.current_state_key', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='banned_timestamp', full_name='qrl.PeerInfo.banned_timestamp', index=2, - number=3, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, + name='activation_header_hash', full_name='qrl.DevConfig.activation_header_hash', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='credibility', full_name='qrl.PeerInfo.credibility', index=3, - number=4, type=13, cpp_type=3, label=1, + name='activation_block_number', full_name='qrl.DevConfig.activation_block_number', index=3, + number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='last_connections_timestamp', full_name='qrl.PeerInfo.last_connections_timestamp', index=4, - number=5, type=13, cpp_type=3, label=3, - has_default_value=False, default_value=[], + name='chain', full_name='qrl.DevConfig.chain', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=7722, - serialized_end=7846, -) - - -_PEERS = _descriptor.Descriptor( - name='Peers', - full_name='qrl.Peers', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ _descriptor.FieldDescriptor( - name='peer_info_list', full_name='qrl.Peers.peer_info_list', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='block', full_name='qrl.DevConfig.block', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transaction', full_name='qrl.DevConfig.transaction', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='pow', full_name='qrl.DevConfig.pow', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), ], extensions=[ ], - nested_types=[], + nested_types=[_DEVCONFIG_CHAIN, _DEVCONFIG_BLOCK, _DEVCONFIG_TRANSACTION, _DEVCONFIG_POW, ], enum_types=[ ], options=None, @@ -3972,8 +6787,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7848, - serialized_end=7894, + serialized_start=13561, + serialized_end=15180, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -3982,9 +6797,10 @@ _GETPEERSSTATRESP.fields_by_name['peers_stat'].message_type = _PEERSTAT _GETSTATSRESP.fields_by_name['node_info'].message_type = _NODEINFO _GETSTATSRESP.fields_by_name['block_timeseries'].message_type = _BLOCKDATAPOINT -_GETADDRESSSTATERESP.fields_by_name['state'].message_type = _ADDRESSSTATE +_GETADDRESSSTATERESP.fields_by_name['state'].message_type = _OPTIMIZEDADDRESSSTATE +_GETMULTISIGADDRESSSTATERESP.fields_by_name['state'].message_type = _MULTISIGADDRESSSTATE _PARSEADDRESSRESP.fields_by_name['desc'].message_type = _ADDRESSDESCRIPTOR -_GETOBJECTRESP.fields_by_name['address_state'].message_type = _ADDRESSSTATE +_GETOBJECTRESP.fields_by_name['address_state'].message_type = _OPTIMIZEDADDRESSSTATE _GETOBJECTRESP.fields_by_name['transaction'].message_type = _TRANSACTIONEXTENDED _GETOBJECTRESP.fields_by_name['block_extended'].message_type = _BLOCKEXTENDED _GETOBJECTRESP.oneofs_by_name['result'].fields.append( @@ -4006,8 +6822,18 @@ _PUSHTRANSACTIONRESP.fields_by_name['error_code'].enum_type = _PUSHTRANSACTIONRESP_RESPONSECODE _PUSHTRANSACTIONRESP_RESPONSECODE.containing_type = _PUSHTRANSACTIONRESP _TOKENTXNREQ.fields_by_name['initial_balances'].message_type = _ADDRESSAMOUNT -_GETTRANSACTIONSBYADDRESSRESP.fields_by_name['mini_transactions'].message_type = _MINITRANSACTION _GETTRANSACTIONRESP.fields_by_name['tx'].message_type = _TRANSACTION +_GETMINITRANSACTIONSBYADDRESSRESP.fields_by_name['mini_transactions'].message_type = _MINITRANSACTION +_GETTRANSACTIONSBYADDRESSRESP.fields_by_name['transactions_detail'].message_type = _GETTRANSACTIONRESP +_GETMULTISIGSPENDTXSBYADDRESSREQ.fields_by_name['filter_type'].enum_type = _GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE +_GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE.containing_type = _GETMULTISIGSPENDTXSBYADDRESSREQ +_GETMULTISIGSPENDTXSBYADDRESSRESP.fields_by_name['transactions_detail'].message_type = _GETTRANSACTIONRESP +_GETVOTESTATSRESP.fields_by_name['vote_stats'].message_type = _VOTESTATS +_GETTOKENSBYADDRESSRESP.fields_by_name['tokens_detail'].message_type = _TOKENDETAIL +_GETSLAVESBYADDRESSRESP.fields_by_name['slaves_detail'].message_type = _SLAVEDETAIL +_GETLATTICEPKSBYADDRESSRESP.fields_by_name['lattice_pks_detail'].message_type = _LATTICEPKSDETAIL +_GETMULTISIGADDRESSESBYADDRESSRESP.fields_by_name['multi_sig_detail'].message_type = _MULTISIGDETAIL +_GETOTSRESP.fields_by_name['ots_bitfield_by_page'].message_type = _OTSBITFIELDBYPAGE _GETBLOCKRESP.fields_by_name['block'].message_type = _BLOCK _GETBLOCKBYNUMBERRESP.fields_by_name['block'].message_type = _BLOCK _NODEINFO.fields_by_name['state'].enum_type = _NODEINFO_STATE @@ -4018,6 +6844,8 @@ _ADDRESSSTATE.fields_by_name['tokens'].message_type = _ADDRESSSTATE_TOKENSENTRY _ADDRESSSTATE.fields_by_name['latticePK_list'].message_type = _LATTICEPK _ADDRESSSTATE.fields_by_name['slave_pks_access_type'].message_type = _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY +_OPTIMIZEDADDRESSSTATE.fields_by_name['proposal_vote_stats'].message_type = _TRANSACTION +_MULTISIGADDRESSSTATE.fields_by_name['proposal_vote_stats'].message_type = _TRANSACTION _BLOCKHEADEREXTENDED.fields_by_name['header'].message_type = _BLOCKHEADER _BLOCKHEADEREXTENDED.fields_by_name['transaction_count'].message_type = _TRANSACTIONCOUNT _TRANSACTIONCOUNT_COUNTENTRY.containing_type = _TRANSACTIONCOUNT @@ -4039,6 +6867,26 @@ _TRANSACTION_TOKEN.containing_type = _TRANSACTION _TRANSACTION_TRANSFERTOKEN.containing_type = _TRANSACTION _TRANSACTION_SLAVE.containing_type = _TRANSACTION +_TRANSACTION_MULTISIGCREATE.containing_type = _TRANSACTION +_TRANSACTION_MULTISIGSPEND.containing_type = _TRANSACTION +_TRANSACTION_MULTISIGVOTE.containing_type = _TRANSACTION +_TRANSACTION_PROPOSALCREATE_QIP.containing_type = _TRANSACTION_PROPOSALCREATE +_TRANSACTION_PROPOSALCREATE_CONFIG.containing_type = _TRANSACTION_PROPOSALCREATE +_TRANSACTION_PROPOSALCREATE_OTHER.containing_type = _TRANSACTION_PROPOSALCREATE +_TRANSACTION_PROPOSALCREATE.fields_by_name['qip'].message_type = _TRANSACTION_PROPOSALCREATE_QIP +_TRANSACTION_PROPOSALCREATE.fields_by_name['config'].message_type = _TRANSACTION_PROPOSALCREATE_CONFIG +_TRANSACTION_PROPOSALCREATE.fields_by_name['other'].message_type = _TRANSACTION_PROPOSALCREATE_OTHER +_TRANSACTION_PROPOSALCREATE.containing_type = _TRANSACTION +_TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'].fields.append( + _TRANSACTION_PROPOSALCREATE.fields_by_name['qip']) +_TRANSACTION_PROPOSALCREATE.fields_by_name['qip'].containing_oneof = _TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'] +_TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'].fields.append( + _TRANSACTION_PROPOSALCREATE.fields_by_name['config']) +_TRANSACTION_PROPOSALCREATE.fields_by_name['config'].containing_oneof = _TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'] +_TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'].fields.append( + _TRANSACTION_PROPOSALCREATE.fields_by_name['other']) +_TRANSACTION_PROPOSALCREATE.fields_by_name['other'].containing_oneof = _TRANSACTION_PROPOSALCREATE.oneofs_by_name['proposalType'] +_TRANSACTION_PROPOSALVOTE.containing_type = _TRANSACTION _TRANSACTION.fields_by_name['transfer'].message_type = _TRANSACTION_TRANSFER _TRANSACTION.fields_by_name['coinbase'].message_type = _TRANSACTION_COINBASE _TRANSACTION.fields_by_name['latticePK'].message_type = _TRANSACTION_LATTICEPUBLICKEY @@ -4046,6 +6894,11 @@ _TRANSACTION.fields_by_name['token'].message_type = _TRANSACTION_TOKEN _TRANSACTION.fields_by_name['transfer_token'].message_type = _TRANSACTION_TRANSFERTOKEN _TRANSACTION.fields_by_name['slave'].message_type = _TRANSACTION_SLAVE +_TRANSACTION.fields_by_name['multi_sig_create'].message_type = _TRANSACTION_MULTISIGCREATE +_TRANSACTION.fields_by_name['multi_sig_spend'].message_type = _TRANSACTION_MULTISIGSPEND +_TRANSACTION.fields_by_name['multi_sig_vote'].message_type = _TRANSACTION_MULTISIGVOTE +_TRANSACTION.fields_by_name['proposal_create'].message_type = _TRANSACTION_PROPOSALCREATE +_TRANSACTION.fields_by_name['proposal_vote'].message_type = _TRANSACTION_PROPOSALVOTE _TRANSACTION.oneofs_by_name['transactionType'].fields.append( _TRANSACTION.fields_by_name['transfer']) _TRANSACTION.fields_by_name['transfer'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] @@ -4067,10 +6920,47 @@ _TRANSACTION.oneofs_by_name['transactionType'].fields.append( _TRANSACTION.fields_by_name['slave']) _TRANSACTION.fields_by_name['slave'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] +_TRANSACTION.oneofs_by_name['transactionType'].fields.append( + _TRANSACTION.fields_by_name['multi_sig_create']) +_TRANSACTION.fields_by_name['multi_sig_create'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] +_TRANSACTION.oneofs_by_name['transactionType'].fields.append( + _TRANSACTION.fields_by_name['multi_sig_spend']) +_TRANSACTION.fields_by_name['multi_sig_spend'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] +_TRANSACTION.oneofs_by_name['transactionType'].fields.append( + _TRANSACTION.fields_by_name['multi_sig_vote']) +_TRANSACTION.fields_by_name['multi_sig_vote'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] +_TRANSACTION.oneofs_by_name['transactionType'].fields.append( + _TRANSACTION.fields_by_name['proposal_create']) +_TRANSACTION.fields_by_name['proposal_create'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] +_TRANSACTION.oneofs_by_name['transactionType'].fields.append( + _TRANSACTION.fields_by_name['proposal_vote']) +_TRANSACTION.fields_by_name['proposal_vote'].containing_oneof = _TRANSACTION.oneofs_by_name['transactionType'] _ENCRYPTEDEPHEMERALMESSAGE_CHANNEL.containing_type = _ENCRYPTEDEPHEMERALMESSAGE _ENCRYPTEDEPHEMERALMESSAGE.fields_by_name['channel'].message_type = _ENCRYPTEDEPHEMERALMESSAGE_CHANNEL _PEERSTAT.fields_by_name['node_chain_state'].message_type = _NODECHAINSTATE _PEERS.fields_by_name['peer_info_list'].message_type = _PEERINFO +_DEVCONFIG_CHAIN.containing_type = _DEVCONFIG +_DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER.containing_type = _DEVCONFIG_BLOCK +_DEVCONFIG_BLOCK.fields_by_name['block_size_controller'].message_type = _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER +_DEVCONFIG_BLOCK.containing_type = _DEVCONFIG +_DEVCONFIG_TRANSACTION_MESSAGE.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION_SLAVE.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION_TOKEN.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION_LATTICE.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION_PROPOSAL.containing_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG_TRANSACTION.fields_by_name['message'].message_type = _DEVCONFIG_TRANSACTION_MESSAGE +_DEVCONFIG_TRANSACTION.fields_by_name['slave'].message_type = _DEVCONFIG_TRANSACTION_SLAVE +_DEVCONFIG_TRANSACTION.fields_by_name['token'].message_type = _DEVCONFIG_TRANSACTION_TOKEN +_DEVCONFIG_TRANSACTION.fields_by_name['lattice'].message_type = _DEVCONFIG_TRANSACTION_LATTICE +_DEVCONFIG_TRANSACTION.fields_by_name['foundation_multi_sig'].message_type = _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG +_DEVCONFIG_TRANSACTION.fields_by_name['proposal'].message_type = _DEVCONFIG_TRANSACTION_PROPOSAL +_DEVCONFIG_TRANSACTION.containing_type = _DEVCONFIG +_DEVCONFIG_POW.containing_type = _DEVCONFIG +_DEVCONFIG.fields_by_name['chain'].message_type = _DEVCONFIG_CHAIN +_DEVCONFIG.fields_by_name['block'].message_type = _DEVCONFIG_BLOCK +_DEVCONFIG.fields_by_name['transaction'].message_type = _DEVCONFIG_TRANSACTION +_DEVCONFIG.fields_by_name['pow'].message_type = _DEVCONFIG_POW DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY DESCRIPTOR.message_types_by_name['GetNodeStateReq'] = _GETNODESTATEREQ DESCRIPTOR.message_types_by_name['GetNodeStateResp'] = _GETNODESTATERESP @@ -4087,6 +6977,10 @@ DESCRIPTOR.message_types_by_name['BlockDataPoint'] = _BLOCKDATAPOINT DESCRIPTOR.message_types_by_name['GetAddressStateReq'] = _GETADDRESSSTATEREQ DESCRIPTOR.message_types_by_name['GetAddressStateResp'] = _GETADDRESSSTATERESP +DESCRIPTOR.message_types_by_name['GetMultiSigAddressStateReq'] = _GETMULTISIGADDRESSSTATEREQ +DESCRIPTOR.message_types_by_name['GetMultiSigAddressStateResp'] = _GETMULTISIGADDRESSSTATERESP +DESCRIPTOR.message_types_by_name['IsSlaveReq'] = _ISSLAVEREQ +DESCRIPTOR.message_types_by_name['IsSlaveResp'] = _ISSLAVERESP DESCRIPTOR.message_types_by_name['ParseAddressReq'] = _PARSEADDRESSREQ DESCRIPTOR.message_types_by_name['ParseAddressResp'] = _PARSEADDRESSRESP DESCRIPTOR.message_types_by_name['GetObjectReq'] = _GETOBJECTREQ @@ -4097,20 +6991,39 @@ DESCRIPTOR.message_types_by_name['TransferCoinsResp'] = _TRANSFERCOINSRESP DESCRIPTOR.message_types_by_name['PushTransactionReq'] = _PUSHTRANSACTIONREQ DESCRIPTOR.message_types_by_name['PushTransactionResp'] = _PUSHTRANSACTIONRESP +DESCRIPTOR.message_types_by_name['MultiSigCreateTxnReq'] = _MULTISIGCREATETXNREQ +DESCRIPTOR.message_types_by_name['MultiSigSpendTxnReq'] = _MULTISIGSPENDTXNREQ +DESCRIPTOR.message_types_by_name['MultiSigVoteTxnReq'] = _MULTISIGVOTETXNREQ DESCRIPTOR.message_types_by_name['MessageTxnReq'] = _MESSAGETXNREQ DESCRIPTOR.message_types_by_name['TokenTxnReq'] = _TOKENTXNREQ DESCRIPTOR.message_types_by_name['TransferTokenTxnReq'] = _TRANSFERTOKENTXNREQ DESCRIPTOR.message_types_by_name['SlaveTxnReq'] = _SLAVETXNREQ +DESCRIPTOR.message_types_by_name['LatticeTxnReq'] = _LATTICETXNREQ DESCRIPTOR.message_types_by_name['MiniTransaction'] = _MINITRANSACTION -DESCRIPTOR.message_types_by_name['GetTransactionsByAddressReq'] = _GETTRANSACTIONSBYADDRESSREQ -DESCRIPTOR.message_types_by_name['GetTransactionsByAddressResp'] = _GETTRANSACTIONSBYADDRESSRESP DESCRIPTOR.message_types_by_name['GetTransactionReq'] = _GETTRANSACTIONREQ DESCRIPTOR.message_types_by_name['GetTransactionResp'] = _GETTRANSACTIONRESP +DESCRIPTOR.message_types_by_name['GetMiniTransactionsByAddressReq'] = _GETMINITRANSACTIONSBYADDRESSREQ +DESCRIPTOR.message_types_by_name['GetMiniTransactionsByAddressResp'] = _GETMINITRANSACTIONSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['GetTransactionsByAddressReq'] = _GETTRANSACTIONSBYADDRESSREQ +DESCRIPTOR.message_types_by_name['GetTransactionsByAddressResp'] = _GETTRANSACTIONSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['GetMultiSigSpendTxsByAddressReq'] = _GETMULTISIGSPENDTXSBYADDRESSREQ +DESCRIPTOR.message_types_by_name['GetMultiSigSpendTxsByAddressResp'] = _GETMULTISIGSPENDTXSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['GetVoteStatsReq'] = _GETVOTESTATSREQ +DESCRIPTOR.message_types_by_name['GetVoteStatsResp'] = _GETVOTESTATSRESP +DESCRIPTOR.message_types_by_name['TokenDetail'] = _TOKENDETAIL +DESCRIPTOR.message_types_by_name['GetTokensByAddressResp'] = _GETTOKENSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['SlaveDetail'] = _SLAVEDETAIL +DESCRIPTOR.message_types_by_name['GetSlavesByAddressResp'] = _GETSLAVESBYADDRESSRESP +DESCRIPTOR.message_types_by_name['LatticePKsDetail'] = _LATTICEPKSDETAIL +DESCRIPTOR.message_types_by_name['GetLatticePKsByAddressResp'] = _GETLATTICEPKSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['MultiSigDetail'] = _MULTISIGDETAIL +DESCRIPTOR.message_types_by_name['GetMultiSigAddressesByAddressResp'] = _GETMULTISIGADDRESSESBYADDRESSRESP DESCRIPTOR.message_types_by_name['GetBalanceReq'] = _GETBALANCEREQ DESCRIPTOR.message_types_by_name['GetBalanceResp'] = _GETBALANCERESP DESCRIPTOR.message_types_by_name['GetTotalBalanceReq'] = _GETTOTALBALANCEREQ DESCRIPTOR.message_types_by_name['GetTotalBalanceResp'] = _GETTOTALBALANCERESP DESCRIPTOR.message_types_by_name['GetOTSReq'] = _GETOTSREQ +DESCRIPTOR.message_types_by_name['OTSBitfieldByPage'] = _OTSBITFIELDBYPAGE DESCRIPTOR.message_types_by_name['GetOTSResp'] = _GETOTSRESP DESCRIPTOR.message_types_by_name['GetHeightReq'] = _GETHEIGHTREQ DESCRIPTOR.message_types_by_name['GetHeightResp'] = _GETHEIGHTRESP @@ -4125,6 +7038,12 @@ DESCRIPTOR.message_types_by_name['StoredPeers'] = _STOREDPEERS DESCRIPTOR.message_types_by_name['Peer'] = _PEER DESCRIPTOR.message_types_by_name['AddressState'] = _ADDRESSSTATE +DESCRIPTOR.message_types_by_name['OptimizedAddressState'] = _OPTIMIZEDADDRESSSTATE +DESCRIPTOR.message_types_by_name['MultiSigAddressState'] = _MULTISIGADDRESSSTATE +DESCRIPTOR.message_types_by_name['MultiSigAddressesList'] = _MULTISIGADDRESSESLIST +DESCRIPTOR.message_types_by_name['DataList'] = _DATALIST +DESCRIPTOR.message_types_by_name['Bitfield'] = _BITFIELD +DESCRIPTOR.message_types_by_name['TransactionHashList'] = _TRANSACTIONHASHLIST DESCRIPTOR.message_types_by_name['LatticePK'] = _LATTICEPK DESCRIPTOR.message_types_by_name['AddressAmount'] = _ADDRESSAMOUNT DESCRIPTOR.message_types_by_name['BlockHeader'] = _BLOCKHEADER @@ -4136,22 +7055,26 @@ DESCRIPTOR.message_types_by_name['GenesisBalance'] = _GENESISBALANCE DESCRIPTOR.message_types_by_name['BlockMetaDataList'] = _BLOCKMETADATALIST DESCRIPTOR.message_types_by_name['Transaction'] = _TRANSACTION +DESCRIPTOR.message_types_by_name['VoteStats'] = _VOTESTATS +DESCRIPTOR.message_types_by_name['ProposalVoteStats'] = _PROPOSALVOTESTATS +DESCRIPTOR.message_types_by_name['ProposalRecord'] = _PROPOSALRECORD DESCRIPTOR.message_types_by_name['TokenList'] = _TOKENLIST +DESCRIPTOR.message_types_by_name['TokenBalance'] = _TOKENBALANCE +DESCRIPTOR.message_types_by_name['SlaveMetadata'] = _SLAVEMETADATA +DESCRIPTOR.message_types_by_name['LatticePKMetadata'] = _LATTICEPKMETADATA DESCRIPTOR.message_types_by_name['TokenMetadata'] = _TOKENMETADATA DESCRIPTOR.message_types_by_name['EncryptedEphemeralMessage'] = _ENCRYPTEDEPHEMERALMESSAGE DESCRIPTOR.message_types_by_name['AddressList'] = _ADDRESSLIST DESCRIPTOR.message_types_by_name['BlockHeightData'] = _BLOCKHEIGHTDATA DESCRIPTOR.message_types_by_name['BlockMetaData'] = _BLOCKMETADATA DESCRIPTOR.message_types_by_name['BlockNumberMapping'] = _BLOCKNUMBERMAPPING -DESCRIPTOR.message_types_by_name['StateLoader'] = _STATELOADER -DESCRIPTOR.message_types_by_name['StateObjects'] = _STATEOBJECTS -DESCRIPTOR.message_types_by_name['LRUStateCache'] = _LRUSTATECACHE DESCRIPTOR.message_types_by_name['PeerStat'] = _PEERSTAT DESCRIPTOR.message_types_by_name['NodeChainState'] = _NODECHAINSTATE DESCRIPTOR.message_types_by_name['NodeHeaderHash'] = _NODEHEADERHASH DESCRIPTOR.message_types_by_name['P2PAcknowledgement'] = _P2PACKNOWLEDGEMENT DESCRIPTOR.message_types_by_name['PeerInfo'] = _PEERINFO DESCRIPTOR.message_types_by_name['Peers'] = _PEERS +DESCRIPTOR.message_types_by_name['DevConfig'] = _DEVCONFIG _sym_db.RegisterFileDescriptor(DESCRIPTOR) Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), dict( @@ -4266,6 +7189,34 @@ )) _sym_db.RegisterMessage(GetAddressStateResp) +GetMultiSigAddressStateReq = _reflection.GeneratedProtocolMessageType('GetMultiSigAddressStateReq', (_message.Message,), dict( + DESCRIPTOR = _GETMULTISIGADDRESSSTATEREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetMultiSigAddressStateReq) + )) +_sym_db.RegisterMessage(GetMultiSigAddressStateReq) + +GetMultiSigAddressStateResp = _reflection.GeneratedProtocolMessageType('GetMultiSigAddressStateResp', (_message.Message,), dict( + DESCRIPTOR = _GETMULTISIGADDRESSSTATERESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetMultiSigAddressStateResp) + )) +_sym_db.RegisterMessage(GetMultiSigAddressStateResp) + +IsSlaveReq = _reflection.GeneratedProtocolMessageType('IsSlaveReq', (_message.Message,), dict( + DESCRIPTOR = _ISSLAVEREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.IsSlaveReq) + )) +_sym_db.RegisterMessage(IsSlaveReq) + +IsSlaveResp = _reflection.GeneratedProtocolMessageType('IsSlaveResp', (_message.Message,), dict( + DESCRIPTOR = _ISSLAVERESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.IsSlaveResp) + )) +_sym_db.RegisterMessage(IsSlaveResp) + ParseAddressReq = _reflection.GeneratedProtocolMessageType('ParseAddressReq', (_message.Message,), dict( DESCRIPTOR = _PARSEADDRESSREQ, __module__ = 'qrl_pb2' @@ -4332,9 +7283,30 @@ PushTransactionResp = _reflection.GeneratedProtocolMessageType('PushTransactionResp', (_message.Message,), dict( DESCRIPTOR = _PUSHTRANSACTIONRESP, __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.PushTransactionResp) + # @@protoc_insertion_point(class_scope:qrl.PushTransactionResp) + )) +_sym_db.RegisterMessage(PushTransactionResp) + +MultiSigCreateTxnReq = _reflection.GeneratedProtocolMessageType('MultiSigCreateTxnReq', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGCREATETXNREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigCreateTxnReq) + )) +_sym_db.RegisterMessage(MultiSigCreateTxnReq) + +MultiSigSpendTxnReq = _reflection.GeneratedProtocolMessageType('MultiSigSpendTxnReq', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGSPENDTXNREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigSpendTxnReq) + )) +_sym_db.RegisterMessage(MultiSigSpendTxnReq) + +MultiSigVoteTxnReq = _reflection.GeneratedProtocolMessageType('MultiSigVoteTxnReq', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGVOTETXNREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigVoteTxnReq) )) -_sym_db.RegisterMessage(PushTransactionResp) +_sym_db.RegisterMessage(MultiSigVoteTxnReq) MessageTxnReq = _reflection.GeneratedProtocolMessageType('MessageTxnReq', (_message.Message,), dict( DESCRIPTOR = _MESSAGETXNREQ, @@ -4364,6 +7336,13 @@ )) _sym_db.RegisterMessage(SlaveTxnReq) +LatticeTxnReq = _reflection.GeneratedProtocolMessageType('LatticeTxnReq', (_message.Message,), dict( + DESCRIPTOR = _LATTICETXNREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.LatticeTxnReq) + )) +_sym_db.RegisterMessage(LatticeTxnReq) + MiniTransaction = _reflection.GeneratedProtocolMessageType('MiniTransaction', (_message.Message,), dict( DESCRIPTOR = _MINITRANSACTION, __module__ = 'qrl_pb2' @@ -4371,6 +7350,34 @@ )) _sym_db.RegisterMessage(MiniTransaction) +GetTransactionReq = _reflection.GeneratedProtocolMessageType('GetTransactionReq', (_message.Message,), dict( + DESCRIPTOR = _GETTRANSACTIONREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetTransactionReq) + )) +_sym_db.RegisterMessage(GetTransactionReq) + +GetTransactionResp = _reflection.GeneratedProtocolMessageType('GetTransactionResp', (_message.Message,), dict( + DESCRIPTOR = _GETTRANSACTIONRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetTransactionResp) + )) +_sym_db.RegisterMessage(GetTransactionResp) + +GetMiniTransactionsByAddressReq = _reflection.GeneratedProtocolMessageType('GetMiniTransactionsByAddressReq', (_message.Message,), dict( + DESCRIPTOR = _GETMINITRANSACTIONSBYADDRESSREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetMiniTransactionsByAddressReq) + )) +_sym_db.RegisterMessage(GetMiniTransactionsByAddressReq) + +GetMiniTransactionsByAddressResp = _reflection.GeneratedProtocolMessageType('GetMiniTransactionsByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETMINITRANSACTIONSBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetMiniTransactionsByAddressResp) + )) +_sym_db.RegisterMessage(GetMiniTransactionsByAddressResp) + GetTransactionsByAddressReq = _reflection.GeneratedProtocolMessageType('GetTransactionsByAddressReq', (_message.Message,), dict( DESCRIPTOR = _GETTRANSACTIONSBYADDRESSREQ, __module__ = 'qrl_pb2' @@ -4385,19 +7392,89 @@ )) _sym_db.RegisterMessage(GetTransactionsByAddressResp) -GetTransactionReq = _reflection.GeneratedProtocolMessageType('GetTransactionReq', (_message.Message,), dict( - DESCRIPTOR = _GETTRANSACTIONREQ, +GetMultiSigSpendTxsByAddressReq = _reflection.GeneratedProtocolMessageType('GetMultiSigSpendTxsByAddressReq', (_message.Message,), dict( + DESCRIPTOR = _GETMULTISIGSPENDTXSBYADDRESSREQ, __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.GetTransactionReq) + # @@protoc_insertion_point(class_scope:qrl.GetMultiSigSpendTxsByAddressReq) )) -_sym_db.RegisterMessage(GetTransactionReq) +_sym_db.RegisterMessage(GetMultiSigSpendTxsByAddressReq) -GetTransactionResp = _reflection.GeneratedProtocolMessageType('GetTransactionResp', (_message.Message,), dict( - DESCRIPTOR = _GETTRANSACTIONRESP, +GetMultiSigSpendTxsByAddressResp = _reflection.GeneratedProtocolMessageType('GetMultiSigSpendTxsByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETMULTISIGSPENDTXSBYADDRESSRESP, __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.GetTransactionResp) + # @@protoc_insertion_point(class_scope:qrl.GetMultiSigSpendTxsByAddressResp) )) -_sym_db.RegisterMessage(GetTransactionResp) +_sym_db.RegisterMessage(GetMultiSigSpendTxsByAddressResp) + +GetVoteStatsReq = _reflection.GeneratedProtocolMessageType('GetVoteStatsReq', (_message.Message,), dict( + DESCRIPTOR = _GETVOTESTATSREQ, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetVoteStatsReq) + )) +_sym_db.RegisterMessage(GetVoteStatsReq) + +GetVoteStatsResp = _reflection.GeneratedProtocolMessageType('GetVoteStatsResp', (_message.Message,), dict( + DESCRIPTOR = _GETVOTESTATSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetVoteStatsResp) + )) +_sym_db.RegisterMessage(GetVoteStatsResp) + +TokenDetail = _reflection.GeneratedProtocolMessageType('TokenDetail', (_message.Message,), dict( + DESCRIPTOR = _TOKENDETAIL, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.TokenDetail) + )) +_sym_db.RegisterMessage(TokenDetail) + +GetTokensByAddressResp = _reflection.GeneratedProtocolMessageType('GetTokensByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETTOKENSBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetTokensByAddressResp) + )) +_sym_db.RegisterMessage(GetTokensByAddressResp) + +SlaveDetail = _reflection.GeneratedProtocolMessageType('SlaveDetail', (_message.Message,), dict( + DESCRIPTOR = _SLAVEDETAIL, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.SlaveDetail) + )) +_sym_db.RegisterMessage(SlaveDetail) + +GetSlavesByAddressResp = _reflection.GeneratedProtocolMessageType('GetSlavesByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETSLAVESBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetSlavesByAddressResp) + )) +_sym_db.RegisterMessage(GetSlavesByAddressResp) + +LatticePKsDetail = _reflection.GeneratedProtocolMessageType('LatticePKsDetail', (_message.Message,), dict( + DESCRIPTOR = _LATTICEPKSDETAIL, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.LatticePKsDetail) + )) +_sym_db.RegisterMessage(LatticePKsDetail) + +GetLatticePKsByAddressResp = _reflection.GeneratedProtocolMessageType('GetLatticePKsByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETLATTICEPKSBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetLatticePKsByAddressResp) + )) +_sym_db.RegisterMessage(GetLatticePKsByAddressResp) + +MultiSigDetail = _reflection.GeneratedProtocolMessageType('MultiSigDetail', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGDETAIL, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigDetail) + )) +_sym_db.RegisterMessage(MultiSigDetail) + +GetMultiSigAddressesByAddressResp = _reflection.GeneratedProtocolMessageType('GetMultiSigAddressesByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETMULTISIGADDRESSESBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetMultiSigAddressesByAddressResp) + )) +_sym_db.RegisterMessage(GetMultiSigAddressesByAddressResp) GetBalanceReq = _reflection.GeneratedProtocolMessageType('GetBalanceReq', (_message.Message,), dict( DESCRIPTOR = _GETBALANCEREQ, @@ -4434,6 +7511,13 @@ )) _sym_db.RegisterMessage(GetOTSReq) +OTSBitfieldByPage = _reflection.GeneratedProtocolMessageType('OTSBitfieldByPage', (_message.Message,), dict( + DESCRIPTOR = _OTSBITFIELDBYPAGE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.OTSBitfieldByPage) + )) +_sym_db.RegisterMessage(OTSBitfieldByPage) + GetOTSResp = _reflection.GeneratedProtocolMessageType('GetOTSResp', (_message.Message,), dict( DESCRIPTOR = _GETOTSRESP, __module__ = 'qrl_pb2' @@ -4548,6 +7632,48 @@ _sym_db.RegisterMessage(AddressState.TokensEntry) _sym_db.RegisterMessage(AddressState.SlavePksAccessTypeEntry) +OptimizedAddressState = _reflection.GeneratedProtocolMessageType('OptimizedAddressState', (_message.Message,), dict( + DESCRIPTOR = _OPTIMIZEDADDRESSSTATE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.OptimizedAddressState) + )) +_sym_db.RegisterMessage(OptimizedAddressState) + +MultiSigAddressState = _reflection.GeneratedProtocolMessageType('MultiSigAddressState', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGADDRESSSTATE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigAddressState) + )) +_sym_db.RegisterMessage(MultiSigAddressState) + +MultiSigAddressesList = _reflection.GeneratedProtocolMessageType('MultiSigAddressesList', (_message.Message,), dict( + DESCRIPTOR = _MULTISIGADDRESSESLIST, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.MultiSigAddressesList) + )) +_sym_db.RegisterMessage(MultiSigAddressesList) + +DataList = _reflection.GeneratedProtocolMessageType('DataList', (_message.Message,), dict( + DESCRIPTOR = _DATALIST, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DataList) + )) +_sym_db.RegisterMessage(DataList) + +Bitfield = _reflection.GeneratedProtocolMessageType('Bitfield', (_message.Message,), dict( + DESCRIPTOR = _BITFIELD, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Bitfield) + )) +_sym_db.RegisterMessage(Bitfield) + +TransactionHashList = _reflection.GeneratedProtocolMessageType('TransactionHashList', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTIONHASHLIST, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.TransactionHashList) + )) +_sym_db.RegisterMessage(TransactionHashList) + LatticePK = _reflection.GeneratedProtocolMessageType('LatticePK', (_message.Message,), dict( DESCRIPTOR = _LATTICEPK, __module__ = 'qrl_pb2' @@ -4676,6 +7802,62 @@ # @@protoc_insertion_point(class_scope:qrl.Transaction.Slave) )) , + + MultiSigCreate = _reflection.GeneratedProtocolMessageType('MultiSigCreate', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_MULTISIGCREATE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.MultiSigCreate) + )) + , + + MultiSigSpend = _reflection.GeneratedProtocolMessageType('MultiSigSpend', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_MULTISIGSPEND, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.MultiSigSpend) + )) + , + + MultiSigVote = _reflection.GeneratedProtocolMessageType('MultiSigVote', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_MULTISIGVOTE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.MultiSigVote) + )) + , + + ProposalCreate = _reflection.GeneratedProtocolMessageType('ProposalCreate', (_message.Message,), dict( + + QIP = _reflection.GeneratedProtocolMessageType('QIP', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_PROPOSALCREATE_QIP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.ProposalCreate.QIP) + )) + , + + Config = _reflection.GeneratedProtocolMessageType('Config', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_PROPOSALCREATE_CONFIG, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.ProposalCreate.Config) + )) + , + + Other = _reflection.GeneratedProtocolMessageType('Other', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_PROPOSALCREATE_OTHER, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.ProposalCreate.Other) + )) + , + DESCRIPTOR = _TRANSACTION_PROPOSALCREATE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.ProposalCreate) + )) + , + + ProposalVote = _reflection.GeneratedProtocolMessageType('ProposalVote', (_message.Message,), dict( + DESCRIPTOR = _TRANSACTION_PROPOSALVOTE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.Transaction.ProposalVote) + )) + , DESCRIPTOR = _TRANSACTION, __module__ = 'qrl_pb2' # @@protoc_insertion_point(class_scope:qrl.Transaction) @@ -4688,6 +7870,35 @@ _sym_db.RegisterMessage(Transaction.Token) _sym_db.RegisterMessage(Transaction.TransferToken) _sym_db.RegisterMessage(Transaction.Slave) +_sym_db.RegisterMessage(Transaction.MultiSigCreate) +_sym_db.RegisterMessage(Transaction.MultiSigSpend) +_sym_db.RegisterMessage(Transaction.MultiSigVote) +_sym_db.RegisterMessage(Transaction.ProposalCreate) +_sym_db.RegisterMessage(Transaction.ProposalCreate.QIP) +_sym_db.RegisterMessage(Transaction.ProposalCreate.Config) +_sym_db.RegisterMessage(Transaction.ProposalCreate.Other) +_sym_db.RegisterMessage(Transaction.ProposalVote) + +VoteStats = _reflection.GeneratedProtocolMessageType('VoteStats', (_message.Message,), dict( + DESCRIPTOR = _VOTESTATS, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.VoteStats) + )) +_sym_db.RegisterMessage(VoteStats) + +ProposalVoteStats = _reflection.GeneratedProtocolMessageType('ProposalVoteStats', (_message.Message,), dict( + DESCRIPTOR = _PROPOSALVOTESTATS, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.ProposalVoteStats) + )) +_sym_db.RegisterMessage(ProposalVoteStats) + +ProposalRecord = _reflection.GeneratedProtocolMessageType('ProposalRecord', (_message.Message,), dict( + DESCRIPTOR = _PROPOSALRECORD, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.ProposalRecord) + )) +_sym_db.RegisterMessage(ProposalRecord) TokenList = _reflection.GeneratedProtocolMessageType('TokenList', (_message.Message,), dict( DESCRIPTOR = _TOKENLIST, @@ -4696,6 +7907,27 @@ )) _sym_db.RegisterMessage(TokenList) +TokenBalance = _reflection.GeneratedProtocolMessageType('TokenBalance', (_message.Message,), dict( + DESCRIPTOR = _TOKENBALANCE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.TokenBalance) + )) +_sym_db.RegisterMessage(TokenBalance) + +SlaveMetadata = _reflection.GeneratedProtocolMessageType('SlaveMetadata', (_message.Message,), dict( + DESCRIPTOR = _SLAVEMETADATA, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.SlaveMetadata) + )) +_sym_db.RegisterMessage(SlaveMetadata) + +LatticePKMetadata = _reflection.GeneratedProtocolMessageType('LatticePKMetadata', (_message.Message,), dict( + DESCRIPTOR = _LATTICEPKMETADATA, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.LatticePKMetadata) + )) +_sym_db.RegisterMessage(LatticePKMetadata) + TokenMetadata = _reflection.GeneratedProtocolMessageType('TokenMetadata', (_message.Message,), dict( DESCRIPTOR = _TOKENMETADATA, __module__ = 'qrl_pb2' @@ -4746,27 +7978,6 @@ )) _sym_db.RegisterMessage(BlockNumberMapping) -StateLoader = _reflection.GeneratedProtocolMessageType('StateLoader', (_message.Message,), dict( - DESCRIPTOR = _STATELOADER, - __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.StateLoader) - )) -_sym_db.RegisterMessage(StateLoader) - -StateObjects = _reflection.GeneratedProtocolMessageType('StateObjects', (_message.Message,), dict( - DESCRIPTOR = _STATEOBJECTS, - __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.StateObjects) - )) -_sym_db.RegisterMessage(StateObjects) - -LRUStateCache = _reflection.GeneratedProtocolMessageType('LRUStateCache', (_message.Message,), dict( - DESCRIPTOR = _LRUSTATECACHE, - __module__ = 'qrl_pb2' - # @@protoc_insertion_point(class_scope:qrl.LRUStateCache) - )) -_sym_db.RegisterMessage(LRUStateCache) - PeerStat = _reflection.GeneratedProtocolMessageType('PeerStat', (_message.Message,), dict( DESCRIPTOR = _PEERSTAT, __module__ = 'qrl_pb2' @@ -4809,6 +8020,101 @@ )) _sym_db.RegisterMessage(Peers) +DevConfig = _reflection.GeneratedProtocolMessageType('DevConfig', (_message.Message,), dict( + + Chain = _reflection.GeneratedProtocolMessageType('Chain', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_CHAIN, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Chain) + )) + , + + Block = _reflection.GeneratedProtocolMessageType('Block', (_message.Message,), dict( + + BlockSizeController = _reflection.GeneratedProtocolMessageType('BlockSizeController', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Block.BlockSizeController) + )) + , + DESCRIPTOR = _DEVCONFIG_BLOCK, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Block) + )) + , + + Transaction = _reflection.GeneratedProtocolMessageType('Transaction', (_message.Message,), dict( + + Message = _reflection.GeneratedProtocolMessageType('Message', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_MESSAGE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.Message) + )) + , + + Slave = _reflection.GeneratedProtocolMessageType('Slave', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_SLAVE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.Slave) + )) + , + + Token = _reflection.GeneratedProtocolMessageType('Token', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_TOKEN, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.Token) + )) + , + + Lattice = _reflection.GeneratedProtocolMessageType('Lattice', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_LATTICE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.Lattice) + )) + , + + FoundationMultiSig = _reflection.GeneratedProtocolMessageType('FoundationMultiSig', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.FoundationMultiSig) + )) + , + + Proposal = _reflection.GeneratedProtocolMessageType('Proposal', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_TRANSACTION_PROPOSAL, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction.Proposal) + )) + , + DESCRIPTOR = _DEVCONFIG_TRANSACTION, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.Transaction) + )) + , + + POW = _reflection.GeneratedProtocolMessageType('POW', (_message.Message,), dict( + DESCRIPTOR = _DEVCONFIG_POW, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig.POW) + )) + , + DESCRIPTOR = _DEVCONFIG, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.DevConfig) + )) +_sym_db.RegisterMessage(DevConfig) +_sym_db.RegisterMessage(DevConfig.Chain) +_sym_db.RegisterMessage(DevConfig.Block) +_sym_db.RegisterMessage(DevConfig.Block.BlockSizeController) +_sym_db.RegisterMessage(DevConfig.Transaction) +_sym_db.RegisterMessage(DevConfig.Transaction.Message) +_sym_db.RegisterMessage(DevConfig.Transaction.Slave) +_sym_db.RegisterMessage(DevConfig.Transaction.Token) +_sym_db.RegisterMessage(DevConfig.Transaction.Lattice) +_sym_db.RegisterMessage(DevConfig.Transaction.FoundationMultiSig) +_sym_db.RegisterMessage(DevConfig.Transaction.Proposal) +_sym_db.RegisterMessage(DevConfig.POW) + _ADDRESSSTATE_TOKENSENTRY.has_options = True _ADDRESSSTATE_TOKENSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) @@ -4823,8 +8129,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=7897, - serialized_end=9415, + serialized_start=15183, + serialized_end=17770, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -4871,10 +8177,28 @@ output_type=_GETADDRESSSTATERESP, options=None, ), + _descriptor.MethodDescriptor( + name='GetMultiSigAddressState', + full_name='qrl.PublicAPI.GetMultiSigAddressState', + index=5, + containing_service=None, + input_type=_GETMULTISIGADDRESSSTATEREQ, + output_type=_GETMULTISIGADDRESSSTATERESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='IsSlave', + full_name='qrl.PublicAPI.IsSlave', + index=6, + containing_service=None, + input_type=_ISSLAVEREQ, + output_type=_ISSLAVERESP, + options=None, + ), _descriptor.MethodDescriptor( name='GetObject', full_name='qrl.PublicAPI.GetObject', - index=5, + index=7, containing_service=None, input_type=_GETOBJECTREQ, output_type=_GETOBJECTRESP, @@ -4883,7 +8207,7 @@ _descriptor.MethodDescriptor( name='GetLatestData', full_name='qrl.PublicAPI.GetLatestData', - index=6, + index=8, containing_service=None, input_type=_GETLATESTDATAREQ, output_type=_GETLATESTDATARESP, @@ -4892,7 +8216,7 @@ _descriptor.MethodDescriptor( name='PushTransaction', full_name='qrl.PublicAPI.PushTransaction', - index=7, + index=9, containing_service=None, input_type=_PUSHTRANSACTIONREQ, output_type=_PUSHTRANSACTIONRESP, @@ -4901,7 +8225,7 @@ _descriptor.MethodDescriptor( name='TransferCoins', full_name='qrl.PublicAPI.TransferCoins', - index=8, + index=10, containing_service=None, input_type=_TRANSFERCOINSREQ, output_type=_TRANSFERCOINSRESP, @@ -4910,7 +8234,7 @@ _descriptor.MethodDescriptor( name='ParseAddress', full_name='qrl.PublicAPI.ParseAddress', - index=9, + index=11, containing_service=None, input_type=_PARSEADDRESSREQ, output_type=_PARSEADDRESSRESP, @@ -4919,7 +8243,7 @@ _descriptor.MethodDescriptor( name='GetChainStats', full_name='qrl.PublicAPI.GetChainStats', - index=10, + index=12, containing_service=None, input_type=_GETCHAINSTATSREQ, output_type=_GETCHAINSTATSRESP, @@ -4928,16 +8252,43 @@ _descriptor.MethodDescriptor( name='GetAddressFromPK', full_name='qrl.PublicAPI.GetAddressFromPK', - index=11, + index=13, containing_service=None, input_type=_GETADDRESSFROMPKREQ, output_type=_GETADDRESSFROMPKRESP, options=None, ), + _descriptor.MethodDescriptor( + name='GetMultiSigCreateTxn', + full_name='qrl.PublicAPI.GetMultiSigCreateTxn', + index=14, + containing_service=None, + input_type=_MULTISIGCREATETXNREQ, + output_type=_TRANSFERCOINSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetMultiSigSpendTxn', + full_name='qrl.PublicAPI.GetMultiSigSpendTxn', + index=15, + containing_service=None, + input_type=_MULTISIGSPENDTXNREQ, + output_type=_TRANSFERCOINSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetMultiSigVoteTxn', + full_name='qrl.PublicAPI.GetMultiSigVoteTxn', + index=16, + containing_service=None, + input_type=_MULTISIGVOTETXNREQ, + output_type=_TRANSFERCOINSRESP, + options=None, + ), _descriptor.MethodDescriptor( name='GetMessageTxn', full_name='qrl.PublicAPI.GetMessageTxn', - index=12, + index=17, containing_service=None, input_type=_MESSAGETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -4946,7 +8297,7 @@ _descriptor.MethodDescriptor( name='GetTokenTxn', full_name='qrl.PublicAPI.GetTokenTxn', - index=13, + index=18, containing_service=None, input_type=_TOKENTXNREQ, output_type=_TRANSFERCOINSRESP, @@ -4955,7 +8306,7 @@ _descriptor.MethodDescriptor( name='GetTransferTokenTxn', full_name='qrl.PublicAPI.GetTransferTokenTxn', - index=14, + index=19, containing_service=None, input_type=_TRANSFERTOKENTXNREQ, output_type=_TRANSFERCOINSRESP, @@ -4964,34 +8315,106 @@ _descriptor.MethodDescriptor( name='GetSlaveTxn', full_name='qrl.PublicAPI.GetSlaveTxn', - index=15, + index=20, containing_service=None, input_type=_SLAVETXNREQ, output_type=_TRANSFERCOINSRESP, options=None, ), _descriptor.MethodDescriptor( - name='GetTransactionsByAddress', - full_name='qrl.PublicAPI.GetTransactionsByAddress', - index=16, + name='GetLatticeTxn', + full_name='qrl.PublicAPI.GetLatticeTxn', + index=21, containing_service=None, - input_type=_GETTRANSACTIONSBYADDRESSREQ, - output_type=_GETTRANSACTIONSBYADDRESSRESP, + input_type=_LATTICETXNREQ, + output_type=_TRANSFERCOINSRESP, options=None, ), _descriptor.MethodDescriptor( name='GetTransaction', full_name='qrl.PublicAPI.GetTransaction', - index=17, + index=22, containing_service=None, input_type=_GETTRANSACTIONREQ, output_type=_GETTRANSACTIONRESP, options=None, ), + _descriptor.MethodDescriptor( + name='GetMiniTransactionsByAddress', + full_name='qrl.PublicAPI.GetMiniTransactionsByAddress', + index=23, + containing_service=None, + input_type=_GETMINITRANSACTIONSBYADDRESSREQ, + output_type=_GETMINITRANSACTIONSBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetTransactionsByAddress', + full_name='qrl.PublicAPI.GetTransactionsByAddress', + index=24, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETTRANSACTIONSBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetTokensByAddress', + full_name='qrl.PublicAPI.GetTokensByAddress', + index=25, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETTOKENSBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetSlavesByAddress', + full_name='qrl.PublicAPI.GetSlavesByAddress', + index=26, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETSLAVESBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetLatticePKsByAddress', + full_name='qrl.PublicAPI.GetLatticePKsByAddress', + index=27, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETLATTICEPKSBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetMultiSigAddressesByAddress', + full_name='qrl.PublicAPI.GetMultiSigAddressesByAddress', + index=28, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETMULTISIGADDRESSESBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetMultiSigSpendTxsByAddress', + full_name='qrl.PublicAPI.GetMultiSigSpendTxsByAddress', + index=29, + containing_service=None, + input_type=_GETMULTISIGSPENDTXSBYADDRESSREQ, + output_type=_GETMULTISIGSPENDTXSBYADDRESSRESP, + options=None, + ), + _descriptor.MethodDescriptor( + name='GetVoteStats', + full_name='qrl.PublicAPI.GetVoteStats', + index=30, + containing_service=None, + input_type=_GETVOTESTATSREQ, + output_type=_GETVOTESTATSRESP, + options=None, + ), _descriptor.MethodDescriptor( name='GetBalance', full_name='qrl.PublicAPI.GetBalance', - index=18, + index=31, containing_service=None, input_type=_GETBALANCEREQ, output_type=_GETBALANCERESP, @@ -5000,7 +8423,7 @@ _descriptor.MethodDescriptor( name='GetTotalBalance', full_name='qrl.PublicAPI.GetTotalBalance', - index=19, + index=32, containing_service=None, input_type=_GETTOTALBALANCEREQ, output_type=_GETTOTALBALANCERESP, @@ -5009,7 +8432,7 @@ _descriptor.MethodDescriptor( name='GetOTS', full_name='qrl.PublicAPI.GetOTS', - index=20, + index=33, containing_service=None, input_type=_GETOTSREQ, output_type=_GETOTSRESP, @@ -5018,7 +8441,7 @@ _descriptor.MethodDescriptor( name='GetHeight', full_name='qrl.PublicAPI.GetHeight', - index=21, + index=34, containing_service=None, input_type=_GETHEIGHTREQ, output_type=_GETHEIGHTRESP, @@ -5027,7 +8450,7 @@ _descriptor.MethodDescriptor( name='GetBlock', full_name='qrl.PublicAPI.GetBlock', - index=22, + index=35, containing_service=None, input_type=_GETBLOCKREQ, output_type=_GETBLOCKRESP, @@ -5036,7 +8459,7 @@ _descriptor.MethodDescriptor( name='GetBlockByNumber', full_name='qrl.PublicAPI.GetBlockByNumber', - index=23, + index=36, containing_service=None, input_type=_GETBLOCKBYNUMBERREQ, output_type=_GETBLOCKBYNUMBERRESP, @@ -5054,8 +8477,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=9417, - serialized_end=9427, + serialized_start=17772, + serialized_end=17782, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/generated/qrl_pb2_grpc.py b/src/qrl/generated/qrl_pb2_grpc.py index 4bf75918a..0337bc44f 100644 --- a/src/qrl/generated/qrl_pb2_grpc.py +++ b/src/qrl/generated/qrl_pb2_grpc.py @@ -1,11 +1,9 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! import grpc -#import qrl_pb2 as qrl__pb2 import qrl.generated.qrl_pb2 as qrl__pb2 - class PublicAPIStub(object): """////////////////////////// ////////////////////////// @@ -49,6 +47,16 @@ def __init__(self, channel): request_serializer=qrl__pb2.GetAddressStateReq.SerializeToString, response_deserializer=qrl__pb2.GetAddressStateResp.FromString, ) + self.GetMultiSigAddressState = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigAddressState', + request_serializer=qrl__pb2.GetMultiSigAddressStateReq.SerializeToString, + response_deserializer=qrl__pb2.GetMultiSigAddressStateResp.FromString, + ) + self.IsSlave = channel.unary_unary( + '/qrl.PublicAPI/IsSlave', + request_serializer=qrl__pb2.IsSlaveReq.SerializeToString, + response_deserializer=qrl__pb2.IsSlaveResp.FromString, + ) self.GetObject = channel.unary_unary( '/qrl.PublicAPI/GetObject', request_serializer=qrl__pb2.GetObjectReq.SerializeToString, @@ -84,6 +92,21 @@ def __init__(self, channel): request_serializer=qrl__pb2.GetAddressFromPKReq.SerializeToString, response_deserializer=qrl__pb2.GetAddressFromPKResp.FromString, ) + self.GetMultiSigCreateTxn = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigCreateTxn', + request_serializer=qrl__pb2.MultiSigCreateTxnReq.SerializeToString, + response_deserializer=qrl__pb2.TransferCoinsResp.FromString, + ) + self.GetMultiSigSpendTxn = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigSpendTxn', + request_serializer=qrl__pb2.MultiSigSpendTxnReq.SerializeToString, + response_deserializer=qrl__pb2.TransferCoinsResp.FromString, + ) + self.GetMultiSigVoteTxn = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigVoteTxn', + request_serializer=qrl__pb2.MultiSigVoteTxnReq.SerializeToString, + response_deserializer=qrl__pb2.TransferCoinsResp.FromString, + ) self.GetMessageTxn = channel.unary_unary( '/qrl.PublicAPI/GetMessageTxn', request_serializer=qrl__pb2.MessageTxnReq.SerializeToString, @@ -104,16 +127,56 @@ def __init__(self, channel): request_serializer=qrl__pb2.SlaveTxnReq.SerializeToString, response_deserializer=qrl__pb2.TransferCoinsResp.FromString, ) - self.GetTransactionsByAddress = channel.unary_unary( - '/qrl.PublicAPI/GetTransactionsByAddress', - request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, - response_deserializer=qrl__pb2.GetTransactionsByAddressResp.FromString, + self.GetLatticeTxn = channel.unary_unary( + '/qrl.PublicAPI/GetLatticeTxn', + request_serializer=qrl__pb2.LatticeTxnReq.SerializeToString, + response_deserializer=qrl__pb2.TransferCoinsResp.FromString, ) self.GetTransaction = channel.unary_unary( '/qrl.PublicAPI/GetTransaction', request_serializer=qrl__pb2.GetTransactionReq.SerializeToString, response_deserializer=qrl__pb2.GetTransactionResp.FromString, ) + self.GetMiniTransactionsByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetMiniTransactionsByAddress', + request_serializer=qrl__pb2.GetMiniTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetMiniTransactionsByAddressResp.FromString, + ) + self.GetTransactionsByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetTransactionsByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetTransactionsByAddressResp.FromString, + ) + self.GetTokensByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetTokensByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetTokensByAddressResp.FromString, + ) + self.GetSlavesByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetSlavesByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetSlavesByAddressResp.FromString, + ) + self.GetLatticePKsByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetLatticePKsByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetLatticePKsByAddressResp.FromString, + ) + self.GetMultiSigAddressesByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigAddressesByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetMultiSigAddressesByAddressResp.FromString, + ) + self.GetMultiSigSpendTxsByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetMultiSigSpendTxsByAddress', + request_serializer=qrl__pb2.GetMultiSigSpendTxsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetMultiSigSpendTxsByAddressResp.FromString, + ) + self.GetVoteStats = channel.unary_unary( + '/qrl.PublicAPI/GetVoteStats', + request_serializer=qrl__pb2.GetVoteStatsReq.SerializeToString, + response_deserializer=qrl__pb2.GetVoteStatsResp.FromString, + ) self.GetBalance = channel.unary_unary( '/qrl.PublicAPI/GetBalance', request_serializer=qrl__pb2.GetBalanceReq.SerializeToString, @@ -160,168 +223,222 @@ class PublicAPIServicer(object): def GetNodeState(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetKnownPeers(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetPeersStat(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetStats(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetAddressState(self, request, context): # missing associated documentation comment in .proto file - pass + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigAddressState(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def IsSlave(self, request, context): + # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetObject(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetLatestData(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def PushTransaction(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def TransferCoins(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def ParseAddress(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetChainStats(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetAddressFromPK(self, request, context): # missing associated documentation comment in .proto file - pass + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigCreateTxn(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigSpendTxn(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigVoteTxn(self, request, context): + # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetMessageTxn(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetTokenTxn(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetTransferTokenTxn(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetSlaveTxn(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def GetTransactionsByAddress(self, request, context): + def GetLatticeTxn(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetTransaction(self, request, context): # missing associated documentation comment in .proto file - pass + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMiniTransactionsByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetTransactionsByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetTokensByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetSlavesByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetLatticePKsByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigAddressesByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMultiSigSpendTxsByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetVoteStats(self, request, context): + # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetBalance(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetTotalBalance(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetOTS(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetHeight(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetBlock(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') def GetBlockByNumber(self, request, context): # missing associated documentation comment in .proto file - pass context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') @@ -354,6 +471,16 @@ def add_PublicAPIServicer_to_server(servicer, server): request_deserializer=qrl__pb2.GetAddressStateReq.FromString, response_serializer=qrl__pb2.GetAddressStateResp.SerializeToString, ), + 'GetMultiSigAddressState': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigAddressState, + request_deserializer=qrl__pb2.GetMultiSigAddressStateReq.FromString, + response_serializer=qrl__pb2.GetMultiSigAddressStateResp.SerializeToString, + ), + 'IsSlave': grpc.unary_unary_rpc_method_handler( + servicer.IsSlave, + request_deserializer=qrl__pb2.IsSlaveReq.FromString, + response_serializer=qrl__pb2.IsSlaveResp.SerializeToString, + ), 'GetObject': grpc.unary_unary_rpc_method_handler( servicer.GetObject, request_deserializer=qrl__pb2.GetObjectReq.FromString, @@ -389,6 +516,21 @@ def add_PublicAPIServicer_to_server(servicer, server): request_deserializer=qrl__pb2.GetAddressFromPKReq.FromString, response_serializer=qrl__pb2.GetAddressFromPKResp.SerializeToString, ), + 'GetMultiSigCreateTxn': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigCreateTxn, + request_deserializer=qrl__pb2.MultiSigCreateTxnReq.FromString, + response_serializer=qrl__pb2.TransferCoinsResp.SerializeToString, + ), + 'GetMultiSigSpendTxn': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigSpendTxn, + request_deserializer=qrl__pb2.MultiSigSpendTxnReq.FromString, + response_serializer=qrl__pb2.TransferCoinsResp.SerializeToString, + ), + 'GetMultiSigVoteTxn': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigVoteTxn, + request_deserializer=qrl__pb2.MultiSigVoteTxnReq.FromString, + response_serializer=qrl__pb2.TransferCoinsResp.SerializeToString, + ), 'GetMessageTxn': grpc.unary_unary_rpc_method_handler( servicer.GetMessageTxn, request_deserializer=qrl__pb2.MessageTxnReq.FromString, @@ -409,16 +551,56 @@ def add_PublicAPIServicer_to_server(servicer, server): request_deserializer=qrl__pb2.SlaveTxnReq.FromString, response_serializer=qrl__pb2.TransferCoinsResp.SerializeToString, ), - 'GetTransactionsByAddress': grpc.unary_unary_rpc_method_handler( - servicer.GetTransactionsByAddress, - request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, - response_serializer=qrl__pb2.GetTransactionsByAddressResp.SerializeToString, + 'GetLatticeTxn': grpc.unary_unary_rpc_method_handler( + servicer.GetLatticeTxn, + request_deserializer=qrl__pb2.LatticeTxnReq.FromString, + response_serializer=qrl__pb2.TransferCoinsResp.SerializeToString, ), 'GetTransaction': grpc.unary_unary_rpc_method_handler( servicer.GetTransaction, request_deserializer=qrl__pb2.GetTransactionReq.FromString, response_serializer=qrl__pb2.GetTransactionResp.SerializeToString, ), + 'GetMiniTransactionsByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetMiniTransactionsByAddress, + request_deserializer=qrl__pb2.GetMiniTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetMiniTransactionsByAddressResp.SerializeToString, + ), + 'GetTransactionsByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetTransactionsByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetTransactionsByAddressResp.SerializeToString, + ), + 'GetTokensByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetTokensByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetTokensByAddressResp.SerializeToString, + ), + 'GetSlavesByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetSlavesByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetSlavesByAddressResp.SerializeToString, + ), + 'GetLatticePKsByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetLatticePKsByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetLatticePKsByAddressResp.SerializeToString, + ), + 'GetMultiSigAddressesByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigAddressesByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetMultiSigAddressesByAddressResp.SerializeToString, + ), + 'GetMultiSigSpendTxsByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetMultiSigSpendTxsByAddress, + request_deserializer=qrl__pb2.GetMultiSigSpendTxsByAddressReq.FromString, + response_serializer=qrl__pb2.GetMultiSigSpendTxsByAddressResp.SerializeToString, + ), + 'GetVoteStats': grpc.unary_unary_rpc_method_handler( + servicer.GetVoteStats, + request_deserializer=qrl__pb2.GetVoteStatsReq.FromString, + response_serializer=qrl__pb2.GetVoteStatsResp.SerializeToString, + ), 'GetBalance': grpc.unary_unary_rpc_method_handler( servicer.GetBalance, request_deserializer=qrl__pb2.GetBalanceReq.FromString, diff --git a/src/qrl/generated/qrllegacy_pb2.py b/src/qrl/generated/qrllegacy_pb2.py index 3e10cbe84..04752d0c0 100644 --- a/src/qrl/generated/qrllegacy_pb2.py +++ b/src/qrl/generated/qrllegacy_pb2.py @@ -20,7 +20,7 @@ name='qrllegacy.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\x0fqrllegacy.proto\x12\x03qrl\x1a\tqrl.proto\"\xee\x07\n\rLegacyMessage\x12.\n\tfunc_name\x18\x01 \x01(\x0e\x32\x1b.qrl.LegacyMessage.FuncName\x12\x1d\n\x06noData\x18\x02 \x01(\x0b\x32\x0b.qrl.NoDataH\x00\x12\x1d\n\x06veData\x18\x03 \x01(\x0b\x32\x0b.qrl.VEDataH\x00\x12\x1d\n\x06plData\x18\x04 \x01(\x0b\x32\x0b.qrl.PLDataH\x00\x12!\n\x08pongData\x18\x05 \x01(\x0b\x32\r.qrl.PONGDataH\x00\x12\x1d\n\x06mrData\x18\x06 \x01(\x0b\x32\x0b.qrl.MRDataH\x00\x12\x1b\n\x05\x62lock\x18\x07 \x01(\x0b\x32\n.qrl.BlockH\x00\x12\x1d\n\x06\x66\x62\x44\x61ta\x18\x08 \x01(\x0b\x32\x0b.qrl.FBDataH\x00\x12\x1d\n\x06pbData\x18\t \x01(\x0b\x32\x0b.qrl.PBDataH\x00\x12&\n\x06\x62hData\x18\n \x01(\x0b\x32\x14.qrl.BlockHeightDataH\x00\x12\"\n\x06txData\x18\x0b \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06mtData\x18\x0c \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06tkData\x18\r \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06ttData\x18\x0e \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06ltData\x18\x0f \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06slData\x18\x10 \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\x31\n\x07\x65phData\x18\x11 \x01(\x0b\x32\x1e.qrl.EncryptedEphemeralMessageH\x00\x12!\n\x08syncData\x18\x12 \x01(\x0b\x32\r.qrl.SYNCDataH\x00\x12-\n\x0e\x63hainStateData\x18\x13 \x01(\x0b\x32\x13.qrl.NodeChainStateH\x00\x12-\n\x0enodeHeaderHash\x18\x14 \x01(\x0b\x32\x13.qrl.NodeHeaderHashH\x00\x12-\n\np2pAckData\x18\x15 \x01(\x0b\x32\x17.qrl.P2PAcknowledgementH\x00\"\xc7\x01\n\x08\x46uncName\x12\x06\n\x02VE\x10\x00\x12\x06\n\x02PL\x10\x01\x12\x08\n\x04PONG\x10\x02\x12\x06\n\x02MR\x10\x03\x12\x07\n\x03SFM\x10\x04\x12\x06\n\x02\x42K\x10\x05\x12\x06\n\x02\x46\x42\x10\x06\x12\x06\n\x02PB\x10\x07\x12\x06\n\x02\x42H\x10\x08\x12\x06\n\x02TX\x10\t\x12\x06\n\x02LT\x10\n\x12\x07\n\x03\x45PH\x10\x0b\x12\x06\n\x02MT\x10\x0c\x12\x06\n\x02TK\x10\r\x12\x06\n\x02TT\x10\x0e\x12\x06\n\x02SL\x10\x0f\x12\x08\n\x04SYNC\x10\x10\x12\x0e\n\nCHAINSTATE\x10\x11\x12\x10\n\x0cHEADERHASHES\x10\x12\x12\x0b\n\x07P2P_ACK\x10\x13\x42\x06\n\x04\x64\x61ta\"\x08\n\x06NoData\"H\n\x06VEData\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x19\n\x11genesis_prev_hash\x18\x02 \x01(\x0c\x12\x12\n\nrate_limit\x18\x03 \x01(\x04\"/\n\x06PLData\x12\x10\n\x08peer_ips\x18\x01 \x03(\t\x12\x13\n\x0bpublic_port\x18\x02 \x01(\r\"\n\n\x08PONGData\"\x9d\x01\n\x06MRData\x12\x0c\n\x04hash\x18\x01 \x01(\x0c\x12)\n\x04type\x18\x02 \x01(\x0e\x32\x1b.qrl.LegacyMessage.FuncName\x12\x16\n\x0estake_selector\x18\x03 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x04 \x01(\x04\x12\x17\n\x0fprev_headerhash\x18\x05 \x01(\x0c\x12\x13\n\x0breveal_hash\x18\x06 \x01(\x0c\"@\n\x06\x42KData\x12\x1b\n\x06mrData\x18\x01 \x01(\x0b\x32\x0b.qrl.MRData\x12\x19\n\x05\x62lock\x18\x02 \x01(\x0b\x32\n.qrl.Block\"\x17\n\x06\x46\x42\x44\x61ta\x12\r\n\x05index\x18\x01 \x01(\x04\"#\n\x06PBData\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x19\n\x08SYNCData\x12\r\n\x05state\x18\x01 \x01(\tb\x06proto3') + serialized_pb=_b('\n\x0fqrllegacy.proto\x12\x03qrl\x1a\tqrl.proto\"\xf2\x08\n\rLegacyMessage\x12.\n\tfunc_name\x18\x01 \x01(\x0e\x32\x1b.qrl.LegacyMessage.FuncName\x12\x1d\n\x06noData\x18\x02 \x01(\x0b\x32\x0b.qrl.NoDataH\x00\x12\x1d\n\x06veData\x18\x03 \x01(\x0b\x32\x0b.qrl.VEDataH\x00\x12\x1d\n\x06plData\x18\x04 \x01(\x0b\x32\x0b.qrl.PLDataH\x00\x12!\n\x08pongData\x18\x05 \x01(\x0b\x32\r.qrl.PONGDataH\x00\x12\x1d\n\x06mrData\x18\x06 \x01(\x0b\x32\x0b.qrl.MRDataH\x00\x12\x1b\n\x05\x62lock\x18\x07 \x01(\x0b\x32\n.qrl.BlockH\x00\x12\x1d\n\x06\x66\x62\x44\x61ta\x18\x08 \x01(\x0b\x32\x0b.qrl.FBDataH\x00\x12\x1d\n\x06pbData\x18\t \x01(\x0b\x32\x0b.qrl.PBDataH\x00\x12&\n\x06\x62hData\x18\n \x01(\x0b\x32\x14.qrl.BlockHeightDataH\x00\x12\"\n\x06txData\x18\x0b \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06mtData\x18\x0c \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06tkData\x18\r \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06ttData\x18\x0e \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06ltData\x18\x0f \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06slData\x18\x10 \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\x31\n\x07\x65phData\x18\x11 \x01(\x0b\x32\x1e.qrl.EncryptedEphemeralMessageH\x00\x12!\n\x08syncData\x18\x12 \x01(\x0b\x32\r.qrl.SYNCDataH\x00\x12-\n\x0e\x63hainStateData\x18\x13 \x01(\x0b\x32\x13.qrl.NodeChainStateH\x00\x12-\n\x0enodeHeaderHash\x18\x14 \x01(\x0b\x32\x13.qrl.NodeHeaderHashH\x00\x12-\n\np2pAckData\x18\x15 \x01(\x0b\x32\x17.qrl.P2PAcknowledgementH\x00\x12\"\n\x06mcData\x18\x16 \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06msData\x18\x17 \x01(\x0b\x32\x10.qrl.TransactionH\x00\x12\"\n\x06mvData\x18\x18 \x01(\x0b\x32\x10.qrl.TransactionH\x00\"\xdf\x01\n\x08\x46uncName\x12\x06\n\x02VE\x10\x00\x12\x06\n\x02PL\x10\x01\x12\x08\n\x04PONG\x10\x02\x12\x06\n\x02MR\x10\x03\x12\x07\n\x03SFM\x10\x04\x12\x06\n\x02\x42K\x10\x05\x12\x06\n\x02\x46\x42\x10\x06\x12\x06\n\x02PB\x10\x07\x12\x06\n\x02\x42H\x10\x08\x12\x06\n\x02TX\x10\t\x12\x06\n\x02LT\x10\n\x12\x07\n\x03\x45PH\x10\x0b\x12\x06\n\x02MT\x10\x0c\x12\x06\n\x02TK\x10\r\x12\x06\n\x02TT\x10\x0e\x12\x06\n\x02SL\x10\x0f\x12\x08\n\x04SYNC\x10\x10\x12\x0e\n\nCHAINSTATE\x10\x11\x12\x10\n\x0cHEADERHASHES\x10\x12\x12\x0b\n\x07P2P_ACK\x10\x13\x12\x06\n\x02MC\x10\x14\x12\x06\n\x02MS\x10\x15\x12\x06\n\x02MV\x10\x16\x42\x06\n\x04\x64\x61ta\"\x08\n\x06NoData\"H\n\x06VEData\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x19\n\x11genesis_prev_hash\x18\x02 \x01(\x0c\x12\x12\n\nrate_limit\x18\x03 \x01(\x04\"/\n\x06PLData\x12\x10\n\x08peer_ips\x18\x01 \x03(\t\x12\x13\n\x0bpublic_port\x18\x02 \x01(\r\"\n\n\x08PONGData\"\x9d\x01\n\x06MRData\x12\x0c\n\x04hash\x18\x01 \x01(\x0c\x12)\n\x04type\x18\x02 \x01(\x0e\x32\x1b.qrl.LegacyMessage.FuncName\x12\x16\n\x0estake_selector\x18\x03 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x04 \x01(\x04\x12\x17\n\x0fprev_headerhash\x18\x05 \x01(\x0c\x12\x13\n\x0breveal_hash\x18\x06 \x01(\x0c\"@\n\x06\x42KData\x12\x1b\n\x06mrData\x18\x01 \x01(\x0b\x32\x0b.qrl.MRData\x12\x19\n\x05\x62lock\x18\x02 \x01(\x0b\x32\n.qrl.Block\"\x17\n\x06\x46\x42\x44\x61ta\x12\r\n\x05index\x18\x01 \x01(\x04\"#\n\x06PBData\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x19\n\x08SYNCData\x12\r\n\x05state\x18\x01 \x01(\tb\x06proto3') , dependencies=[qrl__pb2.DESCRIPTOR,]) @@ -112,11 +112,23 @@ name='P2P_ACK', index=19, number=19, options=None, type=None), + _descriptor.EnumValueDescriptor( + name='MC', index=20, number=20, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MS', index=21, number=21, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MV', index=22, number=22, + options=None, + type=None), ], containing_type=None, options=None, - serialized_start=835, - serialized_end=1034, + serialized_start=943, + serialized_end=1166, ) _sym_db.RegisterEnumDescriptor(_LEGACYMESSAGE_FUNCNAME) @@ -275,6 +287,27 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mcData', full_name='qrl.LegacyMessage.mcData', index=21, + number=22, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='msData', full_name='qrl.LegacyMessage.msData', index=22, + number=23, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mvData', full_name='qrl.LegacyMessage.mvData', index=23, + number=24, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -292,7 +325,7 @@ index=0, containing_type=None, fields=[]), ], serialized_start=36, - serialized_end=1042, + serialized_end=1174, ) @@ -315,8 +348,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1044, - serialized_end=1052, + serialized_start=1176, + serialized_end=1184, ) @@ -360,8 +393,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1054, - serialized_end=1126, + serialized_start=1186, + serialized_end=1258, ) @@ -398,8 +431,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1128, - serialized_end=1175, + serialized_start=1260, + serialized_end=1307, ) @@ -422,8 +455,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1177, - serialized_end=1187, + serialized_start=1309, + serialized_end=1319, ) @@ -488,8 +521,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1190, - serialized_end=1347, + serialized_start=1322, + serialized_end=1479, ) @@ -526,8 +559,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1349, - serialized_end=1413, + serialized_start=1481, + serialized_end=1545, ) @@ -557,8 +590,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1415, - serialized_end=1438, + serialized_start=1547, + serialized_end=1570, ) @@ -588,8 +621,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1440, - serialized_end=1475, + serialized_start=1572, + serialized_end=1607, ) @@ -619,8 +652,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1477, - serialized_end=1502, + serialized_start=1609, + serialized_end=1634, ) _LEGACYMESSAGE.fields_by_name['func_name'].enum_type = _LEGACYMESSAGE_FUNCNAME @@ -644,6 +677,9 @@ _LEGACYMESSAGE.fields_by_name['chainStateData'].message_type = qrl__pb2._NODECHAINSTATE _LEGACYMESSAGE.fields_by_name['nodeHeaderHash'].message_type = qrl__pb2._NODEHEADERHASH _LEGACYMESSAGE.fields_by_name['p2pAckData'].message_type = qrl__pb2._P2PACKNOWLEDGEMENT +_LEGACYMESSAGE.fields_by_name['mcData'].message_type = qrl__pb2._TRANSACTION +_LEGACYMESSAGE.fields_by_name['msData'].message_type = qrl__pb2._TRANSACTION +_LEGACYMESSAGE.fields_by_name['mvData'].message_type = qrl__pb2._TRANSACTION _LEGACYMESSAGE_FUNCNAME.containing_type = _LEGACYMESSAGE _LEGACYMESSAGE.oneofs_by_name['data'].fields.append( _LEGACYMESSAGE.fields_by_name['noData']) @@ -705,6 +741,15 @@ _LEGACYMESSAGE.oneofs_by_name['data'].fields.append( _LEGACYMESSAGE.fields_by_name['p2pAckData']) _LEGACYMESSAGE.fields_by_name['p2pAckData'].containing_oneof = _LEGACYMESSAGE.oneofs_by_name['data'] +_LEGACYMESSAGE.oneofs_by_name['data'].fields.append( + _LEGACYMESSAGE.fields_by_name['mcData']) +_LEGACYMESSAGE.fields_by_name['mcData'].containing_oneof = _LEGACYMESSAGE.oneofs_by_name['data'] +_LEGACYMESSAGE.oneofs_by_name['data'].fields.append( + _LEGACYMESSAGE.fields_by_name['msData']) +_LEGACYMESSAGE.fields_by_name['msData'].containing_oneof = _LEGACYMESSAGE.oneofs_by_name['data'] +_LEGACYMESSAGE.oneofs_by_name['data'].fields.append( + _LEGACYMESSAGE.fields_by_name['mvData']) +_LEGACYMESSAGE.fields_by_name['mvData'].containing_oneof = _LEGACYMESSAGE.oneofs_by_name['data'] _MRDATA.fields_by_name['type'].enum_type = _LEGACYMESSAGE_FUNCNAME _BKDATA.fields_by_name['mrData'].message_type = _MRDATA _BKDATA.fields_by_name['block'].message_type = qrl__pb2._BLOCK diff --git a/src/qrl/generated/qrlmining_pb2.py b/src/qrl/generated/qrlmining_pb2.py index 9d15d5b90..d6424bfe0 100644 --- a/src/qrl/generated/qrlmining_pb2.py +++ b/src/qrl/generated/qrlmining_pb2.py @@ -20,7 +20,7 @@ name='qrlmining.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\x0fqrlmining.proto\x12\x03qrl\x1a\tqrl.proto\"-\n\x1bGetBlockMiningCompatibleReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\'\n\x15GetLastBlockHeaderReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\"p\n\x1cGetBlockMiningCompatibleResp\x12%\n\x0b\x62lockheader\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12)\n\rblockmetadata\x18\x02 \x01(\x0b\x32\x12.qrl.BlockMetaData\"|\n\x16GetLastBlockHeaderResp\x12\x12\n\ndifficulty\x18\x01 \x01(\x04\x12\x0e\n\x06height\x18\x02 \x01(\x04\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x0e\n\x06reward\x18\x04 \x01(\x04\x12\x0c\n\x04hash\x18\x05 \x01(\t\x12\r\n\x05\x64\x65pth\x18\x06 \x01(\x04\"+\n\x11GetBlockToMineReq\x12\x16\n\x0ewallet_address\x18\x01 \x01(\x0c\"m\n\x12GetBlockToMineResp\x12\x1a\n\x12\x62locktemplate_blob\x18\x01 \x01(\t\x12\x12\n\ndifficulty\x18\x02 \x01(\x04\x12\x0e\n\x06height\x18\x03 \x01(\x04\x12\x17\n\x0freserved_offset\x18\x04 \x01(\r\"#\n\x13SubmitMinedBlockReq\x12\x0c\n\x04\x62lob\x18\x01 \x01(\x0c\"%\n\x14SubmitMinedBlockResp\x12\r\n\x05\x65rror\x18\x01 \x01(\x08\x32\xc7\x02\n\tMiningAPI\x12_\n\x18GetBlockMiningCompatible\x12 .qrl.GetBlockMiningCompatibleReq\x1a!.qrl.GetBlockMiningCompatibleResp\x12M\n\x12GetLastBlockHeader\x12\x1a.qrl.GetLastBlockHeaderReq\x1a\x1b.qrl.GetLastBlockHeaderResp\x12\x41\n\x0eGetBlockToMine\x12\x16.qrl.GetBlockToMineReq\x1a\x17.qrl.GetBlockToMineResp\x12G\n\x10SubmitMinedBlock\x12\x18.qrl.SubmitMinedBlockReq\x1a\x19.qrl.SubmitMinedBlockRespb\x06proto3') + serialized_pb=_b('\n\x0fqrlmining.proto\x12\x03qrl\x1a\tqrl.proto\"-\n\x1bGetBlockMiningCompatibleReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\'\n\x15GetLastBlockHeaderReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\"p\n\x1cGetBlockMiningCompatibleResp\x12%\n\x0b\x62lockheader\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12)\n\rblockmetadata\x18\x02 \x01(\x0b\x32\x12.qrl.BlockMetaData\"|\n\x16GetLastBlockHeaderResp\x12\x12\n\ndifficulty\x18\x01 \x01(\x04\x12\x0e\n\x06height\x18\x02 \x01(\x04\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x0e\n\x06reward\x18\x04 \x01(\x04\x12\x0c\n\x04hash\x18\x05 \x01(\t\x12\r\n\x05\x64\x65pth\x18\x06 \x01(\x04\"+\n\x11GetBlockToMineReq\x12\x16\n\x0ewallet_address\x18\x01 \x01(\x0c\"\x80\x01\n\x12GetBlockToMineResp\x12\x1a\n\x12\x62locktemplate_blob\x18\x01 \x01(\t\x12\x12\n\ndifficulty\x18\x02 \x01(\x04\x12\x0e\n\x06height\x18\x03 \x01(\x04\x12\x17\n\x0freserved_offset\x18\x04 \x01(\r\x12\x11\n\tseed_hash\x18\x05 \x01(\t\"#\n\x13SubmitMinedBlockReq\x12\x0c\n\x04\x62lob\x18\x01 \x01(\x0c\"%\n\x14SubmitMinedBlockResp\x12\r\n\x05\x65rror\x18\x01 \x01(\x08\x32\xc7\x02\n\tMiningAPI\x12_\n\x18GetBlockMiningCompatible\x12 .qrl.GetBlockMiningCompatibleReq\x1a!.qrl.GetBlockMiningCompatibleResp\x12M\n\x12GetLastBlockHeader\x12\x1a.qrl.GetLastBlockHeaderReq\x1a\x1b.qrl.GetLastBlockHeaderResp\x12\x41\n\x0eGetBlockToMine\x12\x16.qrl.GetBlockToMineReq\x1a\x17.qrl.GetBlockToMineResp\x12G\n\x10SubmitMinedBlock\x12\x18.qrl.SubmitMinedBlockReq\x1a\x19.qrl.SubmitMinedBlockRespb\x06proto3') , dependencies=[qrl__pb2.DESCRIPTOR,]) @@ -259,6 +259,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='seed_hash', full_name='qrl.GetBlockToMineResp.seed_hash', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -271,8 +278,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=408, - serialized_end=517, + serialized_start=409, + serialized_end=537, ) @@ -302,8 +309,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=519, - serialized_end=554, + serialized_start=539, + serialized_end=574, ) @@ -333,8 +340,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=556, - serialized_end=593, + serialized_start=576, + serialized_end=613, ) _GETBLOCKMININGCOMPATIBLERESP.fields_by_name['blockheader'].message_type = qrl__pb2._BLOCKHEADER @@ -413,8 +420,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=596, - serialized_end=923, + serialized_start=616, + serialized_end=943, methods=[ _descriptor.MethodDescriptor( name='GetBlockMiningCompatible', diff --git a/src/qrl/generated/qrlwallet_pb2.py b/src/qrl/generated/qrlwallet_pb2.py index 9f5d4c2e1..917f070d3 100644 --- a/src/qrl/generated/qrlwallet_pb2.py +++ b/src/qrl/generated/qrlwallet_pb2.py @@ -20,7 +20,7 @@ name='qrlwallet.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\x0fqrlwallet.proto\x12\x03qrl\x1a\tqrl.proto\"9\n\x10\x41\x64\x64NewAddressReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12\x15\n\rhash_function\x18\x02 \x01(\t\"A\n\x11\x41\x64\x64NewAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"]\n\x1a\x41\x64\x64NewAddressWithSlavesReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12\x18\n\x10number_of_slaves\x18\x02 \x01(\x04\x12\x15\n\rhash_function\x18\x03 \x01(\t\"%\n\x15\x41\x64\x64\x41\x64\x64ressFromSeedReq\x12\x0c\n\x04seed\x18\x01 \x01(\t\"F\n\x16\x41\x64\x64\x41\x64\x64ressFromSeedResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"\x12\n\x10ListAddressesReq\"C\n\x11ListAddressesResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x11\n\taddresses\x18\x03 \x03(\t\"#\n\x10RemoveAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"0\n\x11RemoveAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\"\n\x0fValidAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\">\n\x10ValidAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\r\n\x05valid\x18\x03 \x01(\t\"&\n\x10\x45ncryptWalletReq\x12\x12\n\npassphrase\x18\x01 \x01(\t\"0\n\x11\x45ncryptWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"%\n\x0fUnlockWalletReq\x12\x12\n\npassphrase\x18\x01 \x01(\t\"/\n\x10UnlockWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\x0f\n\rLockWalletReq\"-\n\x0eLockWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"&\n\x13GetRecoverySeedsReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"V\n\x14GetRecoverySeedsResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07hexseed\x18\x03 \x01(\t\x12\x10\n\x08mnemonic\x18\x04 \x01(\t\"\x12\n\x10GetWalletInfoReq\"n\n\x11GetWalletInfoResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\r\x12\x15\n\raddress_count\x18\x04 \x01(\x04\x12\x14\n\x0cis_encrypted\x18\x05 \x01(\x08\"\x8c\x01\n\x13RelayTransferTxnReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\x12\x16\n\x0esigner_address\x18\x05 \x01(\t\x12\x11\n\tots_index\x18\x06 \x01(\x04\"h\n\x1aRelayTransferTxnBySlaveReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\"u\n\x12RelayMessageTxnReq\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x16\n\x0emaster_address\x18\x03 \x01(\t\x12\x16\n\x0esigner_address\x18\x04 \x01(\t\x12\x11\n\tots_index\x18\x05 \x01(\x04\"Q\n\x19RelayMessageTxnBySlaveReq\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x16\n\x0emaster_address\x18\x03 \x01(\t\"\xc5\x01\n\x10RelayTokenTxnReq\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x11\n\taddresses\x18\x05 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x06 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x16\n\x0emaster_address\x18\x08 \x01(\t\x12\x16\n\x0esigner_address\x18\t \x01(\t\x12\x11\n\tots_index\x18\n \x01(\x04\"\xa1\x01\n\x17RelayTokenTxnBySlaveReq\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x11\n\taddresses\x18\x05 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x06 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x16\n\x0emaster_address\x18\x08 \x01(\t\"\xa7\x01\n\x18RelayTransferTokenTxnReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x14\n\x0ctoken_txhash\x18\x02 \x01(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x16\n\x0emaster_address\x18\x05 \x01(\t\x12\x16\n\x0esigner_address\x18\x06 \x01(\t\x12\x11\n\tots_index\x18\x07 \x01(\x04\"\x83\x01\n\x1fRelayTransferTokenTxnBySlaveReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x14\n\x0ctoken_txhash\x18\x02 \x01(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x16\n\x0emaster_address\x18\x05 \x01(\t\"\x8b\x01\n\x10RelaySlaveTxnReq\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\x12\x16\n\x0esigner_address\x18\x05 \x01(\t\x12\x11\n\tots_index\x18\x06 \x01(\x04\"g\n\x17RelaySlaveTxnBySlaveReq\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\"N\n\x0cRelayTxnResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12!\n\x02tx\x18\x03 \x01(\x0b\x32\x15.qrl.PlainTransaction\"C\n\x13\x43hangePassphraseReq\x12\x15\n\roldPassphrase\x18\x01 \x01(\t\x12\x15\n\rnewPassphrase\x18\x02 \x01(\t\"3\n\x14\x43hangePassphraseResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"+\n\x18TransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"z\n\x19TransactionsByAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12/\n\x11mini_transactions\x18\x03 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"!\n\x0eTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\t\"\x99\x01\n\x0fTransactionResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12!\n\x02tx\x18\x03 \x01(\x0b\x32\x15.qrl.PlainTransaction\x12\x15\n\rconfirmations\x18\x04 \x01(\t\x12\x14\n\x0c\x62lock_number\x18\x05 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x06 \x01(\t\"\x1d\n\nBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\";\n\x0b\x42\x61lanceResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\t\"\x11\n\x0fTotalBalanceReq\"@\n\x10TotalBalanceResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\t\"\x19\n\x06OTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"[\n\x07OTSResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x14\n\x0cots_bitfield\x18\x03 \x03(\x0c\x12\x1d\n\x15next_unused_ots_index\x18\x04 \x01(\x04\"\x0b\n\tHeightReq\"9\n\nHeightResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0e\n\x06height\x18\x03 \x01(\x04\"\x1f\n\x08\x42lockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\t\"H\n\tBlockResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x1e\n\x05\x62lock\x18\x03 \x01(\x0b\x32\x0f.qrl.PlainBlock\"(\n\x10\x42lockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"\x1e\n\x10\x41\x64\x64ressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\t\"A\n\x11\x41\x64\x64ressFromPKResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"\r\n\x0bNodeInfoReq\"\xc1\x01\n\x0cNodeInfoResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x17\n\x0fnum_connections\x18\x04 \x01(\t\x12\x17\n\x0fnum_known_peers\x18\x05 \x01(\t\x12\x0e\n\x06uptime\x18\x06 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x07 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x08 \x01(\t\x12\x12\n\nnetwork_id\x18\t \x01(\t\"7\n\x13PlainGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"5\n\x12PlainAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xce\x07\n\x10PlainTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\t\x12\x11\n\tsignature\x18\x04 \x01(\t\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\t\x12\x13\n\x0bsigner_addr\x18\x07 \x01(\t\x12\x32\n\x08transfer\x18\x08 \x01(\x0b\x32\x1e.qrl.PlainTransaction.TransferH\x00\x12\x32\n\x08\x63oinbase\x18\t \x01(\x0b\x32\x1e.qrl.PlainTransaction.CoinBaseH\x00\x12;\n\tlatticePK\x18\n \x01(\x0b\x32&.qrl.PlainTransaction.LatticePublicKeyH\x00\x12\x30\n\x07message\x18\x0b \x01(\x0b\x32\x1d.qrl.PlainTransaction.MessageH\x00\x12,\n\x05token\x18\x0c \x01(\x0b\x32\x1b.qrl.PlainTransaction.TokenH\x00\x12=\n\x0etransfer_token\x18\r \x01(\x0b\x32#.qrl.PlainTransaction.TransferTokenH\x00\x12,\n\x05slave\x18\x0e \x01(\x0b\x32\x1b.qrl.PlainTransaction.SlaveH\x00\x1a-\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a:\n\x10LatticePublicKey\x12\x10\n\x08kyber_pk\x18\x01 \x01(\t\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\t\x1a\x1f\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\t\x1ay\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x31\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x17.qrl.PlainAddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\t\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\rB\x11\n\x0ftransactionType\"\xdc\x01\n\x10PlainBlockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\t\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\t\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\t\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"\x93\x01\n\nPlainBlock\x12%\n\x06header\x18\x01 \x01(\x0b\x32\x15.qrl.PlainBlockHeader\x12+\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x15.qrl.PlainTransaction\x12\x31\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x18.qrl.PlainGenesisBalance2\xe5\x0f\n\tWalletAPI\x12>\n\rAddNewAddress\x12\x15.qrl.AddNewAddressReq\x1a\x16.qrl.AddNewAddressResp\x12R\n\x17\x41\x64\x64NewAddressWithSlaves\x12\x1f.qrl.AddNewAddressWithSlavesReq\x1a\x16.qrl.AddNewAddressResp\x12>\n\rListAddresses\x12\x15.qrl.ListAddressesReq\x1a\x16.qrl.ListAddressesResp\x12>\n\rRemoveAddress\x12\x15.qrl.RemoveAddressReq\x1a\x16.qrl.RemoveAddressResp\x12=\n\x0eIsValidAddress\x12\x14.qrl.ValidAddressReq\x1a\x15.qrl.ValidAddressResp\x12>\n\rEncryptWallet\x12\x15.qrl.EncryptWalletReq\x1a\x16.qrl.EncryptWalletResp\x12\x35\n\nLockWallet\x12\x12.qrl.LockWalletReq\x1a\x13.qrl.LockWalletResp\x12;\n\x0cUnlockWallet\x12\x14.qrl.UnlockWalletReq\x1a\x15.qrl.UnlockWalletResp\x12G\n\x10GetRecoverySeeds\x12\x18.qrl.GetRecoverySeedsReq\x1a\x19.qrl.GetRecoverySeedsResp\x12>\n\rGetWalletInfo\x12\x15.qrl.GetWalletInfoReq\x1a\x16.qrl.GetWalletInfoResp\x12?\n\x10RelayTransferTxn\x12\x18.qrl.RelayTransferTxnReq\x1a\x11.qrl.RelayTxnResp\x12M\n\x17RelayTransferTxnBySlave\x12\x1f.qrl.RelayTransferTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12=\n\x0fRelayMessageTxn\x12\x17.qrl.RelayMessageTxnReq\x1a\x11.qrl.RelayTxnResp\x12K\n\x16RelayMessageTxnBySlave\x12\x1e.qrl.RelayMessageTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12\x39\n\rRelayTokenTxn\x12\x15.qrl.RelayTokenTxnReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x14RelayTokenTxnBySlave\x12\x1c.qrl.RelayTokenTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12I\n\x15RelayTransferTokenTxn\x12\x1d.qrl.RelayTransferTokenTxnReq\x1a\x11.qrl.RelayTxnResp\x12W\n\x1cRelayTransferTokenTxnBySlave\x12$.qrl.RelayTransferTokenTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12\x39\n\rRelaySlaveTxn\x12\x15.qrl.RelaySlaveTxnReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x14RelaySlaveTxnBySlave\x12\x1c.qrl.RelaySlaveTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x10\x43hangePassphrase\x12\x18.qrl.ChangePassphraseReq\x1a\x19.qrl.ChangePassphraseResp\x12Y\n\x18GetTransactionsByAddress\x12\x1d.qrl.TransactionsByAddressReq\x1a\x1e.qrl.TransactionsByAddressResp\x12;\n\x0eGetTransaction\x12\x13.qrl.TransactionReq\x1a\x14.qrl.TransactionResp\x12/\n\nGetBalance\x12\x0f.qrl.BalanceReq\x1a\x10.qrl.BalanceResp\x12>\n\x0fGetTotalBalance\x12\x14.qrl.TotalBalanceReq\x1a\x15.qrl.TotalBalanceResp\x12#\n\x06GetOTS\x12\x0b.qrl.OTSReq\x1a\x0c.qrl.OTSResp\x12,\n\tGetHeight\x12\x0e.qrl.HeightReq\x1a\x0f.qrl.HeightResp\x12)\n\x08GetBlock\x12\r.qrl.BlockReq\x1a\x0e.qrl.BlockResp\x12\x39\n\x10GetBlockByNumber\x12\x15.qrl.BlockByNumberReq\x1a\x0e.qrl.BlockResp\x12\x41\n\x10GetAddressFromPK\x12\x15.qrl.AddressFromPKReq\x1a\x16.qrl.AddressFromPKResp\x12\x32\n\x0bGetNodeInfo\x12\x10.qrl.NodeInfoReq\x1a\x11.qrl.NodeInfoRespb\x06proto3') + serialized_pb=_b('\n\x0fqrlwallet.proto\x12\x03qrl\x1a\tqrl.proto\"9\n\x10\x41\x64\x64NewAddressReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12\x15\n\rhash_function\x18\x02 \x01(\t\"A\n\x11\x41\x64\x64NewAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"]\n\x1a\x41\x64\x64NewAddressWithSlavesReq\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12\x18\n\x10number_of_slaves\x18\x02 \x01(\x04\x12\x15\n\rhash_function\x18\x03 \x01(\t\"%\n\x15\x41\x64\x64\x41\x64\x64ressFromSeedReq\x12\x0c\n\x04seed\x18\x01 \x01(\t\"F\n\x16\x41\x64\x64\x41\x64\x64ressFromSeedResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"\x12\n\x10ListAddressesReq\"C\n\x11ListAddressesResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x11\n\taddresses\x18\x03 \x03(\t\"#\n\x10RemoveAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"0\n\x11RemoveAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\"\n\x0fValidAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\">\n\x10ValidAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\r\n\x05valid\x18\x03 \x01(\t\"&\n\x10\x45ncryptWalletReq\x12\x12\n\npassphrase\x18\x01 \x01(\t\"0\n\x11\x45ncryptWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"%\n\x0fUnlockWalletReq\x12\x12\n\npassphrase\x18\x01 \x01(\t\"/\n\x10UnlockWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"\x0f\n\rLockWalletReq\"-\n\x0eLockWalletResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"&\n\x13GetRecoverySeedsReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"V\n\x14GetRecoverySeedsResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07hexseed\x18\x03 \x01(\t\x12\x10\n\x08mnemonic\x18\x04 \x01(\t\"\x12\n\x10GetWalletInfoReq\"n\n\x11GetWalletInfoResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\r\x12\x15\n\raddress_count\x18\x04 \x01(\x04\x12\x14\n\x0cis_encrypted\x18\x05 \x01(\x08\"\x8c\x01\n\x13RelayTransferTxnReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\x12\x16\n\x0esigner_address\x18\x05 \x01(\t\x12\x11\n\tots_index\x18\x06 \x01(\x04\"h\n\x1aRelayTransferTxnBySlaveReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\"u\n\x12RelayMessageTxnReq\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x16\n\x0emaster_address\x18\x03 \x01(\t\x12\x16\n\x0esigner_address\x18\x04 \x01(\t\x12\x11\n\tots_index\x18\x05 \x01(\x04\"Q\n\x19RelayMessageTxnBySlaveReq\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x16\n\x0emaster_address\x18\x03 \x01(\t\"\xc5\x01\n\x10RelayTokenTxnReq\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x11\n\taddresses\x18\x05 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x06 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x16\n\x0emaster_address\x18\x08 \x01(\t\x12\x16\n\x0esigner_address\x18\t \x01(\t\x12\x11\n\tots_index\x18\n \x01(\x04\"\xa1\x01\n\x17RelayTokenTxnBySlaveReq\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x11\n\taddresses\x18\x05 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x06 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x16\n\x0emaster_address\x18\x08 \x01(\t\"\xa7\x01\n\x18RelayTransferTokenTxnReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x14\n\x0ctoken_txhash\x18\x02 \x01(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x16\n\x0emaster_address\x18\x05 \x01(\t\x12\x16\n\x0esigner_address\x18\x06 \x01(\t\x12\x11\n\tots_index\x18\x07 \x01(\x04\"\x83\x01\n\x1fRelayTransferTokenTxnBySlaveReq\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x01 \x03(\t\x12\x14\n\x0ctoken_txhash\x18\x02 \x01(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x16\n\x0emaster_address\x18\x05 \x01(\t\"\x8b\x01\n\x10RelaySlaveTxnReq\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\x12\x16\n\x0esigner_address\x18\x05 \x01(\t\x12\x11\n\tots_index\x18\x06 \x01(\x04\"g\n\x17RelaySlaveTxnBySlaveReq\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x03 \x01(\x04\x12\x16\n\x0emaster_address\x18\x04 \x01(\t\"N\n\x0cRelayTxnResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12!\n\x02tx\x18\x03 \x01(\x0b\x32\x15.qrl.PlainTransaction\"C\n\x13\x43hangePassphraseReq\x12\x15\n\roldPassphrase\x18\x01 \x01(\t\x12\x15\n\rnewPassphrase\x18\x02 \x01(\t\"3\n\x14\x43hangePassphraseResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"[\n\x1cMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"~\n\x1dMiniTransactionsByAddressResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12/\n\x11mini_transactions\x18\x03 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"!\n\x0eTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\t\"\x99\x01\n\x0fTransactionResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12!\n\x02tx\x18\x03 \x01(\x0b\x32\x15.qrl.PlainTransaction\x12\x15\n\rconfirmations\x18\x04 \x01(\t\x12\x14\n\x0c\x62lock_number\x18\x05 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x06 \x01(\t\"\x1d\n\nBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\";\n\x0b\x42\x61lanceResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\t\"\x11\n\x0fTotalBalanceReq\"@\n\x10TotalBalanceResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x03 \x01(\t\"\x19\n\x06OTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\"\x9b\x01\n\x07OTSResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x34\n\x14ots_bitfield_by_page\x18\x03 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x04 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x05 \x01(\x08\"\x0b\n\tHeightReq\"9\n\nHeightResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0e\n\x06height\x18\x03 \x01(\x04\"\x1f\n\x08\x42lockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\t\"H\n\tBlockResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x1e\n\x05\x62lock\x18\x03 \x01(\x0b\x32\x0f.qrl.PlainBlock\"(\n\x10\x42lockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"\x1e\n\x10\x41\x64\x64ressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\t\"A\n\x11\x41\x64\x64ressFromPKResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x03 \x01(\t\"\r\n\x0bNodeInfoReq\"\xc1\x01\n\x0cNodeInfoResp\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x17\n\x0fnum_connections\x18\x04 \x01(\t\x12\x17\n\x0fnum_known_peers\x18\x05 \x01(\t\x12\x0e\n\x06uptime\x18\x06 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x07 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x08 \x01(\t\x12\x12\n\nnetwork_id\x18\t \x01(\t\"7\n\x13PlainGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"5\n\x12PlainAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xce\x07\n\x10PlainTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\t\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\t\x12\x11\n\tsignature\x18\x04 \x01(\t\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\t\x12\x13\n\x0bsigner_addr\x18\x07 \x01(\t\x12\x32\n\x08transfer\x18\x08 \x01(\x0b\x32\x1e.qrl.PlainTransaction.TransferH\x00\x12\x32\n\x08\x63oinbase\x18\t \x01(\x0b\x32\x1e.qrl.PlainTransaction.CoinBaseH\x00\x12;\n\tlatticePK\x18\n \x01(\x0b\x32&.qrl.PlainTransaction.LatticePublicKeyH\x00\x12\x30\n\x07message\x18\x0b \x01(\x0b\x32\x1d.qrl.PlainTransaction.MessageH\x00\x12,\n\x05token\x18\x0c \x01(\x0b\x32\x1b.qrl.PlainTransaction.TokenH\x00\x12=\n\x0etransfer_token\x18\r \x01(\x0b\x32#.qrl.PlainTransaction.TransferTokenH\x00\x12,\n\x05slave\x18\x0e \x01(\x0b\x32\x1b.qrl.PlainTransaction.SlaveH\x00\x1a-\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\t\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a:\n\x10LatticePublicKey\x12\x10\n\x08kyber_pk\x18\x01 \x01(\t\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\t\x1a\x1f\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\t\x1ay\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\r\n\x05owner\x18\x03 \x01(\t\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12\x31\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x17.qrl.PlainAddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\t\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\t\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\rB\x11\n\x0ftransactionType\"\xdc\x01\n\x10PlainBlockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\t\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\t\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\t\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"\x93\x01\n\nPlainBlock\x12%\n\x06header\x18\x01 \x01(\x0b\x32\x15.qrl.PlainBlockHeader\x12+\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x15.qrl.PlainTransaction\x12\x31\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x18.qrl.PlainGenesisBalance2\xf1\x0f\n\tWalletAPI\x12>\n\rAddNewAddress\x12\x15.qrl.AddNewAddressReq\x1a\x16.qrl.AddNewAddressResp\x12R\n\x17\x41\x64\x64NewAddressWithSlaves\x12\x1f.qrl.AddNewAddressWithSlavesReq\x1a\x16.qrl.AddNewAddressResp\x12>\n\rListAddresses\x12\x15.qrl.ListAddressesReq\x1a\x16.qrl.ListAddressesResp\x12>\n\rRemoveAddress\x12\x15.qrl.RemoveAddressReq\x1a\x16.qrl.RemoveAddressResp\x12=\n\x0eIsValidAddress\x12\x14.qrl.ValidAddressReq\x1a\x15.qrl.ValidAddressResp\x12>\n\rEncryptWallet\x12\x15.qrl.EncryptWalletReq\x1a\x16.qrl.EncryptWalletResp\x12\x35\n\nLockWallet\x12\x12.qrl.LockWalletReq\x1a\x13.qrl.LockWalletResp\x12;\n\x0cUnlockWallet\x12\x14.qrl.UnlockWalletReq\x1a\x15.qrl.UnlockWalletResp\x12G\n\x10GetRecoverySeeds\x12\x18.qrl.GetRecoverySeedsReq\x1a\x19.qrl.GetRecoverySeedsResp\x12>\n\rGetWalletInfo\x12\x15.qrl.GetWalletInfoReq\x1a\x16.qrl.GetWalletInfoResp\x12?\n\x10RelayTransferTxn\x12\x18.qrl.RelayTransferTxnReq\x1a\x11.qrl.RelayTxnResp\x12M\n\x17RelayTransferTxnBySlave\x12\x1f.qrl.RelayTransferTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12=\n\x0fRelayMessageTxn\x12\x17.qrl.RelayMessageTxnReq\x1a\x11.qrl.RelayTxnResp\x12K\n\x16RelayMessageTxnBySlave\x12\x1e.qrl.RelayMessageTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12\x39\n\rRelayTokenTxn\x12\x15.qrl.RelayTokenTxnReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x14RelayTokenTxnBySlave\x12\x1c.qrl.RelayTokenTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12I\n\x15RelayTransferTokenTxn\x12\x1d.qrl.RelayTransferTokenTxnReq\x1a\x11.qrl.RelayTxnResp\x12W\n\x1cRelayTransferTokenTxnBySlave\x12$.qrl.RelayTransferTokenTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12\x39\n\rRelaySlaveTxn\x12\x15.qrl.RelaySlaveTxnReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x14RelaySlaveTxnBySlave\x12\x1c.qrl.RelaySlaveTxnBySlaveReq\x1a\x11.qrl.RelayTxnResp\x12G\n\x10\x43hangePassphrase\x12\x18.qrl.ChangePassphraseReq\x1a\x19.qrl.ChangePassphraseResp\x12\x65\n\x1cGetMiniTransactionsByAddress\x12!.qrl.MiniTransactionsByAddressReq\x1a\".qrl.MiniTransactionsByAddressResp\x12;\n\x0eGetTransaction\x12\x13.qrl.TransactionReq\x1a\x14.qrl.TransactionResp\x12/\n\nGetBalance\x12\x0f.qrl.BalanceReq\x1a\x10.qrl.BalanceResp\x12>\n\x0fGetTotalBalance\x12\x14.qrl.TotalBalanceReq\x1a\x15.qrl.TotalBalanceResp\x12#\n\x06GetOTS\x12\x0b.qrl.OTSReq\x1a\x0c.qrl.OTSResp\x12,\n\tGetHeight\x12\x0e.qrl.HeightReq\x1a\x0f.qrl.HeightResp\x12)\n\x08GetBlock\x12\r.qrl.BlockReq\x1a\x0e.qrl.BlockResp\x12\x39\n\x10GetBlockByNumber\x12\x15.qrl.BlockByNumberReq\x1a\x0e.qrl.BlockResp\x12\x41\n\x10GetAddressFromPK\x12\x15.qrl.AddressFromPKReq\x1a\x16.qrl.AddressFromPKResp\x12\x32\n\x0bGetNodeInfo\x12\x10.qrl.NodeInfoReq\x1a\x11.qrl.NodeInfoRespb\x06proto3') , dependencies=[qrl__pb2.DESCRIPTOR,]) @@ -1578,20 +1578,34 @@ ) -_TRANSACTIONSBYADDRESSREQ = _descriptor.Descriptor( - name='TransactionsByAddressReq', - full_name='qrl.TransactionsByAddressReq', +_MINITRANSACTIONSBYADDRESSREQ = _descriptor.Descriptor( + name='MiniTransactionsByAddressReq', + full_name='qrl.MiniTransactionsByAddressReq', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='qrl.TransactionsByAddressReq.address', index=0, + name='address', full_name='qrl.MiniTransactionsByAddressReq.address', index=0, number=1, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='item_per_page', full_name='qrl.MiniTransactionsByAddressReq.item_per_page', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='page_number', full_name='qrl.MiniTransactionsByAddressReq.page_number', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1605,40 +1619,40 @@ oneofs=[ ], serialized_start=2713, - serialized_end=2756, + serialized_end=2804, ) -_TRANSACTIONSBYADDRESSRESP = _descriptor.Descriptor( - name='TransactionsByAddressResp', - full_name='qrl.TransactionsByAddressResp', +_MINITRANSACTIONSBYADDRESSRESP = _descriptor.Descriptor( + name='MiniTransactionsByAddressResp', + full_name='qrl.MiniTransactionsByAddressResp', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='code', full_name='qrl.TransactionsByAddressResp.code', index=0, + name='code', full_name='qrl.MiniTransactionsByAddressResp.code', index=0, number=1, type=13, cpp_type=3, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='error', full_name='qrl.TransactionsByAddressResp.error', index=1, + name='error', full_name='qrl.MiniTransactionsByAddressResp.error', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=_b("").decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='mini_transactions', full_name='qrl.TransactionsByAddressResp.mini_transactions', index=2, + name='mini_transactions', full_name='qrl.MiniTransactionsByAddressResp.mini_transactions', index=2, number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='balance', full_name='qrl.TransactionsByAddressResp.balance', index=3, + name='balance', full_name='qrl.MiniTransactionsByAddressResp.balance', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, @@ -1656,8 +1670,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2758, - serialized_end=2880, + serialized_start=2806, + serialized_end=2932, ) @@ -1687,8 +1701,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2882, - serialized_end=2915, + serialized_start=2934, + serialized_end=2967, ) @@ -1753,8 +1767,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2918, - serialized_end=3071, + serialized_start=2970, + serialized_end=3123, ) @@ -1784,8 +1798,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3073, - serialized_end=3102, + serialized_start=3125, + serialized_end=3154, ) @@ -1829,8 +1843,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3104, - serialized_end=3163, + serialized_start=3156, + serialized_end=3215, ) @@ -1853,8 +1867,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3165, - serialized_end=3182, + serialized_start=3217, + serialized_end=3234, ) @@ -1898,8 +1912,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3184, - serialized_end=3248, + serialized_start=3236, + serialized_end=3300, ) @@ -1929,8 +1943,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3250, - serialized_end=3275, + serialized_start=3302, + serialized_end=3327, ) @@ -1956,8 +1970,8 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='ots_bitfield', full_name='qrl.OTSResp.ots_bitfield', index=2, - number=3, type=12, cpp_type=9, label=3, + name='ots_bitfield_by_page', full_name='qrl.OTSResp.ots_bitfield_by_page', index=2, + number=3, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1969,6 +1983,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unused_ots_index_found', full_name='qrl.OTSResp.unused_ots_index_found', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1981,8 +2002,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3277, - serialized_end=3368, + serialized_start=3330, + serialized_end=3485, ) @@ -2005,8 +2026,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3370, - serialized_end=3381, + serialized_start=3487, + serialized_end=3498, ) @@ -2050,8 +2071,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3383, - serialized_end=3440, + serialized_start=3500, + serialized_end=3557, ) @@ -2081,8 +2102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3442, - serialized_end=3473, + serialized_start=3559, + serialized_end=3590, ) @@ -2126,8 +2147,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3475, - serialized_end=3547, + serialized_start=3592, + serialized_end=3664, ) @@ -2157,8 +2178,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3549, - serialized_end=3589, + serialized_start=3666, + serialized_end=3706, ) @@ -2188,8 +2209,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3591, - serialized_end=3621, + serialized_start=3708, + serialized_end=3738, ) @@ -2233,8 +2254,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3623, - serialized_end=3688, + serialized_start=3740, + serialized_end=3805, ) @@ -2257,8 +2278,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3690, - serialized_end=3703, + serialized_start=3807, + serialized_end=3820, ) @@ -2344,8 +2365,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3706, - serialized_end=3899, + serialized_start=3823, + serialized_end=4016, ) @@ -2382,8 +2403,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3901, - serialized_end=3956, + serialized_start=4018, + serialized_end=4073, ) @@ -2420,8 +2441,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3958, - serialized_end=4011, + serialized_start=4075, + serialized_end=4128, ) @@ -2458,8 +2479,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4539, - serialized_end=4584, + serialized_start=4656, + serialized_end=4701, ) _PLAINTRANSACTION_COINBASE = _descriptor.Descriptor( @@ -2495,8 +2516,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4586, - serialized_end=4629, + serialized_start=4703, + serialized_end=4746, ) _PLAINTRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -2532,8 +2553,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4631, - serialized_end=4689, + serialized_start=4748, + serialized_end=4806, ) _PLAINTRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -2562,8 +2583,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4691, - serialized_end=4722, + serialized_start=4808, + serialized_end=4839, ) _PLAINTRANSACTION_TOKEN = _descriptor.Descriptor( @@ -2620,8 +2641,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4724, - serialized_end=4845, + serialized_start=4841, + serialized_end=4962, ) _PLAINTRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -2664,8 +2685,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4847, - serialized_end=4919, + serialized_start=4964, + serialized_end=5036, ) _PLAINTRANSACTION_SLAVE = _descriptor.Descriptor( @@ -2701,8 +2722,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4921, - serialized_end=4969, + serialized_start=5038, + serialized_end=5086, ) _PLAINTRANSACTION = _descriptor.Descriptor( @@ -2825,8 +2846,8 @@ name='transactionType', full_name='qrl.PlainTransaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=4014, - serialized_end=4988, + serialized_start=4131, + serialized_end=5105, ) @@ -2912,8 +2933,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4991, - serialized_end=5211, + serialized_start=5108, + serialized_end=5328, ) @@ -2957,13 +2978,14 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5214, - serialized_end=5361, + serialized_start=5331, + serialized_end=5478, ) _RELAYTXNRESP.fields_by_name['tx'].message_type = _PLAINTRANSACTION -_TRANSACTIONSBYADDRESSRESP.fields_by_name['mini_transactions'].message_type = qrl__pb2._MINITRANSACTION +_MINITRANSACTIONSBYADDRESSRESP.fields_by_name['mini_transactions'].message_type = qrl__pb2._MINITRANSACTION _TRANSACTIONRESP.fields_by_name['tx'].message_type = _PLAINTRANSACTION +_OTSRESP.fields_by_name['ots_bitfield_by_page'].message_type = qrl__pb2._OTSBITFIELDBYPAGE _BLOCKRESP.fields_by_name['block'].message_type = _PLAINBLOCK _PLAINTRANSACTION_TRANSFER.containing_type = _PLAINTRANSACTION _PLAINTRANSACTION_COINBASE.containing_type = _PLAINTRANSACTION @@ -3038,8 +3060,8 @@ DESCRIPTOR.message_types_by_name['RelayTxnResp'] = _RELAYTXNRESP DESCRIPTOR.message_types_by_name['ChangePassphraseReq'] = _CHANGEPASSPHRASEREQ DESCRIPTOR.message_types_by_name['ChangePassphraseResp'] = _CHANGEPASSPHRASERESP -DESCRIPTOR.message_types_by_name['TransactionsByAddressReq'] = _TRANSACTIONSBYADDRESSREQ -DESCRIPTOR.message_types_by_name['TransactionsByAddressResp'] = _TRANSACTIONSBYADDRESSRESP +DESCRIPTOR.message_types_by_name['MiniTransactionsByAddressReq'] = _MINITRANSACTIONSBYADDRESSREQ +DESCRIPTOR.message_types_by_name['MiniTransactionsByAddressResp'] = _MINITRANSACTIONSBYADDRESSRESP DESCRIPTOR.message_types_by_name['TransactionReq'] = _TRANSACTIONREQ DESCRIPTOR.message_types_by_name['TransactionResp'] = _TRANSACTIONRESP DESCRIPTOR.message_types_by_name['BalanceReq'] = _BALANCEREQ @@ -3302,19 +3324,19 @@ )) _sym_db.RegisterMessage(ChangePassphraseResp) -TransactionsByAddressReq = _reflection.GeneratedProtocolMessageType('TransactionsByAddressReq', (_message.Message,), dict( - DESCRIPTOR = _TRANSACTIONSBYADDRESSREQ, +MiniTransactionsByAddressReq = _reflection.GeneratedProtocolMessageType('MiniTransactionsByAddressReq', (_message.Message,), dict( + DESCRIPTOR = _MINITRANSACTIONSBYADDRESSREQ, __module__ = 'qrlwallet_pb2' - # @@protoc_insertion_point(class_scope:qrl.TransactionsByAddressReq) + # @@protoc_insertion_point(class_scope:qrl.MiniTransactionsByAddressReq) )) -_sym_db.RegisterMessage(TransactionsByAddressReq) +_sym_db.RegisterMessage(MiniTransactionsByAddressReq) -TransactionsByAddressResp = _reflection.GeneratedProtocolMessageType('TransactionsByAddressResp', (_message.Message,), dict( - DESCRIPTOR = _TRANSACTIONSBYADDRESSRESP, +MiniTransactionsByAddressResp = _reflection.GeneratedProtocolMessageType('MiniTransactionsByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _MINITRANSACTIONSBYADDRESSRESP, __module__ = 'qrlwallet_pb2' - # @@protoc_insertion_point(class_scope:qrl.TransactionsByAddressResp) + # @@protoc_insertion_point(class_scope:qrl.MiniTransactionsByAddressResp) )) -_sym_db.RegisterMessage(TransactionsByAddressResp) +_sym_db.RegisterMessage(MiniTransactionsByAddressResp) TransactionReq = _reflection.GeneratedProtocolMessageType('TransactionReq', (_message.Message,), dict( DESCRIPTOR = _TRANSACTIONREQ, @@ -3534,8 +3556,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=5364, - serialized_end=7385, + serialized_start=5481, + serialized_end=7514, methods=[ _descriptor.MethodDescriptor( name='AddNewAddress', @@ -3727,12 +3749,12 @@ options=None, ), _descriptor.MethodDescriptor( - name='GetTransactionsByAddress', - full_name='qrl.WalletAPI.GetTransactionsByAddress', + name='GetMiniTransactionsByAddress', + full_name='qrl.WalletAPI.GetMiniTransactionsByAddress', index=21, containing_service=None, - input_type=_TRANSACTIONSBYADDRESSREQ, - output_type=_TRANSACTIONSBYADDRESSRESP, + input_type=_MINITRANSACTIONSBYADDRESSREQ, + output_type=_MINITRANSACTIONSBYADDRESSRESP, options=None, ), _descriptor.MethodDescriptor( diff --git a/src/qrl/generated/qrlwallet_pb2_grpc.py b/src/qrl/generated/qrlwallet_pb2_grpc.py index d63f2eaac..1a5ca73a4 100644 --- a/src/qrl/generated/qrlwallet_pb2_grpc.py +++ b/src/qrl/generated/qrlwallet_pb2_grpc.py @@ -127,10 +127,10 @@ def __init__(self, channel): request_serializer=qrlwallet__pb2.ChangePassphraseReq.SerializeToString, response_deserializer=qrlwallet__pb2.ChangePassphraseResp.FromString, ) - self.GetTransactionsByAddress = channel.unary_unary( - '/qrl.WalletAPI/GetTransactionsByAddress', - request_serializer=qrlwallet__pb2.TransactionsByAddressReq.SerializeToString, - response_deserializer=qrlwallet__pb2.TransactionsByAddressResp.FromString, + self.GetMiniTransactionsByAddress = channel.unary_unary( + '/qrl.WalletAPI/GetMiniTransactionsByAddress', + request_serializer=qrlwallet__pb2.MiniTransactionsByAddressReq.SerializeToString, + response_deserializer=qrlwallet__pb2.MiniTransactionsByAddressResp.FromString, ) self.GetTransaction = channel.unary_unary( '/qrl.WalletAPI/GetTransaction', @@ -319,7 +319,7 @@ def ChangePassphrase(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def GetTransactionsByAddress(self, request, context): + def GetMiniTransactionsByAddress(self, request, context): # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -487,10 +487,10 @@ def add_WalletAPIServicer_to_server(servicer, server): request_deserializer=qrlwallet__pb2.ChangePassphraseReq.FromString, response_serializer=qrlwallet__pb2.ChangePassphraseResp.SerializeToString, ), - 'GetTransactionsByAddress': grpc.unary_unary_rpc_method_handler( - servicer.GetTransactionsByAddress, - request_deserializer=qrlwallet__pb2.TransactionsByAddressReq.FromString, - response_serializer=qrlwallet__pb2.TransactionsByAddressResp.SerializeToString, + 'GetMiniTransactionsByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetMiniTransactionsByAddress, + request_deserializer=qrlwallet__pb2.MiniTransactionsByAddressReq.FromString, + response_serializer=qrlwallet__pb2.MiniTransactionsByAddressResp.SerializeToString, ), 'GetTransaction': grpc.unary_unary_rpc_method_handler( servicer.GetTransaction, diff --git a/src/qrl/grpcProxy.py b/src/qrl/grpcProxy.py index 4cb59704a..b1d2dd74b 100644 --- a/src/qrl/grpcProxy.py +++ b/src/qrl/grpcProxy.py @@ -161,6 +161,7 @@ def getblocktemplate(reserve_size, wallet_address): 'difficulty': grpc_response.difficulty, 'height': grpc_response.height, 'reserved_offset': grpc_response.reserved_offset, + 'seed_hash': grpc_response.seed_hash, 'status': 'OK' } @@ -205,6 +206,7 @@ def transfer(destinations, fee, mixin, unlock_time): tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, + message_data=None, fee=fee, xmss_pk=xmss.pk, master_addr=payment_slaves[0]) diff --git a/src/qrl/main.py b/src/qrl/main.py index f659eb3a7..3e5f3886a 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -3,8 +3,6 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import argparse import faulthandler -import logging -import threading from os.path import expanduser from mock import MagicMock @@ -15,27 +13,12 @@ from qrl.core.Block import Block from qrl.core.ChainManager import ChainManager from qrl.core.GenesisBlock import GenesisBlock -from qrl.core.misc import ntp, logger, logger_twisted +from qrl.core.misc import ntp, logger, set_logger from qrl.core.qrlnode import QRLNode from qrl.services.services import start_services from qrl.core import config from qrl.core.State import State -LOG_FORMAT_CUSTOM = '%(asctime)s|%(version)s|%(node_state)s|%(thread_id)s| %(levelname)s : %(message)s' - - -class ContextFilter(logging.Filter): - def __init__(self, node_state, version): - super(ContextFilter, self).__init__() - self.node_state = node_state - self.version = version - - def filter(self, record): - record.node_state = "{:<8}".format(self.node_state.state.name) - record.version = self.version - record.thread_id = "{:<11}".format(threading.current_thread().name) - return True - def parse_arguments(): parser = argparse.ArgumentParser(description='QRL node') @@ -60,21 +43,6 @@ def parse_arguments(): return parser.parse_args() -def set_logger(args, sync_state): - log_level = logging.INFO - if args.logLevel: - log_level = getattr(logging, args.logLevel) - logger.initialize_default(force_console_output=not args.quiet).setLevel(log_level) - custom_filter = ContextFilter(sync_state, config.dev.version) - logger.logger.addFilter(custom_filter) - file_handler = logger.log_to_file() - file_handler.addFilter(custom_filter) - file_handler.setLevel(logging.DEBUG) - logger.set_colors(not args.no_colors, LOG_FORMAT_CUSTOM) - logger.set_unhandled_exception_handler() - logger_twisted.enable_twisted_log_observer() - - def get_mining_address(mining_address: str): try: if not mining_address: @@ -113,7 +81,7 @@ def main(): config.user.mining_enabled = True config.user.mining_thread_count = 1 config.user.mining_pause = 500 - config.dev.mining_setpoint_blocktime = 1 + config.dev.block_timing_in_seconds = 1 config.user.genesis_difficulty = 2 # Mocknet mining address @@ -143,7 +111,7 @@ def main(): qrlnode = QRLNode(mining_address=mining_address) qrlnode.set_chain_manager(chain_manager) - set_logger(args, qrlnode.sync_state) + set_logger.set_logger(args, qrlnode.sync_state) ####### # NOTE: Keep assigned to a variable or might get collected @@ -161,5 +129,4 @@ def main(): elif args.mining_address or args.mining_thread_count: logger.warning('Mining is not enabled but you sent some "mining related" param via CLI') - # FIXME: This will be removed once we move away from Twisted reactor.run() diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index 9cf46452d..e1d628704 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -17,15 +17,19 @@ package qrl; service PublicAPI { rpc GetNodeState (GetNodeStateReq) returns (GetNodeStateResp); - + rpc GetKnownPeers (GetKnownPeersReq) returns (GetKnownPeersResp); rpc GetPeersStat (GetPeersStatReq) returns (GetPeersStatResp); rpc GetStats (GetStatsReq) returns (GetStatsResp); - + rpc GetAddressState (GetAddressStateReq) returns (GetAddressStateResp); - + + rpc GetMultiSigAddressState (GetMultiSigAddressStateReq) returns (GetMultiSigAddressStateResp); + + rpc IsSlave (IsSlaveReq) returns (IsSlaveResp); + rpc GetObject(GetObjectReq) returns (GetObjectResp); rpc GetLatestData(GetLatestDataReq) returns (GetLatestDataResp); @@ -33,13 +37,19 @@ service PublicAPI rpc PushTransaction (PushTransactionReq) returns (PushTransactionResp); rpc TransferCoins (TransferCoinsReq) returns (TransferCoinsResp); - + rpc ParseAddress (ParseAddressReq) returns (ParseAddressResp); rpc GetChainStats (GetChainStatsReq) returns (GetChainStatsResp); rpc GetAddressFromPK (GetAddressFromPKReq) returns (GetAddressFromPKResp); + rpc GetMultiSigCreateTxn (MultiSigCreateTxnReq) returns (TransferCoinsResp); + + rpc GetMultiSigSpendTxn (MultiSigSpendTxnReq) returns (TransferCoinsResp); + + rpc GetMultiSigVoteTxn (MultiSigVoteTxnReq) returns (TransferCoinsResp); + rpc GetMessageTxn (MessageTxnReq) returns (TransferCoinsResp); rpc GetTokenTxn (TokenTxnReq) returns (TransferCoinsResp); @@ -48,10 +58,26 @@ service PublicAPI rpc GetSlaveTxn (SlaveTxnReq) returns (TransferCoinsResp); - rpc GetTransactionsByAddress(GetTransactionsByAddressReq) returns (GetTransactionsByAddressResp); + rpc GetLatticeTxn (LatticeTxnReq) returns (TransferCoinsResp); rpc GetTransaction(GetTransactionReq) returns (GetTransactionResp); + rpc GetMiniTransactionsByAddress(GetMiniTransactionsByAddressReq) returns (GetMiniTransactionsByAddressResp); + + rpc GetTransactionsByAddress(GetTransactionsByAddressReq) returns (GetTransactionsByAddressResp); + + rpc GetTokensByAddress(GetTransactionsByAddressReq) returns (GetTokensByAddressResp); + + rpc GetSlavesByAddress(GetTransactionsByAddressReq) returns (GetSlavesByAddressResp); + + rpc GetLatticePKsByAddress(GetTransactionsByAddressReq) returns (GetLatticePKsByAddressResp); + + rpc GetMultiSigAddressesByAddress(GetTransactionsByAddressReq) returns (GetMultiSigAddressesByAddressResp); + + rpc GetMultiSigSpendTxsByAddress(GetMultiSigSpendTxsByAddressReq) returns (GetMultiSigSpendTxsByAddressResp); + + rpc GetVoteStats(GetVoteStatsReq) returns (GetVoteStatsResp); + rpc GetBalance(GetBalanceReq) returns (GetBalanceResp); rpc GetTotalBalance(GetTotalBalanceReq) returns (GetTotalBalanceResp); @@ -136,7 +162,6 @@ message GetChainStatsResp { string state_size_gb = 3; // gigabytes } - /** * Represents a query to get statistics about node */ @@ -186,16 +211,31 @@ message BlockDataPoint bytes header_hash_prev = 8; // Previous block's header hash } - -message GetAddressStateReq { +message GetAddressStateReq { bytes address = 1; bool exclude_ots_bitfield = 2; bool exclude_transaction_hashes = 3; } message GetAddressStateResp { - - AddressState state = 1; + OptimizedAddressState state = 1; +} + +message GetMultiSigAddressStateReq { + bytes address = 1; +} + +message GetMultiSigAddressStateResp { + MultiSigAddressState state = 1; +} + +message IsSlaveReq { + bytes master_address = 1; + bytes slave_pk = 2; +} + +message IsSlaveResp { + bool result = 1; } message ParseAddressReq { @@ -212,7 +252,7 @@ message GetObjectReq { bytes query = 1; } message GetObjectResp { bool found = 1; oneof result { - AddressState address_state = 2; + OptimizedAddressState address_state = 2; TransactionExtended transaction = 3; BlockExtended block_extended = 4; } @@ -238,10 +278,11 @@ message GetLatestDataResp { message TransferCoinsReq { bytes master_addr = 1; // Transaction source address - repeated bytes addresses_to = 2; // Transaction destination address - repeated uint64 amounts = 3; // Amount. It should be expressed in Shor - uint64 fee = 4; // Fee. It should be expressed in Shor - bytes xmss_pk = 5; // XMSS Public key + repeated bytes addresses_to = 2; // Transaction destination address + repeated uint64 amounts = 3; // Amount. It should be expressed in Shor + bytes message_data = 4; // Message Data. Optional field to send messages + uint64 fee = 5; // Fee. It should be expressed in Shor + bytes xmss_pk = 6; // XMSS Public key } message TransferCoinsResp { @@ -262,11 +303,45 @@ message PushTransactionResp { bytes tx_hash = 3; } +message MultiSigCreateTxnReq { + bytes master_addr = 1; + + repeated bytes signatories = 2; + repeated uint32 weights = 3; + uint32 threshold = 4; + + uint64 fee = 5; + bytes xmss_pk = 6; +} + +message MultiSigSpendTxnReq { + bytes master_addr = 1; + + bytes multi_sig_address = 2; + repeated bytes addrs_to = 3; + repeated uint64 amounts = 4; + uint64 expiry_block_number = 5; + + uint64 fee = 6; + bytes xmss_pk = 7; +} + +message MultiSigVoteTxnReq { + bytes master_addr = 1; + + bytes shared_key = 2; + bool unvote = 3; + + uint64 fee = 4; + bytes xmss_pk = 5; +} + message MessageTxnReq { bytes master_addr = 1; bytes message = 2; - uint64 fee = 3; - bytes xmss_pk = 4; + bytes addr_to = 3; + uint64 fee = 4; + bytes xmss_pk = 5; } message TokenTxnReq { @@ -297,21 +372,22 @@ message SlaveTxnReq { bytes xmss_pk = 5; } +message LatticeTxnReq { + bytes master_addr = 1; + bytes pk1 = 2; + bytes pk2 = 3; + bytes pk3 = 4; + bytes pk4 = 5; + uint64 fee = 6; + bytes xmss_pk = 7; +} + message MiniTransaction { string transaction_hash = 1; bool out = 2; uint64 amount = 3; } -message GetTransactionsByAddressReq { - bytes address = 1; -} - -message GetTransactionsByAddressResp { - repeated MiniTransaction mini_transactions = 1; - uint64 balance = 2; -} - message GetTransactionReq { bytes tx_hash = 1; } @@ -321,6 +397,97 @@ message GetTransactionResp { uint64 confirmations = 2; uint64 block_number = 3; bytes block_header_hash = 4; + uint64 timestamp = 5; + bytes addr_from = 6; +} + +message GetMiniTransactionsByAddressReq { + bytes address = 1; + uint64 item_per_page = 2; + uint64 page_number = 3; +} + +message GetMiniTransactionsByAddressResp { + repeated MiniTransaction mini_transactions = 1; + uint64 balance = 2; +} + +message GetTransactionsByAddressReq { + bytes address = 1; + uint64 item_per_page = 2; + uint64 page_number = 3; +} + +message GetTransactionsByAddressResp { + repeated GetTransactionResp transactions_detail = 1; +} + +message GetMultiSigSpendTxsByAddressReq { + enum FilterType { + NONE = 0; + EXECUTED_ONLY = 1; + NON_EXECUTED = 2; + EXPIRED = 3; + NON_EXPIRED = 4; + NON_EXECUTED_EXPIRED = 5; + NON_EXECUTED_NON_EXPIRED = 6; + } + bytes address = 1; + uint64 item_per_page = 2; + uint64 page_number = 3; + FilterType filter_type = 4; +} + +message GetMultiSigSpendTxsByAddressResp { + repeated GetTransactionResp transactions_detail = 1; +} + +message GetVoteStatsReq { + bytes multi_sig_spend_tx_hash = 1; +} + +message GetVoteStatsResp { + VoteStats vote_stats = 1; +} + +message TokenDetail { + bytes token_txhash = 1; + bytes name = 2; + bytes symbol = 3; + uint64 balance = 4; +} + +message GetTokensByAddressResp { + repeated TokenDetail tokens_detail = 1; +} + +message SlaveDetail { + bytes slave_address = 1; + uint64 access_type = 2; +} + +message GetSlavesByAddressResp { + repeated SlaveDetail slaves_detail = 1; +} + +message LatticePKsDetail { + bytes pk1 = 1; + bytes pk2 = 2; + bytes pk3 = 3; + bytes pk4 = 4; +} + +message GetLatticePKsByAddressResp { + repeated LatticePKsDetail lattice_pks_detail = 1; +} + +message MultiSigDetail { + bytes address = 1; + uint64 balance = 2; +} + +message GetMultiSigAddressesByAddressResp { + repeated MultiSigDetail multi_sig_detail = 1; } message GetBalanceReq { @@ -341,11 +508,20 @@ message GetTotalBalanceResp { message GetOTSReq { bytes address = 1; + uint64 page_from = 2; + uint64 page_count = 3; + uint64 unused_ots_index_from = 4; } -message GetOTSResp { +message OTSBitfieldByPage { repeated bytes ots_bitfield = 1; + uint64 page_number = 2; +} + +message GetOTSResp { + repeated OTSBitfieldByPage ots_bitfield_by_page = 1; uint64 next_unused_ots_index = 2; + bool unused_ots_index_found = 3; } message GetHeightReq { @@ -440,10 +616,65 @@ message AddressState { uint64 ots_counter = 9; } +message OptimizedAddressState { + bytes address = 1; + uint64 balance = 2; + uint64 nonce = 3; // FIXME: Discuss. 32 or 64 bits? + uint64 ots_bitfield_used_page = 4; // Keep track of last page till which all ots key has been used + uint64 used_ots_key_count = 5; // Keep track of number of ots key that has been used + uint64 transaction_hash_count = 6; + uint64 tokens_count = 7; + uint64 slaves_count = 8; + uint64 lattice_pk_count = 9; + uint64 multi_sig_address_count = 10; + uint64 multi_sig_spend_count = 11; + + repeated bytes foundation_multi_sig_spend_txn_hash = 12; + repeated bytes foundation_multi_sig_vote_txn_hash = 13; + repeated bytes unvotes = 14; + + repeated Transaction proposal_vote_stats = 15; +} + +message MultiSigAddressState { + bytes address = 1; + bytes creation_tx_hash = 2; + uint64 nonce = 3; + uint64 balance = 4; + repeated bytes signatories = 5; + repeated uint32 weights = 6; + uint32 threshold = 7; + uint64 transaction_hash_count = 8; + uint64 multi_sig_spend_count = 9; + // TODO: To be implemented + uint64 multi_sig_address_count = 10; + + repeated bytes foundation_multi_sig_spend_txn_hash = 11; + repeated bytes foundation_multi_sig_vote_txn_hash = 12; + repeated bytes unvotes = 13; + + repeated Transaction proposal_vote_stats = 14; +} + +message MultiSigAddressesList { + repeated bytes hashes = 1; +} + +message DataList { + repeated bytes values = 1; +} + +message Bitfield { + repeated bytes bitfields = 1; +} + +message TransactionHashList { + repeated bytes hashes = 1; +} + message LatticePK { - bytes txhash = 1; + bytes kyber_pk = 1; bytes dilithium_pk = 2; - bytes kyber_pk = 3; } message AddressAmount { @@ -526,12 +757,20 @@ message Transaction { Token token = 11; TransferToken transfer_token = 12; Slave slave = 13; + + MultiSigCreate multi_sig_create = 14; + MultiSigSpend multi_sig_spend = 15; + MultiSigVote multi_sig_vote = 16; + + ProposalCreate proposal_create = 17; + ProposalVote proposal_vote = 18; } ////////// message Transfer { repeated bytes addrs_to = 1; repeated uint64 amounts = 2; + bytes message_data = 3; } message CoinBase { @@ -540,12 +779,15 @@ message Transaction { } message LatticePublicKey { - bytes kyber_pk = 1; - bytes dilithium_pk = 2; + bytes pk1 = 1; // kyber_pk + bytes pk2 = 2; // dilithium_pk + bytes pk3 = 3; // ecdsa_pk + bytes pk4 = 4; // ecies_pk } message Message { bytes message_hash = 1; + bytes addr_to = 2; } message Token { @@ -566,12 +808,141 @@ message Transaction { repeated bytes slave_pks = 1; repeated uint32 access_types = 2; } + + message MultiSigCreate { + repeated bytes signatories = 1; + repeated uint32 weights = 2; + uint32 threshold = 3; + } + + message MultiSigSpend { + bytes multi_sig_address = 1; + repeated bytes addrs_to = 2; + repeated uint64 amounts = 3; + uint64 expiry_block_number = 4; + } + + message MultiSigVote { + bytes shared_key = 1; + bool unvote = 2; + + bytes prev_tx_hash = 3; // To be used internally by State + } + + message ProposalCreate { + uint64 expiry_block_number = 1; + string description = 2; + + oneof proposalType { + QIP qip = 3; + Config config = 4; + Other other = 5; + } + + message QIP { + string qip_link = 1; + } + + message Config { + repeated bytes changes_bitfield = 1; + + uint64 reorg_limit = 2; + uint64 max_coin_supply = 3; + uint64 complete_emission_time_span_in_years = 4; + + uint64 mining_nonce_offset = 5; + uint64 extra_nonce_offset = 6; + uint64 mining_blob_size_in_bytes = 7; + uint64 block_timing_in_seconds = 8; + + uint64 number_of_blocks_analyze = 9; + uint64 block_size_multiplier = 10; // Support upto 2 decimal places + uint64 block_min_size_limit_in_bytes = 11; + + uint64 transaction_multi_output_limit = 12; + + uint64 message_max_length = 13; + + uint64 token_symbol_max_length = 14; + uint64 token_name_max_length = 15; + + uint64 lattice_pk1_max_length = 16; + uint64 lattice_pk2_max_length = 17; + uint64 lattice_pk3_max_length = 18; + uint64 lattice_pk4_max_length = 19; + + uint64 foundation_multi_sig_address_threshold_percentage = 20; + + uint64 proposal_threshold_per = 21; + repeated string proposal_default_options = 22; + uint64 description_max_length = 23; + uint64 options_max_number = 24; + uint64 option_max_text_length = 25; + uint64 proposal_config_activation_delay = 26; + + uint64 N_measurement = 27; + uint64 kp = 28; + } + + message Other { + repeated string options = 1; + } + } + + message ProposalVote { + bytes shared_key = 1; + uint32 option = 2; + } +} + +message VoteStats { + bytes multi_sig_address = 1; + bytes shared_key = 2; + repeated bytes signatories = 3; + repeated bytes tx_hashes = 4; + repeated bool unvotes = 5; + uint64 expiry_block_number = 6; + uint64 total_weight = 7; + bool executed = 8; +} + +message ProposalVoteStats { + bytes addr_from = 1; + bytes shared_key = 2; + string proposal_type = 3; + repeated uint64 weight_by_option = 4; + uint64 expiry_block_number = 5; + bool executed = 6; + + uint64 number_of_tx_hashes = 7; // Keep track of number of pages for vote txn hash +} + +message ProposalRecord { + uint64 number_of_tx_hashes = 1; } message TokenList { repeated bytes token_txhash = 1; } +message TokenBalance { + uint64 balance = 1; + uint64 decimals = 2; + bool delete = 3; // For internal use only +} + +message SlaveMetadata { + uint64 access_type = 1; + bytes tx_hash = 2; + bool delete = 3; +} + +message LatticePKMetadata { + bool enabled = 1; + bytes tx_hash = 2; + bool delete = 3; +} + message TokenMetadata { bytes token_txhash = 1; repeated bytes transfer_token_tx_hashes = 2; @@ -611,21 +982,6 @@ message BlockNumberMapping { bytes prev_headerhash = 2; } -message StateLoader { - repeated bytes addresses = 1; - repeated bytes token_txhash = 2; - repeated bytes txhash = 3; - uint64 total_coin_supply = 4; -} - -message StateObjects { - repeated bytes state_loaders = 1; -} - -message LRUStateCache { - -} - message PeerStat { bytes peer_ip = 1; uint32 port = 2; @@ -660,3 +1016,84 @@ message PeerInfo { message Peers { repeated PeerInfo peer_info_list = 1; } + +message DevConfig { + bytes prev_state_key = 1; + bytes current_state_key = 2; + bytes activation_header_hash = 3; + uint64 activation_block_number = 4; + + Chain chain = 5; + Block block = 6; + Transaction transaction = 7; + POW pow = 8; + + message Chain { + uint64 reorg_limit = 1; + uint64 max_coin_supply = 2; + uint64 complete_emission_time_span_in_years = 3; + } + + message Block { + uint64 mining_nonce_offset = 1; + uint64 extra_nonce_offset = 2; + uint64 mining_blob_size_in_bytes = 3; + uint64 block_timing_in_seconds = 4; + BlockSizeController block_size_controller = 5; + + message BlockSizeController { + uint64 number_of_blocks_analyze = 1; + uint64 size_multiplier = 2; // Support upto 2 decimal places + uint64 block_min_size_limit_in_bytes = 3; + } + } + + message Transaction { + uint64 multi_output_limit = 1; + Message message = 2; + Slave slave = 3; + Token token = 4; + Lattice lattice = 5; + FoundationMultiSig foundation_multi_sig = 6; + Proposal proposal = 7; + + message Message { + uint64 max_length = 1; + } + + message Slave { + uint64 slave_pk_max_length = 2; + } + + message Token { + uint64 symbol_max_length = 1; + uint64 name_max_length = 2; + } + + message Lattice { + uint64 pk1_max_length = 1; + uint64 pk2_max_length = 2; + uint64 pk3_max_length = 3; + uint64 pk4_max_length = 4; + } + + message FoundationMultiSig { + uint64 threshold_percentage = 1; // Support upto 2 decimal places + } + + message Proposal { + uint64 threshold_per = 1; // Support upto 2 decimal places + repeated string default_options = 2; // Convention: All strings must be in capital letters + + uint64 description_max_length = 3; + uint64 options_max_number = 4; + uint64 option_max_text_length = 5; + uint64 proposal_config_activation_delay = 6; + } + } + + message POW { + uint64 N_measurement = 1; + uint64 kp = 2; + } +} \ No newline at end of file diff --git a/src/qrl/protos/qrllegacy.proto b/src/qrl/protos/qrllegacy.proto index ad2ed6169..f87186958 100644 --- a/src/qrl/protos/qrllegacy.proto +++ b/src/qrl/protos/qrllegacy.proto @@ -21,7 +21,7 @@ message LegacyMessage { PB = 7; // Push Block BH = 8; // Block Height - TX = 9; // Transfer Transaction + TX = 9; // Transfer Transaction LT = 10; // Lattice Transaction EPH = 11; // Ephemeral MT = 12; // Message Transaction @@ -32,6 +32,9 @@ message LegacyMessage { CHAINSTATE = 17; // Chain State HEADERHASHES = 18; // P2P_ACK = 19; // P2P Acknowledgement + MC = 20; // Multi Sig Create Transaction + MS = 21; // Multi Sig Spend Transaction + MV = 22; // Multi Sig Vote Transaction } FuncName func_name = 1; @@ -57,6 +60,9 @@ message LegacyMessage { NodeChainState chainStateData = 19; NodeHeaderHash nodeHeaderHash = 20; P2PAcknowledgement p2pAckData = 21; + Transaction mcData = 22; + Transaction msData = 23; + Transaction mvData = 24; } } diff --git a/src/qrl/protos/qrlmining.proto b/src/qrl/protos/qrlmining.proto index a3952bd2f..ee087fd1c 100644 --- a/src/qrl/protos/qrlmining.proto +++ b/src/qrl/protos/qrlmining.proto @@ -48,6 +48,7 @@ message GetBlockToMineResp { uint64 difficulty = 2; // difficulty that the new block should meet uint64 height = 3; uint32 reserved_offset = 4; + string seed_hash = 5; } message SubmitMinedBlockReq { diff --git a/src/qrl/protos/qrlwallet.proto b/src/qrl/protos/qrlwallet.proto index 8a86c8b77..865a0f252 100644 --- a/src/qrl/protos/qrlwallet.proto +++ b/src/qrl/protos/qrlwallet.proto @@ -62,7 +62,7 @@ service WalletAPI rpc ChangePassphrase(ChangePassphraseReq) returns (ChangePassphraseResp); - rpc GetTransactionsByAddress(TransactionsByAddressReq) returns (TransactionsByAddressResp); + rpc GetMiniTransactionsByAddress(MiniTransactionsByAddressReq) returns (MiniTransactionsByAddressResp); rpc GetTransaction(TransactionReq) returns (TransactionResp); @@ -294,11 +294,13 @@ message ChangePassphraseResp { string error = 2; } -message TransactionsByAddressReq { +message MiniTransactionsByAddressReq { string address = 1; + uint64 item_per_page = 2; + uint64 page_number = 3; } -message TransactionsByAddressResp { +message MiniTransactionsByAddressResp { uint32 code = 1; string error = 2; repeated MiniTransaction mini_transactions = 3; @@ -344,8 +346,9 @@ message OTSReq { message OTSResp { uint32 code = 1; string error = 2; - repeated bytes ots_bitfield = 3; + repeated OTSBitfieldByPage ots_bitfield_by_page = 3; uint64 next_unused_ots_index = 4; + bool unused_ots_index_found = 5; } message HeightReq { diff --git a/src/qrl/services/MiningAPIService.py b/src/qrl/services/MiningAPIService.py index bc8cef814..67c0bab2b 100644 --- a/src/qrl/services/MiningAPIService.py +++ b/src/qrl/services/MiningAPIService.py @@ -7,6 +7,7 @@ from qrl.core import config from qrl.core.qrlnode import QRLNode +from qrl.crypto.Qryptonight import Qryptonight from qrl.generated import qrlmining_pb2 from qrl.generated.qrlmining_pb2_grpc import MiningAPIServicer from qrl.services.grpcHelper import GrpcExceptionWrapper @@ -17,6 +18,7 @@ class MiningAPIService(MiningAPIServicer): def __init__(self, qrlnode: QRLNode): self.qrlnode = qrlnode + self._qn = Qryptonight() @GrpcExceptionWrapper(qrlmining_pb2.GetBlockMiningCompatibleResp, StatusCode.UNKNOWN) def GetBlockMiningCompatible(self, @@ -64,6 +66,8 @@ def GetBlockToMine(self, response.difficulty = blocktemplate_blob_and_difficulty[1] response.height = self.qrlnode.block_height + 1 response.reserved_offset = config.dev.extra_nonce_offset + seed_block_number = self._qn.get_seed_height(response.height) + response.seed_hash = bin2hstr(self.qrlnode.get_block_header_hash_by_number(seed_block_number)) return response diff --git a/src/qrl/services/PublicAPIService.py b/src/qrl/services/PublicAPIService.py index 5b4f26e15..401666e72 100644 --- a/src/qrl/services/PublicAPIService.py +++ b/src/qrl/services/PublicAPIService.py @@ -38,6 +38,10 @@ def GetPeersStat(self, request: qrl_pb2.GetPeersStatReq, context) -> qrl_pb2.Get return peers_stat_resp + @GrpcExceptionWrapper(qrl_pb2.IsSlaveResp) + def IsSlave(self, request: qrl_pb2.IsSlaveReq, context) -> qrl_pb2.IsSlaveResp: + return qrl_pb2.IsSlaveResp(result=self.qrlnode.is_slave(request.master_address, request.slave_pk)) + @GrpcExceptionWrapper(qrl_pb2.GetNodeStateResp) def GetNodeState(self, request: qrl_pb2.GetNodeStateReq, context) -> qrl_pb2.GetNodeStateResp: return qrl_pb2.GetNodeStateResp(info=self.qrlnode.get_node_info()) @@ -103,17 +107,23 @@ def ParseAddress(self, request: qrl_pb2.ParseAddressReq, context) -> qrl_pb2.Par @GrpcExceptionWrapper(qrl_pb2.GetAddressStateResp) def GetAddressState(self, request: qrl_pb2.GetAddressStateReq, context) -> qrl_pb2.GetAddressStateResp: address_state = self.qrlnode.get_address_state(request.address) - if request.exclude_ots_bitfield: - del address_state.pbdata.ots_bitfield[:] - if request.exclude_transaction_hashes: - del address_state.pbdata.transaction_hashes[:] return qrl_pb2.GetAddressStateResp(state=address_state.pbdata) + @GrpcExceptionWrapper(qrl_pb2.GetMultiSigAddressStateResp) + def GetMultiSigAddressState(self, + request: qrl_pb2.GetMultiSigAddressStateReq, + context) -> qrl_pb2.GetMultiSigAddressStateResp: + multi_sig_address_state = self.qrlnode.get_multi_sig_address_state(request.address) + if multi_sig_address_state is None: + return qrl_pb2.GetMultiSigAddressStateResp() + return qrl_pb2.GetMultiSigAddressStateResp(state=multi_sig_address_state.pbdata) + @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) def TransferCoins(self, request: qrl_pb2.TransferCoinsReq, context) -> qrl_pb2.TransferCoinsResp: logger.debug("[PublicAPI] TransferCoins") tx = self.qrlnode.create_send_tx(addrs_to=request.addresses_to, amounts=request.amounts, + message_data=request.message_data, fee=request.fee, xmss_pk=request.xmss_pk, master_addr=request.master_addr) @@ -150,9 +160,55 @@ def PushTransaction(self, request: qrl_pb2.PushTransactionReq, context) -> qrl_p return answer @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) - def GetMessageTxn(self, request: qrl_pb2.TokenTxnReq, context) -> qrl_pb2.TransferCoinsResp: + def GetMultiSigCreateTxn(self, request: qrl_pb2.MultiSigCreateTxnReq, context) -> qrl_pb2.TransferCoinsResp: + logger.debug("[PublicAPI] GetMultiSigCreateTxnReq") + tx = self.qrlnode.create_multi_sig_txn(signatories=request.signatories, + weights=request.weights, + threshold=request.threshold, + fee=request.fee, + xmss_pk=request.xmss_pk, + master_addr=request.master_addr) + + extended_transaction_unsigned = qrl_pb2.TransactionExtended(tx=tx.pbdata, + addr_from=tx.addr_from, + size=tx.size) + return qrl_pb2.TransferCoinsResp(extended_transaction_unsigned=extended_transaction_unsigned) + + @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) + def GetMultiSigSpendTxn(self, request: qrl_pb2.MultiSigSpendTxnReq, context) -> qrl_pb2.TransferCoinsResp: + logger.debug("[PublicAPI] GetMultiSigSpendTxnReq") + tx = self.qrlnode.create_multi_sig_spend_txn(multi_sig_address=request.multi_sig_address, + addrs_to=request.addrs_to, + amounts=request.amounts, + expiry_block_number=request.expiry_block_number, + fee=request.fee, + xmss_pk=request.xmss_pk, + master_addr=request.master_addr) + + extended_transaction_unsigned = qrl_pb2.TransactionExtended(tx=tx.pbdata, + addr_from=tx.addr_from, + size=tx.size) + return qrl_pb2.TransferCoinsResp(extended_transaction_unsigned=extended_transaction_unsigned) + + @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) + def GetMultiSigVoteTxn(self, request: qrl_pb2.MultiSigVoteTxnReq, context) -> qrl_pb2.TransferCoinsResp: + logger.debug("[PublicAPI] GetMultiSigSpendTxnReq") + tx = self.qrlnode.create_multi_sig_vote_txn(shared_key=request.shared_key, + unvote=request.unvote, + fee=request.fee, + xmss_pk=request.xmss_pk, + master_addr=request.master_addr) + + extended_transaction_unsigned = qrl_pb2.TransactionExtended(tx=tx.pbdata, + addr_from=tx.addr_from, + size=tx.size) + return qrl_pb2.TransferCoinsResp(extended_transaction_unsigned=extended_transaction_unsigned) + + @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) + def GetMessageTxn(self, request: qrl_pb2.MessageTxnReq, context) -> qrl_pb2.TransferCoinsResp: logger.debug("[PublicAPI] GetMessageTxn") tx = self.qrlnode.create_message_txn(message_hash=request.message, + addr_to=request.addr_to, fee=request.fee, xmss_pk=request.xmss_pk, master_addr=request.master_addr) @@ -209,6 +265,22 @@ def GetSlaveTxn(self, request: qrl_pb2.SlaveTxnReq, context) -> qrl_pb2.Transfer size=tx.size) return qrl_pb2.TransferCoinsResp(extended_transaction_unsigned=extended_transaction_unsigned) + @GrpcExceptionWrapper(qrl_pb2.TransferCoinsResp) + def GetLatticeTxn(self, request: qrl_pb2.LatticeTxnReq, context) -> qrl_pb2.TransferCoinsResp: + logger.debug("[PublicAPI] GetLatticeTxn") + tx = self.qrlnode.create_lattice_tx(pk1=request.pk1, + pk2=request.pk2, + pk3=request.pk3, + pk4=request.pk4, + fee=request.fee, + xmss_pk=request.xmss_pk, + master_addr=request.master_addr) + + extended_transaction_unsigned = qrl_pb2.TransactionExtended(tx=tx.pbdata, + addr_from=tx.addr_from, + size=tx.size) + return qrl_pb2.TransferCoinsResp(extended_transaction_unsigned=extended_transaction_unsigned) + @GrpcExceptionWrapper(qrl_pb2.GetObjectResp) def GetObject(self, request: qrl_pb2.GetObjectReq, context) -> qrl_pb2.GetObjectResp: logger.debug("[PublicAPI] GetObject") @@ -256,7 +328,6 @@ def GetObject(self, request: qrl_pb2.GetObjectReq, context) -> qrl_pb2.GetObject # NOTE: This is temporary, indexes are accepted for blocks try: block = self.qrlnode.get_block_from_hash(query) - # The condition after or is to avoid a bug, where a block is deserialized by BlockNumberMapping if block is None or (block.block_number == 0 and block.prev_headerhash != config.user.genesis_prev_headerhash): query_str = query.decode() query_index = int(query_str) @@ -332,16 +403,88 @@ def GetLatestData(self, request: qrl_pb2.GetLatestDataReq, context) -> qrl_pb2.G return response + # Obsolete + # @GrpcExceptionWrapper(qrl_pb2.GetTransactionsByAddressResp) + # def GetTransactionsByAddress(self, + # request: qrl_pb2.GetTransactionsByAddressReq, + # context) -> qrl_pb2.GetTransactionsByAddressResp: + # logger.debug("[PublicAPI] GetTransactionsByAddress") + # response = qrl_pb2.GetTransactionsByAddressResp() + # mini_transactions, balance = self.qrlnode.get_transactions_by_address(request.address) + # response.mini_transactions.extend(mini_transactions) + # response.balance = balance + # return response + + @GrpcExceptionWrapper(qrl_pb2.GetMiniTransactionsByAddressResp) + def GetMiniTransactionsByAddress(self, + request: qrl_pb2.GetMiniTransactionsByAddressReq, + context) -> qrl_pb2.GetMiniTransactionsByAddressResp: + logger.debug("[PublicAPI] GetTransactionsByAddress") + return self.qrlnode.get_mini_transactions_by_address(request.address, + request.item_per_page, + request.page_number) + @GrpcExceptionWrapper(qrl_pb2.GetTransactionsByAddressResp) def GetTransactionsByAddress(self, request: qrl_pb2.GetTransactionsByAddressReq, context) -> qrl_pb2.GetTransactionsByAddressResp: logger.debug("[PublicAPI] GetTransactionsByAddress") - response = qrl_pb2.GetTransactionsByAddressResp() - mini_transactions, balance = self.qrlnode.get_transactions_by_address(request.address) - response.mini_transactions.extend(mini_transactions) - response.balance = balance - return response + return self.qrlnode.get_transactions_by_address(request.address, + request.item_per_page, + request.page_number) + + @GrpcExceptionWrapper(qrl_pb2.GetTokensByAddressResp) + def GetTokensByAddress(self, + request: qrl_pb2.GetTransactionsByAddressReq, + context) -> qrl_pb2.GetTokensByAddressResp: + logger.debug("[PublicAPI] GetTokensByAddress") + return self.qrlnode.get_tokens_by_address(request.address, + request.item_per_page, + request.page_number) + + @GrpcExceptionWrapper(qrl_pb2.GetSlavesByAddressResp) + def GetSlavesByAddress(self, + request: qrl_pb2.GetTransactionsByAddressReq, + context) -> qrl_pb2.GetSlavesByAddressResp: + logger.debug("[PublicAPI] GetSlavesByAddress") + return self.qrlnode.get_slaves_by_address(request.address, + request.item_per_page, + request.page_number) + + @GrpcExceptionWrapper(qrl_pb2.GetLatticePKsByAddressResp) + def GetLatticePKsByAddress(self, + request: qrl_pb2.GetTransactionsByAddressReq, + context) -> qrl_pb2.GetLatticePKsByAddressResp: + logger.debug("[PublicAPI] GetLatticePKsByAddress") + return self.qrlnode.get_lattice_pks_by_address(request.address, + request.item_per_page, + request.page_number) + + @GrpcExceptionWrapper(qrl_pb2.GetMultiSigAddressesByAddressResp) + def GetMultiSigAddressesByAddress(self, + request: qrl_pb2.GetTransactionsByAddressReq, + context) -> qrl_pb2.GetMultiSigAddressesByAddressResp: + logger.debug("[PublicAPI] GetMultiSigAddressesByAddress") + return self.qrlnode.get_multi_sig_addresses_by_address(request.address, + request.item_per_page, + request.page_number) + + @GrpcExceptionWrapper(qrl_pb2.GetMultiSigSpendTxsByAddressResp) + def GetMultiSigSpendTxsByAddress(self, + request: qrl_pb2.GetMultiSigSpendTxsByAddressReq, + context) -> qrl_pb2.GetMultiSigSpendTxsByAddressResp: + logger.debug("[PublicAPI] GetMultiSigSpendTxsByAddress") + return self.qrlnode.get_multi_sig_spend_txs_by_address(request.address, + request.item_per_page, + request.page_number, + request.filter_type) + + @GrpcExceptionWrapper(qrl_pb2.GetVoteStatsResp) + def GetVoteStats(self, + request: qrl_pb2.GetVoteStatsReq, + context) -> qrl_pb2.GetVoteStatsResp: + logger.debug("[PublicAPI] GetVoteStats") + return self.qrlnode.get_vote_stats(request.multi_sig_spend_tx_hash) @GrpcExceptionWrapper(qrl_pb2.GetTransactionResp) def GetTransaction(self, request: qrl_pb2.GetTransactionReq, context) -> qrl_pb2.GetTransactionResp: @@ -382,9 +525,14 @@ def GetTotalBalance(self, request: qrl_pb2.GetTotalBalanceReq, context) -> qrl_p @GrpcExceptionWrapper(qrl_pb2.GetOTSResp) def GetOTS(self, request: qrl_pb2.GetOTSReq, context) -> qrl_pb2.GetOTSResp: logger.debug("[PublicAPI] GetOTS") - address_state = self.qrlnode.get_address_state(request.address) - response = qrl_pb2.GetOTSResp(ots_bitfield=address_state.ots_bitfield, - next_unused_ots_index=address_state.get_unused_ots_index()) + ots_bitfield_by_page, next_unused_ots_index, unused_ots_index_found = \ + self.qrlnode.get_ots(request.address, + request.page_from, + request.page_count, + request.unused_ots_index_from) + response = qrl_pb2.GetOTSResp(ots_bitfield_by_page=ots_bitfield_by_page, + next_unused_ots_index=next_unused_ots_index, + unused_ots_index_found=unused_ots_index_found) return response @GrpcExceptionWrapper(qrl_pb2.GetHeightResp) diff --git a/src/qrl/services/WalletAPIService.py b/src/qrl/services/WalletAPIService.py index a27febd21..a002588f1 100644 --- a/src/qrl/services/WalletAPIService.py +++ b/src/qrl/services/WalletAPIService.py @@ -323,13 +323,17 @@ def ChangePassphrase(self, return resp - @GrpcExceptionWrapper(qrlwallet_pb2.TransactionsByAddressResp) - def GetTransactionsByAddress(self, - request: qrlwallet_pb2.TransactionsByAddressReq, - context) -> qrlwallet_pb2.TransactionsByAddressResp: - resp = qrlwallet_pb2.TransactionsByAddressResp() - try: - mini_transactions, balance = self._walletd.get_transactions_by_address(request.address) + @GrpcExceptionWrapper(qrlwallet_pb2.MiniTransactionsByAddressResp) + def GetMiniTransactionsByAddress(self, + request: qrlwallet_pb2.MiniTransactionsByAddressReq, + context) -> qrlwallet_pb2.MiniTransactionsByAddressResp: + resp = qrlwallet_pb2.MiniTransactionsByAddressResp() + try: + mini_transactions, balance = self._walletd.get_mini_transactions_by_address( + request.address, + request.item_per_page, + request.page_number + ) resp.mini_transactions.extend(mini_transactions) resp.balance = balance except Exception as e: @@ -378,11 +382,13 @@ def GetTotalBalance(self, request: qrlwallet_pb2.TotalBalanceReq, context) -> qr @GrpcExceptionWrapper(qrlwallet_pb2.OTSResp) def GetOTS(self, request: qrlwallet_pb2.OTSReq, context) -> qrlwallet_pb2.OTSResp: - resp = qrlwallet_pb2.OTSResp() try: - ots_bitfield, next_unused_ots_index = self._walletd.get_ots(request.address) - resp.ots_bitfield.extend(ots_bitfield) - resp.next_unused_ots_index = next_unused_ots_index + ots_bitfield_by_page, \ + next_unused_ots_index, \ + unused_ots_index_found = self._walletd.get_ots(request.address) + resp = qrlwallet_pb2.OTSResp(ots_bitfield_by_page=ots_bitfield_by_page, + next_unused_ots_index=next_unused_ots_index, + unused_ots_index_found=unused_ots_index_found) except Exception as e: resp.code = 1 resp.error = str(e) diff --git a/src/qrl/tools/generate_genesis.py b/src/qrl/tools/generate_genesis.py index d2b8d45f6..4b9044c60 100644 --- a/src/qrl/tools/generate_genesis.py +++ b/src/qrl/tools/generate_genesis.py @@ -16,6 +16,7 @@ def create_tx(addrs_to, amounts, signing_xmss, nonce): tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, + message_data=None, fee=0, xmss_pk=signing_xmss.pk) tx.sign(signing_xmss) @@ -74,16 +75,19 @@ def main(): transactions = get_migration_transactions(signing_xmss=dist_xmss, filename=filename) - block = Block.create(block_number=0, + block = Block.create(dev_config=config.dev, + block_number=0, prev_headerhash=config.user.genesis_prev_headerhash, prev_timestamp=config.user.genesis_timestamp, transactions=transactions, - miner_address=dist_xmss.address) + miner_address=dist_xmss.address, + seed_height=None, + seed_hash=None) - block.set_nonces(0, 0) + block.set_nonces(config.dev, 0, 0) - block._data.genesis_balance.MergeFrom([qrl_pb2.GenesisBalance(address=config.dev.coinbase_address, - balance=105000000000000000)]) + block._data.genesis_balance.extend([qrl_pb2.GenesisBalance(address=config.dev.coinbase_address, + balance=105000000000000000)]) with open('genesis.yml', 'w') as f: yaml.dump(json.loads(block.to_json()), f) diff --git a/tests/blockchain/MockedBlockchain.py b/tests/blockchain/MockedBlockchain.py index 297e6f80f..8ab1b672c 100644 --- a/tests/blockchain/MockedBlockchain.py +++ b/tests/blockchain/MockedBlockchain.py @@ -51,14 +51,19 @@ def create_block(self, prev_hash, mining_address=None): self.time_mock.return_value = self.time_mock.return_value + time_offset self.ntp_mock.return_value = self.ntp_mock.return_value + time_offset - block_new = Block.create(block_number=block_idx, + block_new = Block.create(dev_config=config.dev, + block_number=block_idx, prev_headerhash=block_prev.headerhash, prev_timestamp=block_prev.timestamp, transactions=transactions, - miner_address=mining_address) + miner_address=mining_address, + seed_height=0, + seed_hash=None) - while not self.qrlnode._chain_manager.validate_mining_nonce(blockheader=block_new.blockheader): - block_new.set_nonces(block_new.mining_nonce + 1, 0) + dev_config = self.qrlnode._chain_manager.get_config_by_block_number(block_new.block_number) + while not self.qrlnode._chain_manager.validate_mining_nonce(blockheader=block_new.blockheader, + dev_config=dev_config): + block_new.set_nonces(config.dev, block_new.mining_nonce + 1, 0) return block_new @@ -81,7 +86,7 @@ def add_new_block(self, mining_address=None): @contextlib.contextmanager def create(num_blocks, mining_address=None): tmp_gen = GenesisBlock() - start_time = tmp_gen.timestamp + config.dev.mining_setpoint_blocktime + start_time = tmp_gen.timestamp + config.dev.block_timing_in_seconds with mock.patch('qrl.core.misc.ntp.getTime') as ntp_mock, \ set_qrl_dir('no_data'), \ State() as state, \ @@ -101,7 +106,7 @@ def create(num_blocks, mining_address=None): chain_manager._difficulty_tracker = Mock() dt = DifficultyTracker() tmp_difficulty = StringToUInt256('2') - tmp_target = dt.get_target(tmp_difficulty) + tmp_target = dt.get_target(tmp_difficulty, config.dev) chain_manager._difficulty_tracker.get = MagicMock(return_value=(tmp_difficulty, tmp_target)) diff --git a/tests/core/p2p/test_p2pTxManagement.py b/tests/core/p2p/test_p2pTxManagement.py index 64f8a4d88..c6e28d729 100644 --- a/tests/core/p2p/test_p2pTxManagement.py +++ b/tests/core/p2p/test_p2pTxManagement.py @@ -74,6 +74,7 @@ def test_notification(self): tx = TransferTransaction.create( addrs_to=[get_some_address()], amounts=[1], + message_data=None, fee=10, xmss_pk=bytes(67)) diff --git a/tests/core/processors/test_TxnProcessor.py b/tests/core/processors/test_TxnProcessor.py index bac378241..0c302842a 100644 --- a/tests/core/processors/test_TxnProcessor.py +++ b/tests/core/processors/test_TxnProcessor.py @@ -8,7 +8,7 @@ from qrl.core.processors.TxnProcessor import TxnProcessor from qrl.core.ChainManager import ChainManager from qrl.core.State import State -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.TransactionPool import TransactionPool from tests.misc.helper import replacement_getTime @@ -26,7 +26,7 @@ def make_tx(txhash=b'hashbrownies', fee=1, autospec=TransferTransaction, PK=b'pu class TestTxnProcessor(TestCase): def setUp(self): m_state = Mock(name='A Mock State', autospec=State) - m_state.get_address_state.return_value = Mock(name='A Mock AddressState', autospec=AddressState) + m_state.get_address_state.return_value = Mock(name='A Mock AddressState', autospec=OptimizedAddressState) self.chain_manager = Mock(autospec=ChainManager) self.chain_manager._state = m_state @@ -67,9 +67,11 @@ def test_txnprocessor_all_valid(self, m_get_slave, m_logger): def test_txnprocessor_tx_validate_fail(self, m_get_slave, m_logger): m_get_slave.return_value = None - self.tx1.validate.return_value = False - - tx_results = [t for t in self.txnprocessor] + self.chain_manager.validate_all.return_value = False + tx_results = [] + for t in self.txnprocessor: + tx_results.append(t) + self.chain_manager.validate_all.return_value = True self.assertEqual([False, True, True, True], tx_results) self.assertEqual(3, self.m_txpool.add_tx_to_pool.call_count) @@ -77,10 +79,14 @@ def test_txnprocessor_tx_validate_fail(self, m_get_slave, m_logger): def test_txnprocessor_tx_validate_extended_fail(self, m_get_slave, m_logger): m_get_slave.return_value = None - self.tx2.validate_extended.return_value = False - self.tx3.validate_extended.return_value = False - - tx_results = [t for t in self.txnprocessor] + self.chain_manager.validate_all.return_value = True + tx_results = [] + for t in self.txnprocessor: + tx_results.append(t) + if len(tx_results) == 3: + self.chain_manager.validate_all.return_value = True + else: + self.chain_manager.validate_all.return_value = False m_logger.info.assert_called() self.assertEqual([True, False, False, True], tx_results) @@ -89,10 +95,13 @@ def test_txnprocessor_tx_validate_extended_fail(self, m_get_slave, m_logger): def test_txnprocessor_tx_validate_transaction_pool_fail(self, m_get_slave, m_logger): m_get_slave.return_value = None - self.tx3.validate_transaction_pool.return_value = False - self.tx4.validate_transaction_pool.return_value = False - - tx_results = [t for t in self.txnprocessor] + tx_results = [] + for t in self.txnprocessor: + tx_results.append(t) + if len(tx_results) < 2: + self.chain_manager.validate_all.return_value = True + else: + self.chain_manager.validate_all.return_value = False m_logger.info.assert_called() self.assertEqual([True, True, False, False], tx_results) @@ -101,11 +110,11 @@ def test_txnprocessor_tx_validate_transaction_pool_fail(self, m_get_slave, m_log def test_txnprocessor_tx_all_failure_modes(self, m_get_slave, m_logger): m_get_slave.return_value = None - self.tx2.validate.return_value = False - self.tx3.validate_extended.return_value = False - self.tx4.validate_transaction_pool.return_value = False - - tx_results = [t for t in self.txnprocessor] + tx_results = [] + self.chain_manager.validate_all.return_value = True + for t in self.txnprocessor: + tx_results.append(t) + self.chain_manager.validate_all.return_value = False m_logger.info.assert_called() self.assertEqual([True, False, False, False], tx_results) diff --git a/tests/core/test_AddressState.py b/tests/core/test_AddressState.py index f51057554..2a95e45df 100644 --- a/tests/core/test_AddressState.py +++ b/tests/core/test_AddressState.py @@ -5,10 +5,12 @@ from unittest import TestCase from mock import Mock, PropertyMock, patch -from tests.misc.helper import get_alice_xmss, get_slave_xmss, get_random_xmss +from tests.misc.helper import get_alice_xmss, get_slave_xmss, get_random_xmss, set_qrl_dir from qrl.core.misc import logger from qrl.core import config +from qrl.core.State import State from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState logger.initialize_default() @@ -90,30 +92,6 @@ def test_get_slave_permission(self): self.addr_state.remove_slave_pks_access_type(slave.pk) self.assertEqual(self.addr_state.get_slave_permission(slave.pk), -1) - def test_lattice_txn(self): - # Add a mock LatticeTransaction to the AddressState. It should show up in addr_state.latticePK_list - m_lattice_txn = Mock(name='mock LatticeTransaction', txhash=b'txhash', dilithium_pk=b'dilithiumPK', - kyber_pk=b'kyberPK') - - self.assertEqual(len(self.addr_state.latticePK_list), 0) - self.addr_state.add_lattice_pk(m_lattice_txn) - self.assertEqual(len(self.addr_state.latticePK_list), 1) - - # Add another different LatticeTransaction. addr_state.latticePK_list should now be longer. - m_lattice_txn_2 = Mock(name='mock LatticeTransaction 2', txhash=b'deadbeef', dilithium_pk=b'dilithiumPK', - kyber_pk=b'kyberPK') - self.addr_state.add_lattice_pk(m_lattice_txn_2) - self.assertEqual(len(self.addr_state.latticePK_list), 2) - - # Remove the second LatticeTransaction. - self.addr_state.remove_lattice_pk(m_lattice_txn_2) - self.assertEqual(len(self.addr_state.latticePK_list), 1) - - # Try to remove the second LatticeTransaction again - # The list should remain the same. - self.addr_state.remove_lattice_pk(m_lattice_txn_2) - self.assertEqual(len(self.addr_state.latticePK_list), 1) - def test_get_default_coinbase(self): # Make sure that Coinbase AddressState gets all the coins supply by default coinbase_addr_state = AddressState.get_default(config.dev.coinbase_address) @@ -269,3 +247,23 @@ def test_get_unused_ots_index2(self): self.assertIsNone(addr_state.get_unused_ots_index()) finally: config.dev.max_ots_tracking_index = old_value + + def test_return_all_addresses(self): + with set_qrl_dir('no_data'): + with State() as state: + self.assertEqual(AddressState.return_all_addresses(state), []) + + def test_put_addresses_state(self): + with set_qrl_dir('no_data'): + with State() as state: + alice_xmss = get_alice_xmss() + alice_state = OptimizedAddressState.get_default(alice_xmss.address) + addresses_state = { + alice_state.address: alice_state, + b'test1': OptimizedAddressState.get_default(b'test1') + } + AddressState.put_addresses_state(state, addresses_state, None) + alice_state2 = OptimizedAddressState.get_optimized_address_state(state, alice_xmss.address) + self.assertEqual(alice_state.serialize(), alice_state2.serialize()) + test_state = OptimizedAddressState.get_optimized_address_state(state, b'test1') + self.assertEqual(test_state.serialize(), OptimizedAddressState.get_default(b'test1').serialize()) diff --git a/tests/core/test_BlockMetadata.py b/tests/core/test_BlockMetadata.py new file mode 100644 index 000000000..e376d1232 --- /dev/null +++ b/tests/core/test_BlockMetadata.py @@ -0,0 +1,50 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from unittest import TestCase + +from tests.misc.helper import get_slave_xmss +from qrl.core.misc import logger +from qrl.core.BlockMetadata import BlockMetadata +from qrl.core.State import State + +from tests.misc.helper import set_qrl_dir, get_alice_xmss + +logger.initialize_default() + +alice = get_alice_xmss() +slave = get_slave_xmss() + + +class TestTokenMetadata(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + + def test_put_block_metadata(self): + block_metadata = BlockMetadata.create() + block_metadata.update_last_headerhashes([b'test1', b'test2'], b'test3') + + BlockMetadata.put_block_metadata(self.state, b'block_headerhash', block_metadata, None) + BlockMetadata.put_block_metadata(self.state, b'block_headerhash2', BlockMetadata.create(), None) + + self.assertEqual(BlockMetadata.get_block_metadata(self.state, b'block_headerhash').to_json(), + block_metadata.to_json()) + + expected_json = b'{\n "blockDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n ' \ + b'"cumulativeDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n}' + + self.assertEqual(BlockMetadata.get_block_metadata(self.state, b'block_headerhash2').to_json(), + expected_json) + + def test_get_block_metadata(self): + self.assertIsNone(BlockMetadata.get_block_metadata(self.state, b'test1')) + BlockMetadata.put_block_metadata(self.state, b'block_headerhash2', BlockMetadata.create(), None) + + tmp_json = BlockMetadata.get_block_metadata(self.state, b'block_headerhash2').to_json() + + expected_json = b'{\n "blockDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n ' \ + b'"cumulativeDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n}' + + self.assertEqual(tmp_json, expected_json) + diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 81da579d1..3b4203370 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -4,7 +4,7 @@ from unittest import TestCase from os import urandom -from mock import Mock, patch, PropertyMock +from mock import Mock, patch, PropertyMock, MagicMock from pyqrllib.pyqrllib import hstr2bin from pyqryptonight.pyqryptonight import StringToUInt256 @@ -12,35 +12,48 @@ from qrl.core import config from qrl.core.misc import logger from qrl.crypto.xmss import XMSS +from qrl.crypto.QRandomX import QRandomX +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.Block import Block +from qrl.core.BlockMetadata import BlockMetadata from qrl.core.ChainManager import ChainManager from qrl.core.DifficultyTracker import DifficultyTracker from qrl.core.GenesisBlock import GenesisBlock +from qrl.core.PaginatedBitfield import PaginatedBitfield from qrl.core.State import State from qrl.core.txs.SlaveTransaction import SlaveTransaction from qrl.core.txs.TransferTransaction import TransferTransaction -from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_default_balance_size, set_qrl_dir, replacement_getTime - -logger.initialize_default() +from qrl.core.txs.LatticeTransaction import LatticeTransaction +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_default_balance_size, set_hard_fork_block_number, \ + set_qrl_dir, replacement_getTime, get_some_address, gen_blocks, get_genesis_with_only_coin_base_txn +# logger.initialize_default() +from qrl.core.misc.set_logger import set_logger_default +#set_logger_default() alice = get_alice_xmss() bob = get_bob_xmss() -def ask_difficulty_tracker(difficulty: str): +def ask_difficulty_tracker(difficulty: str, dev_config: config.DevConfig): dt = DifficultyTracker() tmp_difficulty = StringToUInt256('2') - tmp_target = dt.get_target(tmp_difficulty) + tmp_target = dt.get_target(tmp_difficulty, dev_config) return tmp_difficulty, tmp_target def create_block(block_number, previous_block, miner_address): - return Block.create(block_number=block_number, + return Block.create(dev_config=config.dev, + block_number=block_number, prev_headerhash=previous_block.headerhash, prev_timestamp=previous_block.timestamp, transactions=[], - miner_address=miner_address - ) + miner_address=miner_address, + seed_height=None, + seed_hash=None) def create_m_block(block_number, previous_block, miner_address): @@ -59,211 +72,3848 @@ def create_m_block(block_number, previous_block, miner_address): return mock_block -class TestChainManagerReal(TestCase): - def setUp(self): - with set_qrl_dir('no_data'): - self.state = State() - self.state.get_measurement = Mock(return_value=10000000) +class TestChainManagerReal(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.state.get_measurement = Mock(return_value=10000000) + self._qn = QRandomX() + + try: + del GenesisBlock.instance # Removing Singleton instance + except Exception: # noqa + pass + self.genesis_block = GenesisBlock() + + self.chain_manager = ChainManager(self.state) + self.chain_manager._difficulty_tracker = Mock() + + def test_load(self): + # load() has the following tasks: + # Write Genesis Block into State immediately + # Register block_number <-> blockhash mapping + # Calculate difficulty Metadata for Genesis Block + # Generate AddressStates from Genesis Block balances + # Apply Genesis Block's transactions to the state + self.chain_manager.load(self.genesis_block) + block = Block.get_block(self.state, GenesisBlock().headerhash) + self.assertIsNotNone(block) + + def test_load_twice(self): + self.chain_manager.load(self.genesis_block) + + # If we call load() a second time, it should check to see if we are forked and initiate recovery. + # First we pretend we are not forked. + self.state.get_fork_state = Mock(return_value=None) + self.chain_manager._fork_recovery = Mock(name='mock _fork_recovery()') + self.chain_manager.load(self.genesis_block) + self.chain_manager._fork_recovery.assert_not_called() + + # If we pretend we are forked, it should call _fork_recovery(). + m_fork_state = Mock(autospec=qrlstateinfo_pb2.ForkState, initiator_headerhash=self.genesis_block.headerhash) + self.state.get_fork_state.return_value = m_fork_state + self.chain_manager.load(self.genesis_block) + self.chain_manager._fork_recovery.assert_called_with(self.genesis_block, m_fork_state) + + @patch('qrl.core.misc.ntp.getTime') + def test_simple_add_block(self, time_mock): + # Simply test that adding a block on top of the genesis block works. + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[], + miner_address=alice.address, + seed_hash=None, + seed_height=None) + block_1.set_nonces(config.dev, 201, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_multi_output_transaction_add_block(self, time_mock): + # Test that adding block with a multi-output Transaction updates everybody's balances correctly. + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + + transfer_transaction = TransferTransaction.create(addrs_to=[alice.address, random_xmss.address], + amounts=[40 * int(config.dev.shor_per_quanta), + 59 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob) + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[transfer_transaction], + miner_address=alice.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + bob_addr_state = self.chain_manager.get_address_state(bob.address) + alice_addr_state = self.chain_manager.get_address_state(alice.address) + random_addr_state = self.chain_manager.get_address_state(random_xmss.address) + + self.assertEqual(bob_addr_state.balance, 0) + self.assertEqual(alice_addr_state.balance, + 140 * int(config.dev.shor_per_quanta) + block_1.block_reward + block_1.fee_reward) + self.assertEqual(random_addr_state.balance, 159 * int(config.dev.shor_per_quanta)) + + @patch("qrl.core.DifficultyTracker.DifficultyTracker.get") + def test_add_block(self, mock_difficulty_tracker_get): + """ + Add block_1 on genesis block (that registers Bob as Alice's slave) + Add a competing fork_block on genesis block (without the SlaveTransaction) + Add block_2 on fork_block (without the SlaveTransaction) + Bob should be free from slavery now. + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + # Add block_1 on genesis block. + slave_tx = SlaveTransaction.create(slave_pks=[bob.pk], + access_types=[0], + fee=0, + xmss_pk=alice.pk) + slave_tx.sign(alice) + slave_tx._data.nonce = 1 + self.assertTrue(slave_tx.validate()) + with patch('qrl.core.misc.ntp.getTime') as time_mock: + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[slave_tx], + miner_address=alice.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 2, 0) + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + # Yes, Bob is Alice's slave. + alice_state = self.chain_manager.get_optimized_address_state(alice.address) + self.assertEqual(alice_state.slaves_count(), 1) + bob_access_type = self.chain_manager.get_slave_pk_access_type(alice.address, bob.pk) + self.assertEqual(bob_access_type.access_type, 0) + + # Add fork block on genesis block + with patch('qrl.core.misc.ntp.getTime') as time_mock: + time_mock.return_value = 1715270948 # Very high to get an easy difficulty + fork_block = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[], + miner_address=bob.address, + seed_height=None, + seed_hash=None) + + fork_block.set_nonces(config.dev, 4, 0) + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, fork_block.blockheader, False): + # fork_block.set_nonces(fork_block.mining_nonce + 1) + # print(fork_block.mining_nonce) + self.assertTrue(fork_block.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(fork_block) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + fork_block = Block.get_block(self.state, fork_block.headerhash) + self.assertIsNotNone(fork_block) + + # Add block_2 on fork_block. + with patch('qrl.core.misc.ntp.getTime') as time_mock: + time_mock.return_value = 1815270948 # Very high to get an easy difficulty + block_2 = fork_block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=fork_block.headerhash, + prev_timestamp=fork_block.timestamp, + transactions=[], + miner_address=bob.address, + seed_height=None, + seed_hash=None) + + block_2.set_nonces(config.dev, 1, 0) + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(state, block_2.blockheader, False): + # block_2.set_nonces(block_2.mining_nonce + 1, 0) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block.block_number, block_2.block_number) + self.assertEqual(self.chain_manager.last_block.serialize(), block_2.serialize()) + + # Now we are on the forked chain, Bob is no longer Alice's slave. + alice_state = self.chain_manager.get_address_state(alice.address) + self.assertFalse(str(bob.pk) in alice_state.slave_pks_access_type) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block2(self, time_mock): + """ + Features Tested + - Multi Sig Create, Spend & Vote Txn + - Vote on a multi sig spend + + Expectation + - Multi Sig Spend transaction must be executed as it has received sufficient vote and reached to threshold. + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 1) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[transfer_transaction], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_2.blockheader, False): + # block_2.set_nonces(block_2.mining_nonce + 1) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_2) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 2) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[multi_sig_spend], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_3.blockheader, config.dev, False): + # block_3.set_nonces(config.dev, block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_3) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(4)) + block_4 = Block.create(dev_config=config.dev, + block_number=4, + prev_headerhash=block_3.headerhash, + prev_timestamp=block_3.timestamp, + transactions=[multi_sig_vote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_4.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_4.blockheader, config.dev, False): + # block_4.set_nonces(config.dev, block_4.mining_nonce + 1) + # print(block_4.mining_nonce) + self.assertTrue(block_4.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_4) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_4) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(5)) + block_5 = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=block_4.headerhash, + prev_timestamp=block_4.timestamp, + transactions=[multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_5.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_5.blockheader, config.dev, False): + # block_5.set_nonces(config.dev, block_5.mining_nonce + 1) + # print(block_5.mining_nonce) + self.assertTrue(block_5.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_5) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_5) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward + + block_5.block_reward + block_5.fee_reward + + 5) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + 10) + self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta) - 15) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block3(self, time_mock): + """ + Features Tested + - Multi Sig Create, Spend & Vote Txn + - Vote on an expired multi sig spend + + Expectation + - Block including the vote for multi sig vote txn must be rejected due to failure in validation. + - Multi Sig Spend transaction must not have executed as it expired without sufficient vote reaching threshold. + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=4, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 1) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[transfer_transaction], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_2.blockheader, False): + # block_2.set_nonces(block_2.mining_nonce + 1) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_2) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 2) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[multi_sig_spend], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_3.blockheader, False): + # block_3.set_nonces(block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_3) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(4)) + block_4 = Block.create(dev_config=config.dev, + block_number=4, + prev_headerhash=block_3.headerhash, + prev_timestamp=block_3.timestamp, + transactions=[multi_sig_vote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_4.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_4.blockheader, False): + # block_4.set_nonces(block_4.mining_nonce + 1) + # print(block_4.mining_nonce) + self.assertTrue(block_4.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_4) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_4) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(5)) + block_5 = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=block_4.headerhash, + prev_timestamp=block_4.timestamp, + transactions=[multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_5.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not self.chain_manager.validate_mining_nonce(block_5.blockheader, False): + # block_5.set_nonces(block_5.mining_nonce + 1) + # print(block_5.mining_nonce) + self.assertTrue(block_5.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_5) + + # Block rejected as is includes vote for the expired multi sig spend txn. + self.assertFalse(result) + self.assertEqual(self.chain_manager.last_block, block_4) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block4(self, time_mock): + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + lattice_pk = LatticeTransaction.create(pk1=b'alice_pk1', + pk2=b'alice_pk2', + pk3=b'alice_pk3', + pk4=b'alice_pk4', + fee=5, + xmss_pk=alice_xmss.pk) + lattice_pk.sign(alice_xmss) + lattice_pk.pbdata.nonce = 1 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[lattice_pk], + miner_address=bob_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 1, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) - 5) + self.assertEqual(alice_addr_state.lattice_pk_count(), 1) + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + 5) + + lattice_pk2 = LatticeTransaction.create(pk1=b'alice_pk11', + pk2=b'alice_pk12', + pk3=b'alice_pk13', + pk4=b'alice_pk14', + fee=5, + xmss_pk=alice_xmss.pk) + lattice_pk2.sign(alice_xmss) + lattice_pk2.pbdata.nonce = 2 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[lattice_pk2], + miner_address=bob_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 10, 0) + + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_2) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block5(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn, multisig spend txn + & multi sig vote are added into same block + + Expectation + - Block must have been added + - multi_sig_spend txn must not be executed as threshold has not reached + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, + multi_sig_spend, multi_sig_vote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertFalse(vote_stats.executed) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block6(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn, multisig spend txn, + two multisig vote txns are added into same block. + - Behavior of Rollback + - Transaction storage in State + - OTS index usage before and after rollback + + Expectation + - Block must have been added + - multi_sig_spend txn must be executed as threshold has reached + - Rollback must happen successfully + - Used OTS indexes after rollback must be found as unused + - Transaction must be found in State before roll back + - Transaction must not be found in State after roll back + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend, + multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + multi_sig_spend.amounts[1]) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + multi_sig_spend.amounts[0]) + self.assertEqual(multi_sig_address_state.balance, + 40 * int(config.dev.shor_per_quanta) - multi_sig_spend.total_amount) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertIsNotNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + # Rollback state to genesis block + self.chain_manager._rollback(self.genesis_block.headerhash) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertIsNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state.nonce, 0) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state, None) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertFalse(result) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block7(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn, multisig spend txn, + three multisig vote txns are added into same block. + First, MultiSig vote txn signed by Alice to add vote + Second, MultiSig vote txn signed by Bob to add vote + Third, MultiSig vote txn signed by Alice to unvote + - Behavior of Rollback + - Transaction storage in State + - OTS index usage before and after rollback + + Expectation + - Block must have been added. + - The order of transaction in block is Vote1, Vote3, Vote2, so threshold is not reached. + - multi_sig_spend transaction must not execute. + - Rollback must happen successfully + - Used OTS indexes after rollback must be found as unused + - Transaction must be found in State before roll back + - Transaction must not be found in State after roll back + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=True, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 4 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend, + multi_sig_vote1, multi_sig_vote3, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state.balance, + 40 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertIsNotNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + multi_sig_vote3.set_prev_tx_hash(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote3.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertTrue(result) + + # Rollback state to genesis block + self.chain_manager._rollback(self.genesis_block.headerhash) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertIsNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state.nonce, 0) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state, None) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertFalse(result) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block8(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn, multisig spend txn, + three multisig vote txns are added into same block. + First, MultiSig vote txn signed by Alice to add vote + Second, MultiSig vote txn signed by Bob to add vote + Third, MultiSig vote txn signed by Alice to unvote + + Expectation + - Block must not be added. + - The order of transaction in block is Vote1, Vote2, Vote3 so threshold is reached, + thus Multi Sig Vote3 becomes invalid as unvote txn found after threshold reached. + so the block becomes invalid and rejected. + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=True, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 4 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend, + multi_sig_vote1, multi_sig_vote2, multi_sig_vote3], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertFalse(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertIsNone(vote_stats) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta)) + self.assertIsNone(multi_sig_address_state) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block9(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn, multisig spend txn, + two multisig vote txns are added into same block. + + Expectation + - Block must not be added, as it includes duplicate multi sig vote txn. + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote2.sign(alice_xmss) + multi_sig_vote2.pbdata.nonce = 4 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend, + multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertFalse(result) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block10(self, time_mock): + """ + Features Tested + - Behavior of Block validation when two multi sig spend transactions are made, such that + the last multi sig spend transaction gets enough vote but multi sig address, doesn't + have enough fund for the last multi sig spend transaction. + - Behavior of Rollback + - Transaction storage in State + - OTS index usage before and after rollback + + Expectation + - Both blocks must be added. + - multi_sig_spend1 must be executed at block 1 + - multi_sig_spend2 must have received enough vote at block 2, + but must not execute due to lack of funds. + - Rollback must happen successfully + - Used OTS indexes after rollback must be found as unused + - Transaction must be found in State before roll back + - Transaction must not be found in State after roll back + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend1 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[20, 15], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend1.sign(alice_xmss) + multi_sig_spend1.pbdata.nonce = 2 + + multi_sig_spend2 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 10], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend2.sign(alice_xmss) + multi_sig_spend2.pbdata.nonce = 3 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 4 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 5 + + multi_sig_vote4 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote4.sign(bob_xmss) + multi_sig_vote4.pbdata.nonce = 3 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend1, + multi_sig_spend2, multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction.fee + - transfer_transaction.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction.total_amount + - multi_sig_spend1.total_amount) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[multi_sig_vote3, multi_sig_vote4], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction.fee + - transfer_transaction.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction.total_amount + - multi_sig_spend1.total_amount) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNotNone(vote_stats) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNotNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote3.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote4.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertTrue(result) + + # Rollback state to genesis block + self.chain_manager._rollback(self.genesis_block.headerhash) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNone(vote_stats) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state.nonce, 0) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(multi_sig_address_state, None) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertFalse(result) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block11(self, time_mock): + """ + Features Tested + - Behavior of Block validation when two multi sig spend transactions are made, such that + the last multi sig spend transaction gets enough vote but multi sig address, doesn't + have enough fund for the last multi sig spend transaction. + Then the transaction in block 3 sends more funds to Multi Sig Address, making sufficient funds. + Although to execute the multi_sig_spend2 txn, it needs to be re checked by executing some + vote txn. So in block 4, a multi_sig_vote txn is added to unvote it. + In block 5, a multi_sig_vote txn is added to add vote again, reaching threshold. + - Behavior of Rollback + - Transaction storage in State + - OTS index usage before and after rollback + + Expectation + - Both blocks must be added. + - multi_sig_spend1 must be executed at block 1 + - multi_sig_spend2 must have received enough vote at block 2, + but must not execute due to lack of funds. + - In block 5, when re voted there will be enough funds in multi sig address, so the + multi_sig_spend2 txn must have been executed. + - Rollback must happen successfully + - Used OTS indexes after rollback must be found as unused + - Transaction must be found in State before roll back + - Transaction must not be found in State after roll back + + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction1 = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction1._data.nonce = 1 + transfer_transaction1.sign(bob_xmss) + self.assertTrue(transfer_transaction1.validate_or_raise(True)) + + multi_sig_spend1 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[20, 15], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend1.sign(alice_xmss) + multi_sig_spend1.pbdata.nonce = 2 + + multi_sig_spend2 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 10], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend2.sign(alice_xmss) + multi_sig_spend2.pbdata.nonce = 3 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 4 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 5 + + multi_sig_vote4 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote4.sign(bob_xmss) + multi_sig_vote4.pbdata.nonce = 3 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction1, multi_sig_spend1, + multi_sig_spend2, multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + - multi_sig_spend1.total_amount) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[multi_sig_vote3, multi_sig_vote4], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + - multi_sig_spend1.total_amount) + + transfer_transaction2 = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction2._data.nonce = 4 + transfer_transaction2.sign(bob_xmss) + self.assertTrue(transfer_transaction2.validate_or_raise(True)) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[transfer_transaction2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_3.blockheader, config.dev, False): + # block_3.set_nonces(config.dev, block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount) + + multi_sig_vote5 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=True, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote5.sign(bob_xmss) + multi_sig_vote5.pbdata.nonce = 5 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(4)) + block_4 = Block.create(dev_config=config.dev, + block_number=4, + prev_headerhash=block_3.headerhash, + prev_timestamp=block_3.timestamp, + transactions=[multi_sig_vote5], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_4.set_nonces(config.dev, 4, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_4.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_4) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount + - multi_sig_vote5.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount) + + multi_sig_vote6 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote6.sign(bob_xmss) + multi_sig_vote6.pbdata.nonce = 6 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(5)) + block_5 = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=block_4.headerhash, + prev_timestamp=block_4.timestamp, + transactions=[multi_sig_vote6], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_5.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_5.blockheader, config.dev, False): + # block_5.set_nonces(config.dev, block_5.mining_nonce + 1) + # print(block_5.mining_nonce) + self.assertTrue(block_5.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_5) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount + - multi_sig_vote5.fee + - multi_sig_vote6.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + multi_sig_spend2.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward + + block_5.fee_reward + + block_5.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0] + + multi_sig_spend2.amounts[1]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount + - multi_sig_spend2.total_amount) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNotNone(vote_stats) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNotNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote3.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote4.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote5.txhash) + multi_sig_vote5.set_prev_tx_hash(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote5.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote6.txhash) + multi_sig_vote6.set_prev_tx_hash(multi_sig_vote5.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote6.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction2.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote5.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote6.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction2.ots_key) + self.assertTrue(result) + + # Rollback state to genesis block + self.assertTrue(self.chain_manager._rollback(self.genesis_block.headerhash)) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNone(vote_stats) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNone(vote_stats) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote5.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote6.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction1.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction2.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state.nonce, 0) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + + self.assertEqual(multi_sig_address_state, None) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote5.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote6.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction1.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction2.ots_key) + self.assertFalse(result) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block12(self, time_mock): + """ + Features Tested + - Behavior of Block validation after expiry. + + Expectation + - Block 1 must be added, as it includes valid transactions. + - Block 2 must be added. + - Block 3 must fail as it includes vote for an expired multi_sig_spend transaction. + - multi_sig_spend txn must not be executed as threshold has not reached. + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=2, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_unvote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_unvote1.sign(alice_xmss) + multi_sig_unvote1.pbdata.nonce = 4 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, + multi_sig_spend, multi_sig_vote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 1, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 1, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_2.blockheader, config.dev, False): + # block_2.set_nonces(config.dev, block_2.mining_nonce + 1) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + self.assertTrue(result) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + # Trying to add block_3 with an vote txn for an expired multi_sig_spend txn to meet threshold + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_3.blockheader, config.dev, False): + # block_3.set_nonces(config.dev, block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + self.assertFalse(result) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + # Trying to add block_3 with an unvote txn for an expired multi_sig_spend txn + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[multi_sig_unvote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 1, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_3.blockheader, config.dev, False): + # block_3.set_nonces(config.dev, block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + self.assertFalse(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend.txhash) + self.assertFalse(vote_stats.executed) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block13(self, time_mock): + """ + Features Tested + - Slave transactions + - Transfer Transaction made by slave address + - Rollback of slave transaction + + Expectation + - block_1 must be accepted as all transactions are valid + - block_2 must be rejected as the slave transaction includes existing slave address + associated with master address + - After rollback, slaves meta data containing access type, must not be found in the state + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed1 = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + extended_seed2 = "01040097cbf736e725a5da3ccbdb78688f9261d54a9d752108f" \ + "c331f51e46aca23757d42d49f9aeea3ba2818ed378e755b6c17" + random_xmss1 = XMSS.from_extended_seed(hstr2bin(extended_seed1)) + random_xmss2 = XMSS.from_extended_seed(hstr2bin(extended_seed2)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + slave_txn1 = SlaveTransaction.create(slave_pks=[random_xmss1.pk, random_xmss2.pk], + access_types=[0, 0], + fee=5, + xmss_pk=alice_xmss.pk) + slave_txn1.sign(alice_xmss) + slave_txn1.pbdata.nonce = 1 + + transfer_txn = TransferTransaction.create(addrs_to=[random_xmss1.address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=random_xmss2.pk, + master_addr=alice_xmss.address) + transfer_txn.sign(random_xmss2) + transfer_txn.pbdata.nonce = 1 + + slave_txn2 = SlaveTransaction.create(slave_pks=[random_xmss1.pk], + access_types=[0], + fee=5, + xmss_pk=alice_xmss.pk) + slave_txn2.sign(alice_xmss) + slave_txn2.pbdata.nonce = 2 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[slave_txn1, transfer_txn], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state1 = self.chain_manager.get_optimized_address_state(random_xmss1.address) + random_addr_state2 = self.chain_manager.get_optimized_address_state(random_xmss2.address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + - slave_txn1.fee + - transfer_txn.fee + - transfer_txn.total_amount) + self.assertEqual(random_addr_state1.balance, + 100 * int(config.dev.shor_per_quanta) + + transfer_txn.amounts[0]) + self.assertEqual(random_addr_state2.balance, 100 * int(config.dev.shor_per_quanta)) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss1.pk) + self.assertEqual(slave_metadata.access_type, 0) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss2.pk) + self.assertEqual(slave_metadata.access_type, 0) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 1) + self.assertEqual(random_addr_state1.nonce, 0) + self.assertEqual(random_addr_state2.nonce, 1) + + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[slave_txn2], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_2.set_nonces(config.dev, 1, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_2.blockheader, config.dev, False): + # block_2.set_nonces(config.dev, block_2.mining_nonce + 1) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertFalse(result) + + self.assertTrue(self.chain_manager._rollback(self.genesis_block.headerhash)) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state1 = self.chain_manager.get_optimized_address_state(random_xmss1.address) + random_addr_state2 = self.chain_manager.get_optimized_address_state(random_xmss2.address) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state1.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state2.balance, 100 * int(config.dev.shor_per_quanta)) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss1.pk) + self.assertIsNone(slave_metadata) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss2.pk) + self.assertIsNone(slave_metadata) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state1.nonce, 0) + self.assertEqual(random_addr_state2.nonce, 0) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block14(self, time_mock): + """ + Features Tested + - Transfer Transaction made by slave address which is not associated by the master address + + Expectation + - block_1 must be rejected as slave is not associated with master address + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed1 = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + extended_seed2 = "01040097cbf736e725a5da3ccbdb78688f9261d54a9d752108f" \ + "c331f51e46aca23757d42d49f9aeea3ba2818ed378e755b6c17" + random_xmss1 = XMSS.from_extended_seed(hstr2bin(extended_seed1)) + random_xmss2 = XMSS.from_extended_seed(hstr2bin(extended_seed2)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + + transfer_txn = TransferTransaction.create(addrs_to=[random_xmss1.address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=random_xmss2.pk, + master_addr=alice_xmss.address) + transfer_txn.sign(random_xmss2) + transfer_txn.pbdata.nonce = 1 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[transfer_txn], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertFalse(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertFalse(result) + self.assertEqual(self.chain_manager.last_block, self.genesis_block) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state1 = self.chain_manager.get_optimized_address_state(random_xmss1.address) + random_addr_state2 = self.chain_manager.get_optimized_address_state(random_xmss2.address) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state1.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state2.balance, 100 * int(config.dev.shor_per_quanta)) + + self.assertEqual(bob_addr_state.nonce, 0) + self.assertEqual(alice_addr_state.nonce, 0) + self.assertEqual(random_addr_state1.nonce, 0) + self.assertEqual(random_addr_state2.nonce, 0) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss1.pk) + self.assertIsNone(slave_metadata) + + slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss2.pk) + self.assertIsNone(slave_metadata) + + @set_default_balance_size() + @patch('qrl.core.misc.ntp.getTime') + def test_add_block13(self, time_mock): + """ + Features Tested + - Behavior of Slave txn when duplicate slave transaction are added into a single block + + Expectation + - block_1 must be rejected as the slave transaction includes existing slave address + associated with master address + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed1 = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + extended_seed2 = "01040097cbf736e725a5da3ccbdb78688f9261d54a9d752108f" \ + "c331f51e46aca23757d42d49f9aeea3ba2818ed378e755b6c17" + random_xmss1 = XMSS.from_extended_seed(hstr2bin(extended_seed1)) + random_xmss2 = XMSS.from_extended_seed(hstr2bin(extended_seed2)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + slave_txn1 = SlaveTransaction.create(slave_pks=[random_xmss1.pk, random_xmss2.pk], + access_types=[0, 0], + fee=5, + xmss_pk=alice_xmss.pk) + slave_txn1.sign(alice_xmss) + slave_txn1.pbdata.nonce = 1 + + slave_txn2 = SlaveTransaction.create(slave_pks=[random_xmss1.pk], + access_types=[0], + fee=5, + xmss_pk=alice_xmss.pk) + slave_txn2.sign(alice_xmss) + slave_txn2.pbdata.nonce = 2 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[slave_txn1, slave_txn2], + miner_address=alice_xmss.address, + seed_height=None, + seed_hash=None) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertFalse(result) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_rollback(self, time_mock): + # Test that adding block for multi sig spend with multi sig vote txn + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 129, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): + # block_1.set_nonces(block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_1) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 1) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[transfer_transaction], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not PoWValidator().validate_mining_nonce(self.state, block_2.blockheader, False): + # block_2.set_nonces(block_2.mining_nonce + 1) + # print(block_2.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_2) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 2) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[multi_sig_spend], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_3.blockheader, config.dev, False): + # block_3.set_nonces(config.dev, block_3.mining_nonce + 1) + # print(block_3.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_3) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(4)) + block_4 = Block.create(dev_config=config.dev, + block_number=4, + prev_headerhash=block_3.headerhash, + prev_timestamp=block_3.timestamp, + transactions=[multi_sig_vote1], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_4.set_nonces(config.dev, 4, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_4.blockheader, config.dev, False): + # block_4.set_nonces(config.dev, block_4.mining_nonce + 1) + # print(block_4.mining_nonce) + self.assertTrue(block_4.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_4) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_4) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(5)) + block_5 = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=block_4.headerhash, + prev_timestamp=block_4.timestamp, + transactions=[multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_5.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not self.chain_manager.validate_mining_nonce(block_5.blockheader, False): + # block_5.set_nonces(block_5.mining_nonce + 1) + # print(block_5.mining_nonce) + self.assertTrue(block_5.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_5) + + self.assertTrue(result) + self.assertEqual(self.chain_manager.last_block, block_5) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward + + block_5.block_reward + block_5.fee_reward + + 5) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + 10) + self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta) - 15) + self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) + + self.chain_manager._rollback(self.genesis_block.headerhash) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + + self.assertIsNone(MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, multi_sig_address)) + + self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(alice_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_rollback2(self, time_mock): + """ + Features Tested + - Behavior of Block validation when two multi sig spend transactions are made, such that + the last multi sig spend transaction gets enough vote but multi sig address, doesn't + have enough fund for the last multi sig spend transaction. + - Behavior of Rollback for block number 2 + - Transaction storage in State + - OTS index usage before and after rollback + + Expectation + - Both blocks must be added. + - multi_sig_spend1 must be executed at block 1 + - multi_sig_spend2 must have received enough vote at block 2, + but must not execute due to lack of funds. + - Rollback must happen successfully + - multi_sig_vote3 and multi_sig_vote4 must be found in the state before rollback + - multi_sig_vote3 and multi_sig_vote4 must be deleted from the state after the rollback + - Used OTS indexes for multi_sig_vote3 and multi_sig_vote4 after rollback must be found as unused + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend1 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[20, 15], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend1.sign(alice_xmss) + multi_sig_spend1.pbdata.nonce = 2 + + multi_sig_spend2 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 10], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend2.sign(alice_xmss) + multi_sig_spend2.pbdata.nonce = 3 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 4 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 5 + + multi_sig_vote4 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote4.sign(bob_xmss) + multi_sig_vote4.pbdata.nonce = 3 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend1, + multi_sig_spend2, multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 2, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction.fee + - transfer_transaction.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction.total_amount + - multi_sig_spend1.total_amount) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[multi_sig_vote3, multi_sig_vote4], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction.fee + - transfer_transaction.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction.total_amount + - multi_sig_spend1.total_amount) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNotNone(vote_stats) + self.assertTrue(vote_stats.executed) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNotNone(vote_stats) + self.assertFalse(vote_stats.executed) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote3.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote4.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertTrue(result) - del GenesisBlock.instance # Removing Singleton instance - self.genesis_block = GenesisBlock() + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertTrue(result) - self.chain_manager = ChainManager(self.state) - self.chain_manager._difficulty_tracker = Mock() + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) - def test_load(self): - # load() has the following tasks: - # Write Genesis Block into State immediately - # Register block_number <-> blockhash mapping - # Calculate difficulty Metadata for Genesis Block - # Generate AddressStates from Genesis Block balances - # Apply Genesis Block's transactions to the state - self.chain_manager.load(self.genesis_block) - block = self.state.get_block(GenesisBlock().headerhash) - self.assertIsNotNone(block) + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) - def test_load_twice(self): - self.chain_manager.load(self.genesis_block) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertTrue(result) - # If we call load() a second time, it should check to see if we are forked and initiate recovery. - # First we pretend we are not forked. - self.state.get_fork_state = Mock(return_value=None) - self.chain_manager._fork_recovery = Mock(name='mock _fork_recovery()') - self.chain_manager.load(self.genesis_block) - self.chain_manager._fork_recovery.assert_not_called() + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertTrue(result) - # If we pretend we are forked, it should call _fork_recovery(). - m_fork_state = Mock(autospec=qrlstateinfo_pb2.ForkState, initiator_headerhash=self.genesis_block.headerhash) - self.state.get_fork_state.return_value = m_fork_state - self.chain_manager.load(self.genesis_block) - self.chain_manager._fork_recovery.assert_called_with(self.genesis_block, m_fork_state) + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertTrue(result) - @patch('qrl.core.misc.ntp.getTime') - def test_simple_add_block(self, time_mock): - # Simply test that adding a block on top of the genesis block works. - self.chain_manager._difficulty_tracker.get.return_value = ask_difficulty_tracker('2') - self.chain_manager.load(self.genesis_block) + # Rollback state to block number 1 + self.chain_manager._rollback(block_1.headerhash) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertIsNone(tx_meta_data) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) - time_mock.return_value = 1615270948 # Very high to get an easy difficulty + self.assertEqual(bob_addr_state.nonce, 2) + self.assertEqual(alice_addr_state.nonce, 4) + self.assertEqual(random_addr_state.nonce, 0) - block_1 = Block.create(block_number=1, - prev_headerhash=self.genesis_block.headerhash, - prev_timestamp=self.genesis_block.timestamp, - transactions=[], - miner_address=alice.address) - block_1.set_nonces(201, 0) + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction.total_amount + - transfer_transaction.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) - # Uncomment only to determine the correct mining_nonce of above blocks - # from qrl.core.PoWValidator import PoWValidator - # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): - # block_1.set_nonces(block_1.mining_nonce + 1) - # print(block_1.mining_nonce) - self.assertTrue(block_1.validate(self.chain_manager, {})) - result = self.chain_manager.add_block(block_1) + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) - self.assertTrue(result) - self.assertEqual(self.chain_manager.last_block, block_1) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertFalse(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction.ots_key) + self.assertTrue(result) @set_default_balance_size() + @set_hard_fork_block_number() @patch('qrl.core.misc.ntp.getTime') - def test_multi_output_transaction_add_block(self, time_mock): - # Test that adding block with a multi-output Transaction updates everybody's balances correctly. - self.chain_manager.load(self.genesis_block) + def test_roll_back3(self, time_mock): + """ + Features Tested + - Behavior of Block validation when two multi sig spend transactions are made, such that + the last multi sig spend transaction gets enough vote but multi sig address, doesn't + have enough fund for the last multi sig spend transaction. + Then the transaction in block 3 sends more funds to Multi Sig Address, making sufficient funds. + Although to execute the multi_sig_spend2 txn, it needs to be re checked by executing some + vote txn. So in block 4, a multi_sig_vote txn is added to unvote it. + In block 5, a multi_sig_vote txn is added to add vote again, reaching threshold. + - Behavior of Rollback + - Transaction storage in State + - OTS index usage before and after rollback - extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ - "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" - random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) - - transfer_transaction = TransferTransaction.create(addrs_to=[alice.address, random_xmss.address], - amounts=[40 * int(config.dev.shor_per_quanta), - 59 * int(config.dev.shor_per_quanta)], - fee=1 * config.dev.shor_per_quanta, - xmss_pk=bob.pk) - transfer_transaction._data.nonce = 1 - transfer_transaction.sign(bob) - - time_mock.return_value = 1615270948 # Very high to get an easy difficulty - - block_1 = Block.create(block_number=1, - prev_headerhash=self.genesis_block.headerhash, - prev_timestamp=self.genesis_block.timestamp, - transactions=[transfer_transaction], - miner_address=alice.address) - block_1.set_nonces(129, 0) - - # Uncomment only to determine the correct mining_nonce of above blocks - # from qrl.core.PoWValidator import PoWValidator - # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): - # block_1.set_nonces(block_1.mining_nonce + 1) - # print(block_1.mining_nonce) - self.assertTrue(block_1.validate(self.chain_manager, {})) - result = self.chain_manager.add_block(block_1) - - self.assertTrue(result) - self.assertEqual(self.chain_manager.last_block, block_1) - - bob_addr_state = self.state.get_address_state(bob.address) - alice_addr_state = self.state.get_address_state(alice.address) - random_addr_state = self.state.get_address_state(random_xmss.address) - - self.assertEqual(bob_addr_state.balance, 0) - self.assertEqual(alice_addr_state.balance, - 140 * int(config.dev.shor_per_quanta) + block_1.block_reward + block_1.fee_reward) - self.assertEqual(random_addr_state.balance, 159 * int(config.dev.shor_per_quanta)) + Expectation + - Both blocks must be added. + - multi_sig_spend1 must be executed at block 1 + - multi_sig_spend2 must have received enough vote at block 2, + but must not execute due to lack of funds. + - In block 5, when re voted there will be enough funds in multi sig address, so the + multi_sig_spend2 txn must have been executed. + - Rollback must happen successfully + - Used OTS indexes after rollback must be found as unused + - Transaction must be found in State before roll back + - Transaction must not be found in State after roll back - @patch("qrl.core.DifficultyTracker.DifficultyTracker.get") - def test_add_block(self, mock_difficulty_tracker_get): - """ - Add block_1 on genesis block (that registers Bob as Alice's slave) - Add a competing fork_block on genesis block (without the SlaveTransaction) - Add block_2 on fork_block (without the SlaveTransaction) - Bob should be free from slavery now. + + :param time_mock: + :return: """ - mock_difficulty_tracker_get.return_value = ask_difficulty_tracker('2') - self.chain_manager.load(self.genesis_block) + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=8, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction1 = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction1._data.nonce = 1 + transfer_transaction1.sign(bob_xmss) + self.assertTrue(transfer_transaction1.validate_or_raise(True)) + + multi_sig_spend1 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[20, 15], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend1.sign(alice_xmss) + multi_sig_spend1.pbdata.nonce = 2 + + multi_sig_spend2 = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 10], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend2.sign(alice_xmss) + multi_sig_spend2.pbdata.nonce = 3 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 4 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend1.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + + multi_sig_vote3 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote3.sign(alice_xmss) + multi_sig_vote3.pbdata.nonce = 5 + + multi_sig_vote4 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote4.sign(bob_xmss) + multi_sig_vote4.pbdata.nonce = 3 - # Add block_1 on genesis block. - slave_tx = SlaveTransaction.create(slave_pks=[bob.pk], - access_types=[0], - fee=0, - xmss_pk=alice.pk) - slave_tx.sign(alice) - slave_tx._data.nonce = 1 - self.assertTrue(slave_tx.validate()) - with patch('qrl.core.misc.ntp.getTime') as time_mock: time_mock.return_value = 1615270948 # Very high to get an easy difficulty - block_1 = Block.create(block_number=1, + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, prev_headerhash=self.genesis_block.headerhash, prev_timestamp=self.genesis_block.timestamp, - transactions=[slave_tx], - miner_address=alice.address) - block_1.set_nonces(2, 0) + transactions=[multi_sig_create, transfer_transaction1, multi_sig_spend1, + multi_sig_spend2, multi_sig_vote1, multi_sig_vote2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 2, 0) + # Uncomment only to determine the correct mining_nonce of above blocks - # from qrl.core.PoWValidator import PoWValidator - # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): - # block_1.set_nonces(block_1.mining_nonce + 1) + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) # print(block_1.mining_nonce) self.assertTrue(block_1.validate(self.chain_manager, {})) result = self.chain_manager.add_block(block_1) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) - self.assertTrue(result) - self.assertEqual(self.chain_manager.last_block, block_1) + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) - # Yes, Bob is Alice's slave. - alice_state = self.chain_manager.get_address_state(alice.address) - self.assertEqual(len(alice_state.slave_pks_access_type), 1) - self.assertTrue(str(bob.pk) in alice_state.slave_pks_access_type) + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) - # Add fork block on genesis block - with patch('qrl.core.misc.ntp.getTime') as time_mock: - time_mock.return_value = 1715270948 # Very high to get an easy difficulty - fork_block = Block.create(block_number=1, - prev_headerhash=self.genesis_block.headerhash, - prev_timestamp=self.genesis_block.timestamp, - transactions=[], - miner_address=bob.address) + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + - multi_sig_spend1.total_amount) + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) + block_2 = Block.create(dev_config=config.dev, + block_number=2, + prev_headerhash=block_1.headerhash, + prev_timestamp=block_1.timestamp, + transactions=[multi_sig_vote3, multi_sig_vote4], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_2.set_nonces(config.dev, 0, 0) - fork_block.set_nonces(4, 0) # Uncomment only to determine the correct mining_nonce of above blocks - # from qrl.core.PoWValidator import PoWValidator - # while not PoWValidator().validate_mining_nonce(self.state, fork_block.blockheader, False): - # fork_block.set_nonces(fork_block.mining_nonce + 1) - # print(fork_block.mining_nonce) - self.assertTrue(fork_block.validate(self.chain_manager, {})) - result = self.chain_manager.add_block(fork_block) + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_2.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_2) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) - self.assertTrue(result) - self.assertEqual(self.chain_manager.last_block, block_1) + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + - multi_sig_spend1.total_amount) - fork_block = self.state.get_block(fork_block.headerhash) - self.assertIsNotNone(fork_block) + transfer_transaction2 = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction2._data.nonce = 4 + transfer_transaction2.sign(bob_xmss) + self.assertTrue(transfer_transaction2.validate_or_raise(True)) - # Add block_2 on fork_block. - with patch('qrl.core.misc.ntp.getTime') as time_mock: - time_mock.return_value = 1815270948 # Very high to get an easy difficulty - block_2 = fork_block.create(block_number=2, - prev_headerhash=fork_block.headerhash, - prev_timestamp=fork_block.timestamp, - transactions=[], - miner_address=bob.address) + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[transfer_transaction2], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 0, 0) - block_2.set_nonces(1, 0) # Uncomment only to determine the correct mining_nonce of above blocks - # from qrl.core.PoWValidator import PoWValidator - # while not PoWValidator().validate_mining_nonce(state, block_2.blockheader, False): - # block_2.set_nonces(block_2.mining_nonce + 1, 0) - # print(block_2.mining_nonce) - self.assertTrue(block_2.validate(self.chain_manager, {})) - result = self.chain_manager.add_block(block_2) + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount) + + multi_sig_vote5 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=True, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote5.sign(bob_xmss) + multi_sig_vote5.pbdata.nonce = 5 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(4)) + block_4 = Block.create(dev_config=config.dev, + block_number=4, + prev_headerhash=block_3.headerhash, + prev_timestamp=block_3.timestamp, + transactions=[multi_sig_vote5], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_4.set_nonces(config.dev, 4, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_4.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_4) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount + - multi_sig_vote5.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount) + + multi_sig_vote6 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote6.sign(bob_xmss) + multi_sig_vote6.pbdata.nonce = 6 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(5)) + block_5 = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=block_4.headerhash, + prev_timestamp=block_4.timestamp, + transactions=[multi_sig_vote6], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_5.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_5.blockheader, config.dev, False): + # block_5.set_nonces(config.dev, block_5.mining_nonce + 1) + # print(block_5.mining_nonce) + self.assertTrue(block_5.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_5) + self.assertTrue(result) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertTrue(vote_stats.executed) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount + - multi_sig_vote5.fee + - multi_sig_vote6.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + multi_sig_spend2.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward + + block_5.fee_reward + + block_5.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0] + + multi_sig_spend2.amounts[1]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount + - multi_sig_spend2.total_amount) + + # Check Txns in State + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertIsNotNone(vote_stats) + self.assertTrue(vote_stats.executed) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertIsNotNone(vote_stats) + self.assertTrue(vote_stats.executed) + self.assertEqual(vote_stats.total_weight, 10) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_create.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_create.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_spend2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_spend2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote2.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote3.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote3.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote4.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote5.txhash) + multi_sig_vote5.set_prev_tx_hash(multi_sig_vote4.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote5.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote6.txhash) + multi_sig_vote6.set_prev_tx_hash(multi_sig_vote5.txhash) + self.assertEqual(tx_meta_data[0].pbdata, multi_sig_vote6.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction1.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction1.pbdata) + + tx_meta_data = self.chain_manager.get_tx_metadata(transfer_transaction2.txhash) + self.assertEqual(tx_meta_data[0].pbdata, transfer_transaction2.pbdata) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_create.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_spend2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote1.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote2.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(alice_addr_state.address, multi_sig_vote3.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote4.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote5.ots_key) + self.assertTrue(result) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote6.ots_key) + self.assertTrue(result) - self.assertTrue(result) - self.assertEqual(self.chain_manager.last_block.block_number, block_2.block_number) - self.assertEqual(self.chain_manager.last_block.serialize(), block_2.serialize()) + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction1.ots_key) + self.assertTrue(result) - # Now we are on the forked chain, Bob is no longer Alice's slave. - alice_state = self.chain_manager.get_address_state(alice.address) - self.assertFalse(str(bob.pk) in alice_state.slave_pks_access_type) + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, transfer_transaction2.ots_key) + self.assertTrue(result) + + # Rollback state to block number 4 + self.assertTrue(self.chain_manager._rollback(block_4.headerhash)) + + self.assertEqual(self.chain_manager.last_block.block_number, block_4.block_number) + + # Post Rollback tests + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + self.assertEqual(vote_stats.total_weight, 4) + + tx_meta_data = self.chain_manager.get_tx_metadata(multi_sig_vote6.txhash) + self.assertIsNone(tx_meta_data) + + bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) + multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, + multi_sig_address) + + self.assertEqual(bob_addr_state.nonce, 5) + self.assertEqual(alice_addr_state.nonce, 5) + self.assertEqual(random_addr_state.nonce, 0) + + self.assertEqual(bob_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + - transfer_transaction1.fee + - transfer_transaction1.total_amount + - transfer_transaction2.fee + - transfer_transaction2.total_amount + - multi_sig_vote5.fee) + self.assertEqual(alice_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) + self.assertEqual(random_addr_state.balance, + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) + + self.assertIsNotNone(multi_sig_address_state) + self.assertEqual(multi_sig_address_state.balance, + transfer_transaction1.total_amount + + transfer_transaction2.total_amount + - multi_sig_spend1.total_amount) + + # Check OTS key usage + p = PaginatedBitfield(False, self.state._db) + + result = p.load_bitfield_and_ots_key_reuse(bob_addr_state.address, multi_sig_vote6.ots_key) + self.assertFalse(result) + + # Rollback state to block number 3 + self.assertTrue(self.chain_manager._rollback(block_3.headerhash)) + + self.assertEqual(self.chain_manager.last_block.block_number, 3) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) + self.assertTrue(vote_stats.executed) + + vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend2.txhash) + self.assertFalse(vote_stats.executed) + self.assertEqual(vote_stats.total_weight, 10) @patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) def test_get_headerhashes(self): @@ -308,25 +3958,313 @@ def test_fork_recovery(self): self.chain_manager.add_block(block_3_alt) self.assertEqual(self.chain_manager.last_block, block_3) - # When it is obvious that the fork is longer (has a higher cum. diff), the chain manager invokes _fork_recovery() - # and switches over to the fork + # When it is obvious that the fork is longer (has a higher cum. diff), the chain manager invokes + # _fork_recovery() and switches over to the fork self.chain_manager.add_block(block_4_alt) self.assertEqual(self.chain_manager.last_block, block_4_alt) + def test_new_state_container(self): + with set_qrl_dir('no_data'): + with State() as state: + pass + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_update_state_container(self, time_mock): + """ + Features Tested + - Behavior of update_state_container when a multisig vote txn is made for an unknown multi sig spend txn + + Expectation + - update_state_container must return false + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 3, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + + state_container = self.chain_manager.new_state_container(set(), + 10, + False, + None) + + self.assertFalse(self.chain_manager.update_state_container(multi_sig_vote1, state_container)) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_update_state_container2(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn & multisig spend txn + both are added into same block + - Behavior of update_state_container for multi_sig_vote1 and multi_sig_vote2 txn + + Expectation + - update_state_container must return false and thus block should not be added as multi_sig_create + doesnt have any balance + - update_state_container must return false for both multi_sig_vote1 and multi_sig_vote2 txn + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, multi_sig_spend], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # from qrl.core.PoWValidator import PoWValidator + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertFalse(result) + + state_container = self.chain_manager.new_state_container(set(), + 10, + False, + None) + + self.assertFalse(self.chain_manager.update_state_container(multi_sig_vote1, state_container)) + self.assertFalse(self.chain_manager.update_state_container(multi_sig_vote2, state_container)) + + @set_default_balance_size() + @set_hard_fork_block_number() + @patch('qrl.core.misc.ntp.getTime') + def test_update_state_container3(self, time_mock): + """ + Features Tested + - Behavior of Block validation when multisig create txn, transfer txn & multisig spend txn + are added into same block + + Expectation + - update_state_container when provided with txns multi_sig_vote1 and multi_sig_vote2, it must + return true, as the multi-sig create and spend txn both are available into the state + + :param time_mock: + :return: + """ + with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): + self.chain_manager.load(self.genesis_block) + + extended_seed = "010300cebc4e25553afa0aab899f7838e59e18a48852fa9dfd5" \ + "ae78278c371902aa9e6e9c1fa8a196d2dba0cbfd2f2d212d16c" + random_xmss = XMSS.from_extended_seed(hstr2bin(extended_seed)) + alice_xmss = get_alice_xmss(4) + bob_xmss = get_bob_xmss(4) + multi_sig_create = MultiSigCreate.create(signatories=[alice_xmss.address, + bob_xmss.address], + weights=[4, 6], + threshold=5, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_create.sign(alice_xmss) + multi_sig_create.pbdata.nonce = 1 + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(multi_sig_create.txhash) + + transfer_transaction = TransferTransaction.create(addrs_to=[multi_sig_address], + amounts=[40 * int(config.dev.shor_per_quanta)], + message_data=None, + fee=1 * config.dev.shor_per_quanta, + xmss_pk=bob_xmss.pk) + transfer_transaction._data.nonce = 1 + transfer_transaction.sign(bob_xmss) + self.assertTrue(transfer_transaction.validate_or_raise(True)) + + multi_sig_spend = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[random_xmss.address, alice_xmss.address], + amounts=[10, 5], + expiry_block_number=100, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_spend.sign(alice_xmss) + multi_sig_spend.pbdata.nonce = 2 + + multi_sig_vote1 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=alice_xmss.pk) + multi_sig_vote1.sign(alice_xmss) + multi_sig_vote1.pbdata.nonce = 3 + + multi_sig_vote2 = MultiSigVote.create(shared_key=multi_sig_spend.txhash, + unvote=False, + fee=0, + xmss_pk=bob_xmss.pk) + multi_sig_vote2.sign(bob_xmss) + multi_sig_vote2.pbdata.nonce = 2 + time_mock.return_value = 1615270948 # Very high to get an easy difficulty + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(1)) + block_1 = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=self.genesis_block.headerhash, + prev_timestamp=self.genesis_block.timestamp, + transactions=[multi_sig_create, transfer_transaction, multi_sig_spend], + miner_address=alice_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_1.set_nonces(config.dev, 0, 0) + + # Uncomment only to determine the correct mining_nonce of above blocks + # while not self.chain_manager.validate_mining_nonce(block_1.blockheader, config.dev, False): + # block_1.set_nonces(config.dev, block_1.mining_nonce + 1) + # print(block_1.mining_nonce) + self.assertTrue(block_1.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_1) + + self.assertTrue(result) + + state_container = self.chain_manager.new_state_container(set(), + 10, + False, + None) + + self.assertTrue(self.chain_manager.update_state_container(multi_sig_vote1, state_container)) + self.assertTrue(self.chain_manager.update_state_container(multi_sig_vote2, state_container)) + class TestChainManager(TestCase): def setUp(self): self.state = Mock(autospec=State) self.state.get_measurement.return_value = 10000000 - del GenesisBlock.instance # Removing Singleton instance + try: + del GenesisBlock.instance # Removing Singleton instance + except Exception: # noqa + pass self.genesis_block = GenesisBlock() self.chain_manager = ChainManager(self.state) self.chain_manager.tx_pool = Mock() self.chain_manager._difficulty_tracker = Mock() - def test_fork_recovery_failed(self): + @patch('qrl.core.Block.Block', autospec=True) + def test_fork_recovery_failed(self, mock_block): # When switching to the longer chain fails, _fork_recovery() must _rollback and restore the shorter chain. # Mock out irrelevant functions self.chain_manager._update_block_number_mapping = Mock() @@ -352,7 +4290,7 @@ def test_fork_recovery_failed(self): # _fork_recovery() will _rollback() to the genesis block and go on the longer chain. # At this point, _rollback() should return the old hash path as a backup # in case switching to the longer chain fails. - self.chain_manager._rollback.return_value = [block_2.headerhash, block_1.headerhash] + self.chain_manager._rollback.return_value = [block_2.headerhash, block_1.headerhash], True self.chain_manager._fork_recovery(block_3_alt, fork_state) @@ -387,27 +4325,28 @@ def test_fork_recovery_rollbacked_already(self): ) # State.get_block() should say that we are already on block_1_alt - self.chain_manager._state.get_block.return_value = block_1_alt - - # _fork_recovery() will not call _rollback(), because it has already happened. - self.chain_manager._fork_recovery(block_3_alt, fork_state) + with patch.object(Block, 'get_block', return_value=block_1_alt): + # _fork_recovery() will not call _rollback(), because it has already happened. + self.chain_manager._fork_recovery(block_3_alt, fork_state) - # _fork_recovery() should have _rollback()ed when trying to switch to the longer chain - self.chain_manager._rollback.assert_not_called() + # _fork_recovery() should have _rollback()ed when trying to switch to the longer chain + self.chain_manager._rollback.assert_not_called() @patch('qrl.core.config') - @patch('qrl.core.ChainManager.ChainManager.height', new_callable=PropertyMock) - def test_add_block_doesnt_add_blocks_beyond_reorg_limit(self, m_height, m_config): + @patch('qrl.core.ChainManager.ChainManager.re_org_limit', new_callable=PropertyMock) + def test_add_block_doesnt_add_blocks_beyond_reorg_limit(self, m_re_org_limit, m_height): # If we are at height 40000, what's the use of adding a block that's height 1? Simply ignore that block. - m_config.dev.reorg_limit = 22000 + m_re_org_limit.return_value = 40000 m_height.return_value = 40000 block_1 = create_m_block(1, self.genesis_block, alice.address) ans = self.chain_manager.add_block(block_1) self.assertFalse(ans) - def test_add_block_refuses_to_add_too_large_blocks(self): + @patch('qrl.core.ChainManager.ChainManager.re_org_limit', new_callable=PropertyMock) + def test_add_block_refuses_to_add_too_large_blocks(self, m_re_org_limit): # State.get_block_size_limit() calculates how large each Block should be from the last 10 confirmed blocks. + m_re_org_limit.return_value = 0 self.state.get_block_size_limit.return_value = 5000000 block_1 = create_m_block(1, self.genesis_block, alice.address) block_1.size = 6000000 @@ -415,43 +4354,38 @@ def test_add_block_refuses_to_add_too_large_blocks(self): ans = self.chain_manager.add_block(block_1) self.assertFalse(ans) - def test_get_fork_point_failure_modes(self): + @patch('qrl.core.Block.Block', autospec=True) + def test_get_fork_point_failure_modes(self, mock_block): block_0 = create_m_block(0, Mock(headerhash=b'Fake Genesis', timestamp=replacement_getTime()), alice.address) block_1 = create_m_block(1, block_0, alice.address) block_2 = create_m_block(2, block_1, alice.address) + fork_block_0 = create_m_block(0, Mock(headerhash=b'Fake Genesis', timestamp=replacement_getTime()), alice.address) + fork_block_1 = create_m_block(1, fork_block_0, alice.address) + fork_block_2 = create_m_block(2, fork_block_1, alice.address) + # If _get_fork_point() ever reaches block_number 0, that means the genesis block is different! # Mock self.state leads us back to block_0 - self.state.get_block.side_effect = [block_2, block_1, block_0] - + mock_block.deserialize = MagicMock(side_effect=[fork_block_1, fork_block_0]) with self.assertRaises(Exception): - self.chain_manager._get_fork_point(block_2) + self.chain_manager._get_fork_point(fork_block_2) # If _get_fork_point() cannot find a particular block while walking back to the fork point, something has gone # very wrong # Mock self.state leads us back through a broken chain - self.state.get_block.side_effect = [block_2, None, block_0] + mock_block.deserialize.side_effect = [block_2, None, block_0] with self.assertRaises(Exception): self.chain_manager._get_fork_point(block_2) - def test_apply_block_fails_if_state_changes_fail(self): - # ChainManager._apply_block() should fail if Block.apply_state_changes() fails. - block = create_m_block(50, self.genesis_block, alice.address) - block.apply_state_changes.return_value = False - - ans = self.chain_manager._apply_block(block, []) - self.assertFalse(ans) - def test_try_branch_add_block_fails_if_apply_block_fails(self): # ChainManager._try_branch_add_block() should fail if ChainManager._apply_block() fails self.chain_manager._apply_block = Mock(return_value=False) block = create_m_block(50, self.genesis_block, alice.address) - block_added, fork_flag = self.chain_manager._try_branch_add_block(block, []) + block_added = self.chain_manager._try_branch_add_block(block, config.dev) self.assertFalse(block_added) - self.assertFalse(fork_flag) def test_add_chain_fails_if_fork_recovery_didnt_complete_successfully(self): block_1 = create_m_block(1, self.genesis_block, alice.address) @@ -472,7 +4406,8 @@ def test_add_chain_fails_if_fork_recovery_didnt_complete_successfully(self): ans = self.chain_manager.add_chain([block_1_alt.headerhash, block_2_alt.headerhash], fork_state) self.assertFalse(ans) - def test_add_chain_fails_if_apply_block_fails(self): + @patch('qrl.core.Block.Block', autospec=True) + def test_add_chain_fails_if_apply_block_fails(self, mock_block_deserialize): block_1 = create_m_block(1, self.genesis_block, alice.address) block_2 = create_m_block(2, block_1, alice.address) @@ -492,7 +4427,163 @@ def test_add_chain_fails_if_apply_block_fails(self): ans = self.chain_manager.add_chain([block_1_alt.headerhash, block_2_alt.headerhash], fork_state) self.assertFalse(ans) - def test_get_transaction(self): - # get_transaction() is simply a wrapper for State.get_tx_metadata - self.chain_manager.get_tx_metadata(b'txhash') - self.state.get_tx_metadata.assert_called_once() + @patch("qrl.core.Block.Block.get_block") + def test_get_measurement(self, mock_get_block): + def block(state, headerhash): + nth_block = Block() + if headerhash == b'test_block_1': + nth_block.blockheader._data.timestamp_seconds = 50000 + elif headerhash == b'test_block_2': + nth_block.blockheader._data.timestamp_seconds = 80000 + elif headerhash == b'test_block_3': + nth_block.blockheader._data.timestamp_seconds = 90000 + return nth_block + + parent_metadata = BlockMetadata.create(block_difficulty=b'\x00' * 32, + cumulative_difficulty=b'\x00' * 32, + child_headerhashes=[]) + + measurement = self.chain_manager.get_measurement(dev_config=config.dev, + block_timestamp=100000, + parent_headerhash=b'', + parent_metadata=parent_metadata) + + # Test Case, when count_headerhashes equals 0 + self.assertEqual(measurement, config.dev.block_timing_in_seconds) + + mock_get_block.side_effect = block + parent_metadata.update_last_headerhashes([], b'test_block_1') + + measurement = self.chain_manager.get_measurement(dev_config=config.dev, + block_timestamp=100000, + parent_headerhash=b'test_block_1', + parent_metadata=parent_metadata) + + # Test Case, when count_headerhashes equals 1 + self.assertEqual(measurement, + (100000 - 50000 + config.dev.block_timing_in_seconds) // 2) + + parent_metadata.update_last_headerhashes([b'test_block_1'], b'test_block_2') + + measurement = self.chain_manager.get_measurement(dev_config=config.dev, + block_timestamp=100000, + parent_headerhash=b'test_block_2', + parent_metadata=parent_metadata) + + # Test Case, when count_headerhashes is greater than 1 + # but less than config.dev.N_measurement + self.assertEqual(measurement, + (100000 - 80000 + config.dev.block_timing_in_seconds) // 2) + + parent_metadata.update_last_headerhashes([b'test_block_3'] * config.dev.N_measurement, + b'test_block_2') + + measurement = self.chain_manager.get_measurement(dev_config=config.dev, + block_timestamp=100000, + parent_headerhash=b'test_block_2', + parent_metadata=parent_metadata) + + # Test Case, when count_headerhashes is greater than config.dev.N_measurement + self.assertEqual(measurement, + (100000 - 90000) // config.dev.N_measurement) + + def test_get_all_address_state(self): + with set_qrl_dir('no_data'): + with State() as state: + chain_manager = ChainManager(state) + addresses_state = chain_manager.get_all_address_state() + self.assertEqual(len(addresses_state), 0) + + alice_xmss = get_alice_xmss() + alice_address = alice_xmss.address + address_state = OptimizedAddressState.get_optimized_address_state(state, alice_address) + addresses_state = { + alice_address: address_state + } + self.assertTrue(isinstance(address_state.address, bytes)) + OptimizedAddressState.put_optimized_addresses_state(state, addresses_state) + + addresses_state = chain_manager.get_all_address_state() + self.assertEqual(len(addresses_state), 1) + + bob_xmss = get_bob_xmss() + bob_address = bob_xmss.address + address_state = OptimizedAddressState.get_optimized_address_state(state, bob_address) + addresses_state = { + bob_address: address_state + } + self.assertTrue(isinstance(address_state.address, bytes)) + OptimizedAddressState.put_optimized_addresses_state(state, addresses_state) + + addresses_state = chain_manager.get_all_address_state() + self.assertEqual(len(addresses_state), 2) + + def test_set_affected_address(self): + block = Block.create(dev_config=config.dev, + block_number=10, + prev_headerhash=b'', + prev_timestamp=10, + transactions=[], + miner_address=get_some_address(1), + seed_height=None, + seed_hash=None) + # Test Case: without any transactions of block + self.assertEqual(self.chain_manager.set_affected_address(block), + {config.dev.coinbase_address, get_some_address(1)}) + + alice_xmss = get_alice_xmss() + block = Block.create(dev_config=config.dev, + block_number=10, + prev_headerhash=b'', + prev_timestamp=10, + transactions=[TransferTransaction.create(addrs_to=[get_some_address(2), + get_some_address(3)], + amounts=[100, 100], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk)], + miner_address=get_some_address(1), + seed_height=None, + seed_hash=None) + + # Test Case, with one Transaction + self.assertEqual(self.chain_manager.set_affected_address(block), + {config.dev.coinbase_address, + get_some_address(1), + get_some_address(2), + get_some_address(3), + alice_xmss.address}) + + def test_get_block_datapoint(self): + with set_qrl_dir('no_data'): + with State() as state: + chain_manager = ChainManager(state) + # Test Case: When block not found + self.assertIsNone(chain_manager.get_block_datapoint(b'test')) + + alice_xmss = get_alice_xmss() + blocks = gen_blocks(20, state, alice_xmss.address) + for i in range(1, 20): + datapoint = chain_manager.get_block_datapoint(blocks[i].headerhash) + self.assertEqual(datapoint.difficulty, "256") + self.assertEqual(datapoint.timestamp, 1615270947 + i) + self.assertEqual(datapoint.header_hash, blocks[i].headerhash) + self.assertEqual(datapoint.header_hash_prev, blocks[i - 1].headerhash) + + def test_get_state_mainchain(self): + with set_qrl_dir('no_data'): + with State() as state: + chain_manager = ChainManager(state) + alice_xmss = get_alice_xmss() + alice_state = OptimizedAddressState.get_default(alice_xmss.address) + alice_state.increase_nonce() + alice_state.update_balance(None, 1000) + addresses_state = { + alice_state.address: alice_state, + } + OptimizedAddressState.put_optimized_addresses_state(state, addresses_state, None) + addresses_state1, success = chain_manager.get_state_mainchain({alice_state.address}) + + self.assertTrue(success) + self.assertEqual(addresses_state[alice_state.address].serialize(), + addresses_state1[alice_state.address].serialize()) diff --git a/tests/core/test_GenesisBlock.py b/tests/core/test_GenesisBlock.py index aa90091e1..4e5133aed 100644 --- a/tests/core/test_GenesisBlock.py +++ b/tests/core/test_GenesisBlock.py @@ -21,5 +21,6 @@ def test_genesis_block_values(self): self.assertIsNotNone(gb) self.assertEqual(0, gb.block_number) + self.assertEqual(config.user.genesis_prev_headerhash, gb.prev_headerhash) self.assertEqual(1, len(gb.genesis_balance)) diff --git a/tests/core/test_LastTransactions.py b/tests/core/test_LastTransactions.py new file mode 100644 index 000000000..145c62450 --- /dev/null +++ b/tests/core/test_LastTransactions.py @@ -0,0 +1,106 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from unittest import TestCase +from mock import MagicMock + +from qrl.core.LastTransactions import LastTransactions +from qrl.core.misc import logger, db +from qrl.core.State import State +from qrl.core.txs.TransferTransaction import TransferTransaction +from qrl.core.Block import Block + +from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_some_address + +logger.initialize_default() + + +class TestLastTransactions(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.m_db = MagicMock(name='mock DB', autospec=db.DB) + + def test_update_last_tx(self): + alice_xmss = get_alice_xmss() + # Test Case: When there is no last txns + self.assertEqual(LastTransactions.get_last_txs(self.state), []) + + block = Block() + tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block._data.transactions.extend([tx1.pbdata]) + LastTransactions._update_last_tx(self.state, block, None) + last_txns = LastTransactions.get_last_txs(self.state) + + # Test Case: When there is only 1 last txns + self.assertEqual(len(last_txns), 1) + self.assertEqual(last_txns[0].to_json(), tx1.to_json()) + + block = Block() + tx2 = TransferTransaction.create(addrs_to=[get_some_address(2), get_some_address(3)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + + tx3 = TransferTransaction.create(addrs_to=[get_some_address(4), get_some_address(5)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block._data.transactions.extend([tx2.pbdata, tx3.pbdata]) + LastTransactions._update_last_tx(self.state, block, None) + last_txns = LastTransactions.get_last_txs(self.state) + + # Test Case: When there are 3 last txns + self.assertEqual(len(last_txns), 3) + self.assertEqual(last_txns[0].to_json(), + tx3.to_json()) + self.assertEqual(last_txns[1].to_json(), + tx2.to_json()) + self.assertEqual(last_txns[2].to_json(), + tx1.to_json()) + + def test_get_last_txs(self): + self.assertEqual(LastTransactions.get_last_txs(self.state), []) + + alice_xmss = get_alice_xmss() + block = Block() + tx1 = TransferTransaction.create(addrs_to=[get_some_address(0), get_some_address(1)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block._data.transactions.extend([tx1.pbdata]) + LastTransactions._update_last_tx(self.state, block, None) + last_txns = LastTransactions.get_last_txs(self.state) + + # Test Case: When there is only 1 last txns + self.assertEqual(len(last_txns), 1) + self.assertEqual(last_txns[0].to_json(), tx1.to_json()) + + def test_remove_last_tx(self): + # Test Case: When there is no last txns + self.assertEqual(LastTransactions.get_last_txs(self.state), []) + + alice_xmss = get_alice_xmss() + + block = Block() + tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block._data.transactions.extend([tx1.pbdata]) + LastTransactions._update_last_tx(self.state, block, None) + last_txns = LastTransactions.get_last_txs(self.state) + + self.assertEqual(last_txns[0].to_json(), tx1.to_json()) + + LastTransactions._remove_last_tx(self.state, block, None) + last_txns = LastTransactions.get_last_txs(self.state) + self.assertEqual(last_txns, []) diff --git a/tests/core/test_Miner.py b/tests/core/test_Miner.py index a85e82a7c..6fd6cadc6 100644 --- a/tests/core/test_Miner.py +++ b/tests/core/test_Miner.py @@ -3,10 +3,13 @@ from mock import Mock, patch, create_autospec, MagicMock from pyqryptonight.pyqryptonight import StringToUInt256 -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.Block import Block from qrl.core.misc import logger from qrl.core.ChainManager import ChainManager +from qrl.core.StateContainer import StateContainer from qrl.core.Miner import Miner from qrl.core.TransactionPool import TransactionPool from qrl.core.misc.helper import parse_qaddress @@ -32,6 +35,9 @@ def setUp(self): self.m_mining_address = parse_qaddress(self.m_mining_qaddress) self.chain_manager = Mock(spec=ChainManager) + self.chain_manager.get_block_size_limit.return_value = 500 + # self.chain_manager.get_address_state.return_value = self.alice_address_state + self.chain_manager.get_config_by_block_number.return_value = config.dev self.parent_block = Block() self.parent_difficulty = StringToUInt256('0') # tuple (0,0,0,0,0...) length 32 @@ -39,11 +45,10 @@ def setUp(self): m_add_unprocessed_txn_fn = create_autospec(P2PFactory.add_unprocessed_txn) mining_thread_count = 1 - self.miner = Miner(self.m_pre_block_logic, + self.miner = Miner(self.chain_manager, + self.m_pre_block_logic, self.m_mining_address, - self.chain_manager, - mining_thread_count, - m_add_unprocessed_txn_fn) + mining_thread_count) self.txpool = Mock(spec=TransactionPool) self.txpool.transactions = [] @@ -65,7 +70,8 @@ def test_prepare_next_unmined_block_template_works(self, m_getTime, m_logger): self.miner.prepare_next_unmined_block_template(self.m_mining_address, self.txpool, self.parent_block, - self.parent_difficulty) + self.parent_difficulty, + config.dev) self.assertEqual(self.miner._current_difficulty, StringToUInt256('2')) self.assertEqual(self.miner._current_target, StringToUInt256( @@ -87,7 +93,8 @@ def test_prepare_next_unmined_block_template_exception(self, m_getTime, m_logger self.miner.prepare_next_unmined_block_template(self.m_mining_address, self.txpool, self.parent_block, - self.parent_difficulty) + self.parent_difficulty, + config.dev) self.assertIsNone(self.miner._current_difficulty) self.assertIsNone(self.miner._current_target) @@ -107,8 +114,8 @@ def test_start_mining_works(self, m_getTime, m_logger): StringToUInt256('115792089237316195423570985008687907853269984665640564039457584007913129639807') # start() is from Qryptominer, let's not actually mine in a test - with patch('qrl.core.Miner.Miner.start', spec=True) as m_start: - self.miner.start_mining(self.parent_block, self.parent_difficulty) + with patch('qrl.core.miners.qryptonight7.CNv1Miner.CNv1Miner.start', spec=True) as m_start: + self.miner.start_mining(self.parent_block, self.parent_difficulty, config.dev) m_start.assert_called_once() def test_get_block_to_mine_no_existing_block_being_mined_upon(self, m_getTime, m_logger): @@ -136,7 +143,7 @@ def test_get_block_to_mine_not_mining_upon_last_block(self, m_getTime, m_logger) m_getTime.return_value = 1526830525 self.miner._current_difficulty = StringToUInt256('1') m_mining_block = Mock(autospec=Block) - m_mining_block.mining_blob = b'big_bad_blob' + m_mining_block.mining_blob.return_value = b'big_bad_blob' m_mining_block.prev_headerhash = b'nothing should be equal to this' self.miner._mining_block = m_mining_block @@ -156,11 +163,13 @@ def test_get_block_to_mine_perfect_block_no_changes(self, m_getTime, m_logger): m_coinbase.coinbase.addr_to = self.m_mining_address m_parent_block = Mock(autospec=Block, name='mock parent_block') + m_parent_block.block_number = 10 + m_parent_block.timestamp = 0 m_parent_block.transactions = [m_coinbase] m_mining_block = Mock(autospec=Block, name='mock _mining_block') m_mining_block.transactions = [m_coinbase] - m_mining_block.mining_blob = b'this is the blob you should iterate the nonce upon' + m_mining_block.mining_blob.return_value = b'this is the blob you should iterate the nonce upon' self.miner._mining_block = m_mining_block self.miner._current_difficulty = StringToUInt256('1') @@ -186,11 +195,13 @@ def test_get_block_to_mine_we_have_a_block_in_mind(self, m_getTime, m_logger): m_coinbase.coinbase.addr_to = self.m_mining_address m_parent_block = Mock(autospec=Block, name='mock parent_block') + m_parent_block.block_number = 10 + m_parent_block.timestamp = 0 m_parent_block.transactions = [m_coinbase] m_mining_block = Mock(autospec=Block, name='mock _mining_block') m_mining_block.transactions = [m_coinbase] - m_mining_block.mining_blob = b'this is the blob you should iterate the nonce upon' + m_mining_block.mining_blob.return_value = b'this is the blob you should iterate the nonce upon' self.miner._mining_block = m_mining_block self.miner._current_difficulty = StringToUInt256('1') @@ -212,6 +223,7 @@ def test_get_block_to_mine_we_have_a_block_in_mind(self, m_getTime, m_logger): def test_get_block_to_mine_chokes_on_invalid_mining_address(self, m_getTime, m_logger): invalid_address = self.m_mining_qaddress + 'aaaa' m_parent_block = Mock(autospec=Block, name='mock parent_block') + m_parent_block.block_number = 10 with self.assertRaises(ValueError): self.miner.get_block_to_mine(invalid_address.encode(), self.txpool, m_parent_block, self.parent_difficulty) @@ -224,6 +236,7 @@ def test_submit_mined_block(self, m_getTime, m_logger): :return: """ m_mining_block = Mock(autospec=Block, name='mock _mining_block') + m_mining_block.block_number = 10 m_mining_block.verify_blob.return_value = False self.miner._mining_block = m_mining_block blob = 'this is a blob12345that was the nonce'.encode() @@ -250,9 +263,13 @@ def setUp(self): self.m_mining_qaddress = alice.qaddress self.m_mining_address = parse_qaddress(self.m_mining_qaddress) + self.alice_address_state = Mock(autospec=OptimizedAddressState, + name='mock alice OptimizedAddressState') + self.chain_manager = Mock(spec=ChainManager) self.chain_manager.get_block_size_limit.return_value = 500 - self.chain_manager.get_address_state.return_value = Mock(autospec=AddressState, name='mock alice AddressState') + self.chain_manager.get_address_state.return_value = self.alice_address_state + self.chain_manager.get_config_by_block_number.return_value = config.dev self.parent_block = Block() self.parent_difficulty = StringToUInt256('0') # tuple (0,0,0,0,0...) length 32 @@ -261,11 +278,10 @@ def setUp(self): m_add_unprocessed_txn_fn = create_autospec(P2PFactory.add_unprocessed_txn) mining_thread_count = 1 - self.miner = Miner(self.m_pre_block_logic, + self.miner = Miner(self.chain_manager, + self.m_pre_block_logic, self.m_mining_address, - self.chain_manager, - mining_thread_count, - m_add_unprocessed_txn_fn) + mining_thread_count) self.txpool = TransactionPool(None) @@ -283,9 +299,26 @@ def replacement_set_affected_address(addresses_set): "set_affected_address": replacement_set_affected_address } + def mock_new_state_container(self): + addresses_state = {alice.address: self.alice_address_state} + self.chain_manager.new_state_container.return_value = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=5, + total_coin_supply=0, + current_dev_config=config.dev, + write_access=False, + my_db=None, + batch=None) + @patch('qrl.core.Miner.Block.create') def test_create_block_with_one_transaction(self, m_create, m_logger): + self.mock_new_state_container() m_tx = Mock(autospec=TransferTransaction, name='mock TransferTransaction') + m_tx.fee = 0 m_tx.configure_mock(**self.m_tx_args) m_create.return_value = Mock(autospec=Block, name='mock Block', size=205) @@ -295,13 +328,17 @@ def test_create_block_with_one_transaction(self, m_create, m_logger): self.miner.create_block(last_block=self.parent_block, mining_nonce=0, tx_pool=self.txpool, miner_address=self.m_mining_address) - m_create.assert_called_with(block_number=1, prev_headerhash=b'', prev_timestamp=0, transactions=[m_tx], - miner_address=alice.address) + seed_block = self.chain_manager.get_block_by_number( + self.miner._qn.get_seed_height(self.parent_block.block_number + 1)) + m_create.assert_called_with(dev_config=config.dev, block_number=1, prev_headerhash=b'', prev_timestamp=0, + transactions=[m_tx], miner_address=alice.address, + seed_height=seed_block.block_number, seed_hash=seed_block.headerhash) @patch('qrl.core.Miner.Block.create') def test_create_block_does_not_include_invalid_txs_from_txpool(self, m_create, m_logger): - self.m_tx_args["validate_extended.return_value"] = False + self.mock_new_state_container() m_tx = Mock(autospec=TransferTransaction, name='mock TransferTransaction') + m_tx.validate_all.return_value = False m_tx.configure_mock(**self.m_tx_args) m_create.return_value = Mock(autospec=Block, name='mock Block', size=205) @@ -311,5 +348,8 @@ def test_create_block_does_not_include_invalid_txs_from_txpool(self, m_create, m self.miner.create_block(last_block=self.parent_block, mining_nonce=0, tx_pool=self.txpool, miner_address=self.m_mining_address) - m_create.assert_called_with(block_number=1, prev_headerhash=b'', prev_timestamp=0, transactions=[], - miner_address=alice.address) + seed_block = self.chain_manager.get_block_by_number( + self.miner._qn.get_seed_height(self.parent_block.block_number + 1)) + m_create.assert_called_with(dev_config=config.dev, block_number=1, prev_headerhash=b'', prev_timestamp=0, + transactions=[], miner_address=alice.address, + seed_height=seed_block.block_number, seed_hash=seed_block.headerhash) diff --git a/tests/core/test_MultiSigAddressState.py b/tests/core/test_MultiSigAddressState.py new file mode 100644 index 000000000..0e12d0045 --- /dev/null +++ b/tests/core/test_MultiSigAddressState.py @@ -0,0 +1,87 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from pyqrllib.pyqrllib import hstr2bin, bin2hstr +from unittest import TestCase + +from qrl.core.misc import logger +from qrl.core.AddressState import AddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from qrl.core.State import State +from tests.misc.helper import set_qrl_dir, get_bob_xmss, get_alice_xmss, get_random_xmss + +logger.initialize_default() + + +class TestMultiSigAddressState(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + + def test_generate_multi_sig_address(self): + creation_tx_hash = bytes(hstr2bin("5a4c37ef7e5b7cc5a2a58ab730269ed8" + "f4cbf08a005dc3508e31465535e1d6bb")) + address = MultiSigAddressState.generate_multi_sig_address(creation_tx_hash) + expected_address = bytes(hstr2bin("1100003674370317e1cac0ca13f896ab5b6472a" + "261ba0d2b2961d3adba1b9060f6e8f7fe2088fb")) + self.assertEqual(address, expected_address) + self.assertFalse(OptimizedAddressState.address_is_valid(address)) + + def test_address_is_valid(self): + address = bytes(hstr2bin("110000000000000000000000000000000000000" + "000000000000000000000000000000000000000")) + self.assertFalse(OptimizedAddressState.address_is_valid(address)) + + def test_get_multi_sig_address_state_by_address(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + random_xmss = get_random_xmss() + + signatories = [alice_xmss.address, bob_xmss.address] + weights = [20, 20] + threshold = 21 + multi_sig_tx = MultiSigCreate.create(signatories, + weights, + threshold, + 0, + random_xmss.pk) + multi_sig_tx.sign(random_xmss) + multi_sig_address_state = MultiSigAddressState.get_default(multi_sig_tx.txhash, + signatories, + weights, + threshold) + AddressState.put_address_state(self.state, multi_sig_address_state) + multi_sig_address_state2 = MultiSigAddressState.get_multi_sig_address_state_by_address( + self.state._db, + MultiSigAddressState.generate_multi_sig_address(multi_sig_tx.txhash)) + + self.assertEqual(multi_sig_address_state.pbdata, multi_sig_address_state2.pbdata) + + def test_put_multi_sig_addresses_state(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + random_xmss = get_random_xmss() + + signatories = [alice_xmss.address, bob_xmss.address] + weights = [20, 20] + threshold = 21 + multi_sig_tx = MultiSigCreate.create(signatories, + weights, + threshold, + 0, + random_xmss.pk) + multi_sig_tx.sign(random_xmss) + multi_sig_address_state = MultiSigAddressState.get_default(multi_sig_tx.txhash, + signatories, + weights, + threshold) + + multi_sig_addresses_state = {multi_sig_address_state.address: multi_sig_address_state} + AddressState.put_addresses_state(self.state, multi_sig_addresses_state) + + multi_sig_address_state2 = MultiSigAddressState.get_multi_sig_address_state_by_address( + self.state._db, + MultiSigAddressState.generate_multi_sig_address(multi_sig_tx.txhash)) + self.assertEqual(multi_sig_address_state.pbdata, multi_sig_address_state2.pbdata) diff --git a/tests/core/test_OptimizedAddressState.py b/tests/core/test_OptimizedAddressState.py new file mode 100644 index 000000000..7bc4ffb16 --- /dev/null +++ b/tests/core/test_OptimizedAddressState.py @@ -0,0 +1,175 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from mock import PropertyMock, patch +from unittest import TestCase +from math import ceil + +from qrl.core import config +from qrl.core.misc import logger +from qrl.core.State import State +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.PaginatedBitfield import PaginatedBitfield +from qrl.core.AddressState import AddressState +from tests.misc.helper import get_alice_xmss, get_slave_xmss, set_qrl_dir + +logger.initialize_default() + +alice = get_alice_xmss() +slave = get_slave_xmss() + + +class TestOptimizedAddressState(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + + # TODO: Move this test to Optimized Address State + def test_get_optimized_address_state(self): + alice_xmss = get_alice_xmss() + + alice_address = alice_xmss.address + address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + self.assertTrue(isinstance(address_state.address, bytes)) + + alice_address = bytearray(alice_xmss.address) + with self.assertRaises(TypeError): + OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + + alice_address = alice_xmss.address + address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + addresses_state = { + alice_address: address_state + } + self.assertTrue(isinstance(address_state.address, bytes)) + AddressState.put_addresses_state(self.state, addresses_state) + + address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + self.assertTrue(isinstance(address_state.address, bytes)) + + def test_get_optimized_address_state2(self): + alice_xmss = get_alice_xmss() + + alice_address = alice_xmss.address + address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + addresses_state = { + alice_address: address_state + } + self.assertTrue(isinstance(address_state.address, bytes)) + OptimizedAddressState.put_optimized_addresses_state(self.state, addresses_state) + address_state = OptimizedAddressState.get_optimized_address_state(self.state, alice_address) + self.assertTrue(isinstance(address_state.address, bytes)) + + def test_update_used_page_in_address_state(self): + alice_xmss = get_alice_xmss(4) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, self.state._db) + key = paginated_bitfield.generate_bitfield_key(address, 1) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(0, 16): + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i != 15: + self.assertEqual(address_state.ots_bitfield_used_page, 0) + else: + self.assertEqual(address_state.ots_bitfield_used_page, 1) + + for i in range(0, 16): + ots_bitfield = paginated_bitfield.key_value[key] + ots_key_index = i % config.dev.ots_tracking_per_page + offset = ots_key_index >> 3 + relative = ots_key_index % 8 + bitfield = bytearray(ots_bitfield[offset]) + self.assertEqual(bytes([bitfield[0] >> relative & 1]), b'\x01') + + self.assertEqual(address_state.ots_bitfield_used_page, 1) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_update_used_page_in_address_state2(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, self.state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + factor = min(config.dev.ots_tracking_per_page, 2 ** alice_xmss.height) + for i in range(0, 2 ** alice_xmss.height): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, (i + 1) // factor) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_update_used_page_in_address_state3(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, self.state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(3072, 2 ** alice_xmss.height): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(2048, 3072): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(1024, 2048): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(0, 1024): + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i + 1 == 1024: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_update_used_page_in_address_state4(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, self.state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(2048, 3072): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(1024, 2048): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + for i in range(0, 1024): + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i + 1 == 1024: + self.assertEqual(address_state.ots_bitfield_used_page, 3) + + for i in range(3072, 2 ** alice_xmss.height): + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i + 1 == 2 ** alice_xmss.height: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + else: + self.assertEqual(address_state.ots_bitfield_used_page, 3) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) diff --git a/tests/core/test_PaginatedBitfield.py b/tests/core/test_PaginatedBitfield.py new file mode 100644 index 000000000..630539dba --- /dev/null +++ b/tests/core/test_PaginatedBitfield.py @@ -0,0 +1,309 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from unittest import TestCase +from mock import PropertyMock, patch +import random +from math import ceil + +from qrl.core import config +from qrl.core.misc import logger +from qrl.core.State import State +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.PaginatedBitfield import PaginatedBitfield +from tests.misc.helper import get_alice_xmss, get_slave_xmss, set_qrl_dir + +logger.initialize_default() + +alice = get_alice_xmss() +slave = get_slave_xmss() + + +class TestPaginatedBitfield(TestCase): + def setUp(self): + pass + + def test_generate_bitfield_key(self): + with set_qrl_dir('no_data'): + state = State() + paginated_bitfield = PaginatedBitfield(True, state._db) + address = b'addr1' + page = 1 + expected_key = b'bitfield_' + address + b'_' + page.to_bytes(8, byteorder='big', signed=False) + found_key = paginated_bitfield.generate_bitfield_key(address, page) + self.assertEqual(expected_key, found_key) + + def test_load_bitfield_and_ots_key_reuse(self): + with set_qrl_dir('no_data'): + state = State() + alice_xmss = get_alice_xmss(4) + paginated_bitfield = PaginatedBitfield(True, state._db) + self.assertFalse(paginated_bitfield.load_bitfield_and_ots_key_reuse(alice_xmss.address, + 0)) + addresses_state = { + alice_xmss.address: OptimizedAddressState.get_default(alice_xmss.address) + } + paginated_bitfield.set_ots_key(addresses_state, alice_xmss.address, 0) + self.assertTrue(paginated_bitfield.load_bitfield_and_ots_key_reuse(alice_xmss.address, + 0)) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_ots_key_reuse(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Randomly using OTS key + :return: + """ + with set_qrl_dir('no_data'): + state = State() + + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + paginated_bitfield = PaginatedBitfield(True, state._db) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + bitfield_data = paginated_bitfield.get_paginated_data(address, 1) + self.assertFalse(paginated_bitfield.ots_key_reuse(bitfield_data, 0)) + + paginated_bitfield.set_ots_key(addresses_state, address, 0) + bitfield_data = paginated_bitfield.get_paginated_data(address, 1) + # False, as bitfield has been set but has not been written to state. + self.assertFalse(paginated_bitfield.ots_key_reuse(bitfield_data, 0)) + + # Writing bitfield to the state. + paginated_bitfield.put_addresses_bitfield(None) + bitfield_data = paginated_bitfield.get_paginated_data(address, 1) + self.assertTrue(paginated_bitfield.ots_key_reuse(bitfield_data, 0)) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_set_ots_key(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Randomly using OTS key + :return: + """ + with set_qrl_dir('no_data'): + state = State() + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(3072, 2 ** alice_xmss.height)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(2048, 3072)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(1024, 2048)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(0, 1024)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i == ots_indexes[-1]: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_set_ots_key2(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Randomly using OTS key + :return: + """ + with set_qrl_dir('no_data'): + state = State() + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(0, 2**alice_xmss.height)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i == ots_indexes[-1]: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_unset_ots_key(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Randomly using OTS key + :return: + """ + with set_qrl_dir('no_data'): + state = State() + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(3072, 2 ** alice_xmss.height)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(2048, 3072)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(1024, 2048)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(0, 1024)) + random.shuffle(ots_indexes) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i == ots_indexes[-1]: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + else: + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + paginated_bitfield.unset_ots_key(addresses_state, address, 2049) + self.assertEqual(address_state.ots_bitfield_used_page, 2) + + paginated_bitfield.unset_ots_key(addresses_state, address, 1023) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + paginated_bitfield.set_ots_key(addresses_state, address, 1023) + self.assertEqual(address_state.ots_bitfield_used_page, 2) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_unset_ots_key2(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Randomly using OTS key + :return: + """ + with set_qrl_dir('no_data'): + state = State() + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + ots_indexes = list(range(1, 2**alice_xmss.height)) + random.shuffle(ots_indexes) + ots_indexes.append(0) + for i in ots_indexes: + paginated_bitfield.set_ots_key(addresses_state, address, i) + if i == ots_indexes[-1]: + self.assertEqual(address_state.ots_bitfield_used_page, 4) + else: + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + paginated_bitfield.unset_ots_key(addresses_state, address, 4095) + self.assertEqual(address_state.ots_bitfield_used_page, 3) + + paginated_bitfield.unset_ots_key(addresses_state, address, 3000) + self.assertEqual(address_state.ots_bitfield_used_page, 2) + + paginated_bitfield.unset_ots_key(addresses_state, address, 2000) + self.assertEqual(address_state.ots_bitfield_used_page, 1) + + paginated_bitfield.unset_ots_key(addresses_state, address, 1000) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + paginated_bitfield.set_ots_key(addresses_state, address, 1000) + self.assertEqual(address_state.ots_bitfield_used_page, 1) + + paginated_bitfield.set_ots_key(addresses_state, address, 2000) + self.assertEqual(address_state.ots_bitfield_used_page, 2) + + paginated_bitfield.set_ots_key(addresses_state, address, 3000) + self.assertEqual(address_state.ots_bitfield_used_page, 3) + + paginated_bitfield.set_ots_key(addresses_state, address, 4095) + self.assertEqual(address_state.ots_bitfield_used_page, 4) + + @patch('qrl.core.config.DevConfig.ots_tracking_per_page', new_callable=PropertyMock, return_value=1024) + @patch('qrl.core.config.DevConfig.ots_bitfield_size', new_callable=PropertyMock) + def test_unset_ots_key3(self, mock_ots_bitfield_size, mock_ots_tracking_per_page): + """ + Features Tested + - Sequentially marking OTS indexes as used + - Sequentially marking OTS indexes as unused + - ots_bitfield_used_page value with each OTS index being used + + Expectation + - The ots_bitfield_used_page must increase by 1 for every sequential 1024 (ots_tracking_per_page) ots indexes + marked as used + + :param mock_ots_bitfield_size: + :param mock_ots_tracking_per_page: + :return: + """ + with set_qrl_dir('no_data'): + state = State() + mock_ots_bitfield_size.return_value = ceil(config.dev.ots_tracking_per_page / 8) + + alice_xmss = get_alice_xmss(12) + address = alice_xmss.address + address_state = OptimizedAddressState.get_default(address) + addresses_state = {address: address_state} + paginated_bitfield = PaginatedBitfield(True, state._db) + paginated_bitfield.update_used_page_in_address_state(address, addresses_state, 1) + self.assertEqual(address_state.ots_bitfield_used_page, 0) + + total_ots = 2 ** alice_xmss.height + for i in range(0, total_ots + 1): + paginated_bitfield.set_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, (i + 1) // config.dev.ots_tracking_per_page) + + self.assertEqual(address_state.ots_bitfield_used_page, + total_ots // config.dev.ots_tracking_per_page) + self.assertEqual(total_ots // config.dev.ots_tracking_per_page, 4) + + paginated_bitfield.unset_ots_key(addresses_state, address, total_ots - 1) + self.assertEqual(address_state.ots_bitfield_used_page, 3) + + for i in range(total_ots - 2, -1, -1): + paginated_bitfield.unset_ots_key(addresses_state, address, i) + self.assertEqual(address_state.ots_bitfield_used_page, i // config.dev.ots_tracking_per_page) diff --git a/tests/core/test_PaginatedData.py b/tests/core/test_PaginatedData.py new file mode 100644 index 000000000..f7307b19d --- /dev/null +++ b/tests/core/test_PaginatedData.py @@ -0,0 +1,216 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +from mock import patch, PropertyMock +from unittest import TestCase + +from qrl.core import config +from qrl.core.misc import logger +from qrl.core.PaginatedData import PaginatedData +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.State import State + +from tests.misc.helper import set_qrl_dir, get_alice_xmss + +logger.initialize_default() + + +class TestPaginatedData(TestCase): + def setUp(self): + self.alice = get_alice_xmss() + + def test_reset_key_value(self): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + + self.assertEqual(len(p.key_value), 0) + + p.key_value[b'a'] = [10] + self.assertEqual(len(p.key_value), 1) + + p.reset_key_value() + self.assertEqual(len(p.key_value), 0) + + def test_get_value(self): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + storage_key = p.generate_key(b'a', 0) + p.key_value[storage_key] = [10] + self.assertEqual(p.get_value(b'a', 0), [10]) + + def test_insert(self): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + + p.insert(OptimizedAddressState.get_default(b'a'), b'10') + self.assertEqual(p.get_value(b'a', 0), [b'10']) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_put_paginated_data(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + + for i in range(0, 10): + p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + self.assertEqual(alice_address_state.get_counter_by_name(p.name), i + 1) + + p.put_paginated_data(None) + self.assertEqual(alice_address_state.get_counter_by_name(p.name), 10) + + for i in range(10, 25): + p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + self.assertEqual(alice_address_state.get_counter_by_name(p.name), i + 1) + + p.put_paginated_data(None) + self.assertEqual(alice_address_state.get_counter_by_name(p.name), 25) + self.assertEqual(len(p.key_value), 0) + + pages_data = [] + for i in range(0, (25 // config.dev.data_per_page) + 1): + data = p.get_paginated_data(self.alice.address, + (i + 1) * config.dev.data_per_page - 1) + pages_data.append(data) + + self.assertEqual(len(pages_data), 3) + + self.assertEqual(len(pages_data[0]), 10) + for i in range(0, 10): + self.assertEqual(pages_data[0][i], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + + self.assertEqual(len(pages_data[1]), 10) + for i in range(10, 20): + self.assertEqual(pages_data[1][i - 10], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + + self.assertEqual(len(pages_data[2]), 5) + for i in range(20, 25): + self.assertEqual(pages_data[2][i - 20], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_revert_paginated_data(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + + for i in range(0, 25): + p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + p.put_paginated_data(None) + + full_hash = [] + for i in range(0, (25 // config.dev.data_per_page) + 1): + data = p.get_paginated_data(self.alice.address, + (i + 1) * config.dev.data_per_page - 1) + full_hash.extend(data) + + for tx_hash in full_hash[24:18:-1]: + p.remove(alice_address_state, tx_hash) + p.put_paginated_data(None) + + self.assertEqual(alice_address_state.get_counter_by_name(b'p_tx_hash'), + 19) + + # page 2 data count must be 0 + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, 2 * config.dev.data_per_page)), + 0) + + # page 1 data count must be 9 + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, config.dev.data_per_page)), + 9) + + # page 0 data count must be 10 + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, 0)), + 10) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_revert_paginated_data2(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + + for i in range(0, 25): + p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + + p.put_paginated_data(None) + + full_hash = [] + for i in range(0, (25 // config.dev.data_per_page) + 1): + data = p.get_paginated_data(self.alice.address, + (i + 1) * config.dev.data_per_page - 1) + full_hash.extend(data) + + for tx_hash in full_hash[-1::-1]: + p.remove(alice_address_state, tx_hash) + p.put_paginated_data(None) + + self.assertEqual(alice_address_state.get_counter_by_name(b'p_tx_hash'), + 0) + + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, 22)), + 0) + + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, 12)), + 0) + + self.assertEqual(len(p.get_paginated_data(alice_address_state.address, 2)), + 0) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_get_paginated_data(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + + total_hashes = 25 + expected_full_hash = [] + for i in range(0, total_hashes): + tx_hash = b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False) + p.insert(alice_address_state, tx_hash) + expected_full_hash.append(tx_hash) + + p.put_paginated_data(None) + + found_full_hash = [] + expected_data_count = [10, 10, 5] + for i in range(0, (total_hashes // config.dev.data_per_page) + 1): + data = p.get_paginated_data(self.alice.address, + (i + 1) * config.dev.data_per_page - 1) + self.assertEqual(len(data), expected_data_count[i]) + found_full_hash.extend(data) + + self.assertEqual(expected_full_hash, found_full_hash) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_put(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + key = b'test_key' + value = [b'hello world'] + storage_key = p.generate_key(key, 11) + p.put(storage_key, value, None) + found_value = p.get_paginated_data(key, 11) + self.assertEqual(value, found_value) + + @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) + def test_remove(self, mock_dev_config): + with set_qrl_dir('no_data'): + state = State() + p = PaginatedData(b'p_tx_hash', True, state._db) + key = b'test_key' + value = [b'hello world'] + storage_key = p.generate_key(key, 11) + p.put(storage_key, value, None) + found_value = p.get_paginated_data(key, 11) + self.assertEqual(value, found_value) + + p.delete(storage_key, None) + found_value = p.get_paginated_data(key, 11) + self.assertEqual([], found_value) diff --git a/tests/core/test_Qryptominer.py b/tests/core/test_Qryptominer.py index 35f63a502..e7b68c32c 100644 --- a/tests/core/test_Qryptominer.py +++ b/tests/core/test_Qryptominer.py @@ -28,7 +28,7 @@ def __init__(self): self.nonce = None self.solution_blob = None - def start(self, input, nonceOffset, target, thread_count): + def start(self, input, nonceOffset, target, thread_count=1): self.cancel() try: self._solution_lock.release() @@ -60,7 +60,8 @@ def handleEvent(self, event): new_diff, new_target = DifficultyTracker.get( measurement, - parent_difficulty=parent_difficulty) + parent_difficulty=parent_difficulty, + dev_config=config.dev) self.assertEqual(new_diff, (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -81,11 +82,11 @@ def handleEvent(self, event): 207, 109, 238, 83, 220, 167, 148, 247, 200, 197, 41, 37, 36, 150, 12, 116, 85, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 198, 40, 62, 106, 139, 108, 83, 216, 206, 161, 148, 50, 65, 212, 137, 94, 102, 124, 45) - self.assertEqual(expected_blob, tuple(block.mining_blob)) + self.assertEqual(expected_blob, tuple(block.mining_blob(dev_config=config.dev))) custom_qminer = CustomQMiner() - custom_qminer.start(input=block.mining_blob, - nonceOffset=block.mining_nonce_offset, + custom_qminer.start(input=block.mining_blob(dev_config=config.dev), + nonceOffset=block.mining_nonce_offset(dev_config=config.dev), target=new_target, thread_count=2) custom_qminer.wait_for_solution() diff --git a/tests/core/test_State.py b/tests/core/test_State.py index 3ef050190..15d72ea8c 100644 --- a/tests/core/test_State.py +++ b/tests/core/test_State.py @@ -5,72 +5,17 @@ import mock from mock import MagicMock, patch -from pyqrllib.pyqrllib import sha2_256 -from pyqryptonight.pyqryptonight import StringToUInt256 - from qrl.core import config -from qrl.core.AddressState import AddressState -from qrl.core.GenesisBlock import GenesisBlock from qrl.core.misc import logger, db from qrl.core.State import State -from qrl.core.txs.Transaction import Transaction -from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction -from qrl.core.txs.TransferTransaction import TransferTransaction -from qrl.core.TokenMetadata import TokenMetadata from qrl.core.Block import Block -from qrl.core.BlockMetadata import BlockMetadata -from qrl.generated import qrl_pb2, qrlstateinfo_pb2 +from qrl.generated import qrlstateinfo_pb2 -from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_bob_xmss, get_token_transaction, get_some_address, \ - replacement_getTime +from tests.misc.helper import set_qrl_dir, get_alice_xmss, replacement_getTime, gen_blocks logger.initialize_default() -def gen_blocks(block_count, state, miner_address): - blocks = [] - block = None - with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: - time_mock.return_value = 1615270948 - addresses_state = dict() - for i in range(0, block_count): - if i == 0: - block = GenesisBlock() - for genesis_balance in GenesisBlock().genesis_balance: - bytes_addr = genesis_balance.address - addresses_state[bytes_addr] = AddressState.get_default(bytes_addr) - addresses_state[bytes_addr]._data.balance = genesis_balance.balance - else: - block = Block.create(block_number=i, - prev_headerhash=block.headerhash, - prev_timestamp=block.timestamp, - transactions=[], - miner_address=miner_address) - addresses_set = state.prepare_address_list(block) - for address in addresses_set: - addresses_state[address] = state.get_address_state(address) - for tx_protobuf in block.transactions: - tx = Transaction.from_pbdata(tx_protobuf) - tx.apply_state_changes(addresses_state) - - block.set_nonces(10, 0) - blocks.append(block) - - metadata = BlockMetadata() - metadata.set_block_difficulty(StringToUInt256('256')) - state.put_block_metadata(block.headerhash, metadata, None) - - state.put_block(block, None) - bm = qrl_pb2.BlockNumberMapping(headerhash=block.headerhash, - prev_headerhash=block.prev_headerhash) - - state.put_block_number_mapping(block.block_number, bm, None) - state.update_mainchain_height(block.block_number, None) - state.put_addresses_state(addresses_state) - - return blocks - - @mock.patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) class TestState(TestCase): def setUp(self): @@ -84,384 +29,59 @@ def test_create_state(self): def test_release_state(self): self.assertIsNotNone(self.state) # to avoid warning (unused variable) - def test_get_address_state(self): - alice_xmss = get_alice_xmss() - - alice_address = alice_xmss.address - address_state = self.state.get_address_state(alice_address) - self.assertTrue(isinstance(address_state.address, bytes)) - - alice_address = bytearray(alice_xmss.address) - with self.assertRaises(TypeError): - self.state.get_address_state(alice_address) - - alice_address = alice_xmss.address - address_state = self.state.get_address_state(alice_address) - addresses_state = { - alice_address: address_state - } - self.assertTrue(isinstance(address_state.address, bytes)) - self.state.put_addresses_state(addresses_state) - - address_state = self.state.get_address_state(alice_address) - self.assertTrue(isinstance(address_state.address, bytes)) - - def test_get_all_address_state(self): - addresses_state = self.state.get_all_address_state() - self.assertEqual(len(addresses_state), 0) - - alice_xmss = get_alice_xmss() - alice_address = alice_xmss.address - address_state = self.state.get_address_state(alice_address) - addresses_state = { - alice_address: address_state - } - self.assertTrue(isinstance(address_state.address, bytes)) - self.state.put_addresses_state(addresses_state) - - addresses_state = self.state.get_all_address_state() - self.assertEqual(len(addresses_state), 1) - - bob_xmss = get_bob_xmss() - bob_address = bob_xmss.address - address_state = self.state.get_address_state(bob_address) - addresses_state = { - bob_address: address_state - } - self.assertTrue(isinstance(address_state.address, bytes)) - self.state.put_addresses_state(addresses_state) - - addresses_state = self.state.get_all_address_state() - self.assertEqual(len(addresses_state), 2) - def test_basic_state_funcs(self): - alice_xmss = get_alice_xmss() - self.assertTrue(self.state.get_address_is_used(alice_xmss.address)) - self.assertEqual(self.state._return_all_addresses(), []) batch = self.state.batch self.assertIsNotNone(batch) self.state.write_batch(batch) self.assertEqual(self.state.total_coin_supply, 0) - def test_get_address_nonce(self): - alice_xmss = get_alice_xmss() - self.assertEqual(self.state.get_address_nonce(alice_xmss.address), 0) - - def test_get_address_balance(self): - alice_xmss = get_alice_xmss() - self.assertEqual(self.state.get_address_balance(alice_xmss.address), 0) - - def test_get_address2(self): - alice_xmss = get_alice_xmss() - - alice_address = alice_xmss.address - address_state = self.state.get_address_state(alice_address) - addresses_state = { - alice_address: address_state - } - self.assertTrue(isinstance(address_state.address, bytes)) - self.state.put_addresses_state(addresses_state) - address_state = self.state.get_address_state(alice_address) - self.assertTrue(isinstance(address_state.address, bytes)) - - def test_create_token_metadata(self): - alice_xmss = get_alice_xmss() - bob_xmss = get_bob_xmss() - - token_transaction = get_token_transaction(alice_xmss, bob_xmss) - self.state.create_token_metadata(token_transaction) - - token_metadata = self.state.get_token_metadata(token_transaction.txhash) - self.assertEqual(token_metadata.token_txhash, token_transaction.txhash) - self.assertEqual(token_metadata.transfer_token_tx_hashes[0], token_transaction.txhash) - - def test_update_token_metadata(self): - alice_xmss = get_alice_xmss() - bob_xmss = get_bob_xmss() - - token_transaction = get_token_transaction(alice_xmss, bob_xmss) - self.state.create_token_metadata(token_transaction) - - transfer_token_transaction = TransferTokenTransaction.create(token_txhash=token_transaction.txhash, - addrs_to=[alice_xmss.address], - amounts=[100000000], - fee=1, - xmss_pk=bob_xmss.pk) - - self.state.update_token_metadata(transfer_token_transaction) - - token_metadata = self.state.get_token_metadata(token_transaction.txhash) - self.assertEqual(len(token_metadata.transfer_token_tx_hashes), 2) - self.assertEqual(token_metadata.transfer_token_tx_hashes[0], token_transaction.txhash) - self.assertEqual(token_metadata.transfer_token_tx_hashes[1], transfer_token_transaction.txhash) - - def test_get_token_metadata(self): - token_txhash = bytes(sha2_256(b'alpha')) - token_metadata = TokenMetadata.create(token_txhash, - [bytes(sha2_256(b'delta')), - bytes(sha2_256(b'gamma'))]) - self.state._db.get_raw = MagicMock(return_value=token_metadata.serialize()) - self.assertEqual(self.state.get_token_metadata(token_txhash).to_json(), - token_metadata.to_json()) - - def test_remove_transfer_token_metadata(self): - alice_xmss = get_alice_xmss() - bob_xmss = get_bob_xmss() - - token_transaction = get_token_transaction(alice_xmss, bob_xmss) - self.state.create_token_metadata(token_transaction) - - transfer_token = TransferTokenTransaction.create(token_txhash=token_transaction.txhash, - addrs_to=[alice_xmss.address], - amounts=[100000000], - fee=1, - xmss_pk=bob_xmss.pk) - transfer_token.sign(alice_xmss) - - self.state.update_token_metadata(transfer_token) - token_metadata = self.state.get_token_metadata(transfer_token.token_txhash) - self.assertIn(transfer_token.txhash, - token_metadata.transfer_token_tx_hashes) - - self.state.remove_transfer_token_metadata(transfer_token) - token_metadata = self.state.get_token_metadata(transfer_token.token_txhash) - self.assertNotIn(transfer_token.txhash, - token_metadata.transfer_token_tx_hashes) - - def test_remove_token_metadata(self): - alice_xmss = get_alice_xmss() - bob_xmss = get_bob_xmss() - - token_tx = get_token_transaction(alice_xmss, bob_xmss) - self.state.create_token_metadata(token_tx) - - token_metadata = self.state.get_token_metadata(token_tx.txhash) - self.assertEqual(token_metadata.token_txhash, token_tx.txhash) - self.state.remove_token_metadata(token_tx) - self.assertIsNone(self.state.get_token_metadata(token_tx.txhash)) - def test_address_used(self): alice_xmss = get_alice_xmss() - self.assertTrue(self.state.get_address_is_used(alice_xmss.address)) - - def test_return_all_addresses(self): - self.assertEqual(self.state._return_all_addresses(), []) + self.assertFalse(self.state.get_address_is_used(alice_xmss.address)) def test_get_batch(self): self.assertIsNotNone(self.state.batch) def test_write_batch(self): batch = self.state.batch - block = Block.create(block_number=10, + block = Block.create(dev_config=config.dev, + block_number=10, prev_headerhash=b'aa', prev_timestamp=10, transactions=[], - miner_address=b'aa') - self.state.put_block(block, batch) - self.assertIsNone(self.state.get_block(block.headerhash)) + miner_address=b'aa', + seed_height=0, + seed_hash=None) + Block.put_block(self.state, block, batch) + self.assertIsNone(Block.get_block(self.state, block.headerhash)) self.state.write_batch(batch) - block2 = self.state.get_block(block.headerhash) + block2 = Block.get_block(self.state, block.headerhash) self.assertEqual(block.headerhash, block2.headerhash) def test_update_total_coin_supply(self): self.assertEqual(self.state.total_coin_supply, 0) - self.state._update_total_coin_supply(100) + self.state._update_total_coin_supply(100, None) self.assertEqual(self.state.total_coin_supply, 100) def test_total_coin_supply(self): self.assertEqual(self.state.total_coin_supply, 0) - def test_get_measurement(self): - def block(headerhash): - nth_block = Block() - if headerhash == b'test_block_1': - nth_block.blockheader._data.timestamp_seconds = 50000 - elif headerhash == b'test_block_2': - nth_block.blockheader._data.timestamp_seconds = 80000 - elif headerhash == b'test_block_3': - nth_block.blockheader._data.timestamp_seconds = 90000 - return nth_block - - parent_metadata = BlockMetadata.create(block_difficulty=b'\x00' * 32, - cumulative_difficulty=b'\x00' * 32, - child_headerhashes=[]) - - measurement = self.state.get_measurement(block_timestamp=100000, - parent_headerhash=b'', - parent_metadata=parent_metadata) - - # Test Case, when count_headerhashes equals 0 - self.assertEqual(measurement, config.dev.mining_setpoint_blocktime) - - self.state.get_block = MagicMock(side_effect=block) - parent_metadata.update_last_headerhashes([], b'test_block_1') - - measurement = self.state.get_measurement(block_timestamp=100000, - parent_headerhash=b'test_block_1', - parent_metadata=parent_metadata) - - # Test Case, when count_headerhashes equals 1 - self.assertEqual(measurement, - (100000 - 50000 + config.dev.mining_setpoint_blocktime) // 2) - - parent_metadata.update_last_headerhashes([b'test_block_1'], b'test_block_2') - - measurement = self.state.get_measurement(block_timestamp=100000, - parent_headerhash=b'test_block_2', - parent_metadata=parent_metadata) - - # Test Case, when count_headerhashes is greater than 1 - # but less than config.dev.N_measurement - self.assertEqual(measurement, - (100000 - 80000 + config.dev.mining_setpoint_blocktime) // 2) - - parent_metadata.update_last_headerhashes([b'test_block_3'] * config.dev.N_measurement, - b'test_block_2') - - measurement = self.state.get_measurement(block_timestamp=100000, - parent_headerhash=b'test_block_2', - parent_metadata=parent_metadata) - - # Test Case, when count_headerhashes is greater than config.dev.N_measurement - self.assertEqual(measurement, - (100000 - 90000) // config.dev.N_measurement) - def test_delete(self): block = Block() - self.state.put_block(block, None) - block1 = self.state.get_block(block.headerhash) + Block.put_block(self.state, block, None) + block1 = Block.get_block(self.state, block.headerhash) self.assertEqual(block.serialize(), block1.serialize()) self.state._delete(block.headerhash, None) - self.assertIsNone(self.state.get_block(block.headerhash)) + self.assertIsNone(Block.get_block(self.state, block.headerhash)) def test_get_block_size_limit(self): alice_xmss = get_alice_xmss() blocks = gen_blocks(20, self.state, alice_xmss.address) - self.assertEqual(self.state.get_block_size_limit(blocks[-1]), 1048576) + self.assertEqual(Block.get_block_size_limit(self.state, blocks[-1], config.dev), 1048576) # get_block_size_limit() should return None if it couldn't get any blocks from db - with patch('qrl.core.State.State.get_block', return_value=None): - self.assertIsNone(self.state.get_block_size_limit(blocks[-1])) - - def test_put_block_metadata(self): - block_metadata = BlockMetadata.create() - block_metadata.update_last_headerhashes([b'test1', b'test2'], b'test3') - - self.state.put_block_metadata(b'block_headerhash', block_metadata, None) - self.state.put_block_metadata(b'block_headerhash2', BlockMetadata.create(), None) - - self.assertEqual(self.state.get_block_metadata(b'block_headerhash').to_json(), - block_metadata.to_json()) - - expected_json = b'{\n "blockDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n ' \ - b'"cumulativeDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n}' - - self.assertEqual(self.state.get_block_metadata(b'block_headerhash2').to_json(), - expected_json) - - def test_get_block_metadata(self): - self.assertIsNone(self.state.get_block_metadata(b'test1')) - self.state.put_block_metadata(b'block_headerhash2', BlockMetadata.create(), None) - - tmp_json = self.state.get_block_metadata(b'block_headerhash2').to_json() - - expected_json = b'{\n "blockDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n ' \ - b'"cumulativeDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n}' - - self.assertEqual(tmp_json, expected_json) - - def test_prepare_address_list(self): - block = Block.create(block_number=10, - prev_headerhash=b'', - prev_timestamp=10, - transactions=[], - miner_address=get_some_address(1)) - # Test Case: without any transactions of block - self.assertEqual(self.state.prepare_address_list(block), - {config.dev.coinbase_address, get_some_address(1)}) - - alice_xmss = get_alice_xmss() - block = Block.create(block_number=10, - prev_headerhash=b'', - prev_timestamp=10, - transactions=[TransferTransaction.create(addrs_to=[get_some_address(2), - get_some_address(3)], - amounts=[100, 100], - fee=0, - xmss_pk=alice_xmss.pk)], - miner_address=get_some_address(1)) - - # Test Case, with one Transaction - self.assertEqual(self.state.prepare_address_list(block), - {config.dev.coinbase_address, - get_some_address(1), - get_some_address(2), - get_some_address(3), - alice_xmss.address}) - - def test_put_addresses_state(self): - alice_xmss = get_alice_xmss() - alice_state = AddressState.get_default(alice_xmss.address) - addresses_state = { - alice_state.address: alice_state, - b'test1': AddressState.get_default(b'test1') - } - self.state.put_addresses_state(addresses_state, None) - alice_state2 = self.state.get_address_state(alice_xmss.address) - self.assertEqual(alice_state.serialize(), alice_state2.serialize()) - test_state = self.state.get_address_state(b'test1') - self.assertEqual(test_state.serialize(), AddressState.get_default(b'test1').serialize()) - - def test_get_state_mainchain(self): - alice_xmss = get_alice_xmss() - alice_state = AddressState.get_default(alice_xmss.address) - alice_state.increase_nonce() - alice_state.balance += 1000 - addresses_state = { - alice_state.address: alice_state, - b'test1': AddressState.get_default(b'test1') - } - self.state.put_addresses_state(addresses_state, None) - addresses_state1 = self.state.get_state_mainchain({alice_state.address, b'test1'}) - - self.assertEqual(addresses_state[alice_state.address].serialize(), - addresses_state1[alice_state.address].serialize()) - self.assertEqual(addresses_state[b'test1'].serialize(), - addresses_state1[b'test1'].serialize()) - - def test_get_block_datapoint(self): - # Test Case: When block not found - self.assertIsNone(self.state.get_block_datapoint(b'test')) - - alice_xmss = get_alice_xmss() - blocks = gen_blocks(20, self.state, alice_xmss.address) - for i in range(1, 20): - datapoint = self.state.get_block_datapoint(blocks[i].headerhash) - self.assertEqual(datapoint.difficulty, "256") - self.assertEqual(datapoint.timestamp, 1615270947 + i) - self.assertEqual(datapoint.header_hash, blocks[i].headerhash) - self.assertEqual(datapoint.header_hash_prev, blocks[i - 1].headerhash) - - def test_put_block_number_mapping(self): - bm = qrl_pb2.BlockNumberMapping() - self.state.put_block_number_mapping(0, bm, None) - read_bm = self.state.get_block_number_mapping(0) - self.assertEqual(bm.SerializeToString(), - read_bm.SerializeToString()) - self.assertIsNone(self.state.get_block_by_number(4)) - - def test_get_block_number_mapping(self): - self.assertIsNone(self.state.get_block_number_mapping(0)) - bm = qrl_pb2.BlockNumberMapping() - self.state.put_block_number_mapping(0, bm, None) - read_bm = self.state.get_block_number_mapping(0) - self.assertEqual(bm.SerializeToString(), - read_bm.SerializeToString()) - - def test_get_block_by_number(self): - bm = qrl_pb2.BlockNumberMapping() - self.state.put_block_number_mapping(0, bm, None) - self.assertIsNone(self.state.get_block_by_number(4)) + with patch('qrl.core.Block.Block.get_block', return_value=None): + self.assertIsNone(Block.get_block_size_limit(self.state, blocks[-1], config.dev)) def test_update_mainchain_height(self): self.state.update_mainchain_height(5, None) @@ -477,209 +97,6 @@ def test_get_mainchain_height(self): self.state.update_mainchain_height(5, None) self.assertEqual(self.state.get_mainchain_height(), 5) - def test_last_block(self): - def get_block_by_number(block_number): - block = Block() - block.blockheader._data.block_number = block_number - return block - - self.assertIsNone(self.state.last_block) - self.state.get_block_by_number = MagicMock(side_effect=get_block_by_number) - - self.state.update_mainchain_height(10, None) - self.assertEqual(self.state.last_block.block_number, 10) - - self.state.update_mainchain_height(1, None) - self.assertEqual(self.state.last_block.block_number, 1) - - def test_update_last_tx(self): - alice_xmss = get_alice_xmss() - # Test Case: When there is no last txns - self.assertEqual(self.state.get_last_txs(), []) - - block = Block() - tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block._data.transactions.extend([tx1.pbdata]) - self.state._update_last_tx(block, None) - last_txns = self.state.get_last_txs() - - # Test Case: When there is only 1 last txns - self.assertEqual(len(last_txns), 1) - self.assertEqual(last_txns[0].to_json(), tx1.to_json()) - - block = Block() - tx2 = TransferTransaction.create(addrs_to=[get_some_address(2), get_some_address(3)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - - tx3 = TransferTransaction.create(addrs_to=[get_some_address(4), get_some_address(5)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block._data.transactions.extend([tx2.pbdata, tx3.pbdata]) - self.state._update_last_tx(block, None) - last_txns = self.state.get_last_txs() - - # Test Case: When there are 3 last txns - self.assertEqual(len(last_txns), 3) - self.assertEqual(last_txns[0].to_json(), - tx3.to_json()) - self.assertEqual(last_txns[1].to_json(), - tx2.to_json()) - self.assertEqual(last_txns[2].to_json(), - tx1.to_json()) - - def test_get_last_txs(self): - self.assertEqual(self.state.get_last_txs(), []) - - alice_xmss = get_alice_xmss() - block = Block() - tx1 = TransferTransaction.create(addrs_to=[get_some_address(0), get_some_address(1)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block._data.transactions.extend([tx1.pbdata]) - self.state._update_last_tx(block, None) - last_txns = self.state.get_last_txs() - - # Test Case: When there is only 1 last txns - self.assertEqual(len(last_txns), 1) - self.assertEqual(last_txns[0].to_json(), tx1.to_json()) - - def test_remove_last_tx(self): - # Test Case: When there is no last txns - self.assertEqual(self.state.get_last_txs(), []) - - alice_xmss = get_alice_xmss() - - block = Block() - tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block._data.transactions.extend([tx1.pbdata]) - self.state._update_last_tx(block, None) - last_txns = self.state.get_last_txs() - - self.assertEqual(last_txns[0].to_json(), tx1.to_json()) - - self.state._remove_last_tx(block, None) - last_txns = self.state.get_last_txs() - self.assertEqual(last_txns, []) - - def test_rollback_tx_metadata(self): - alice_xmss = get_alice_xmss() - - tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - - block = Block.create(block_number=5, - prev_headerhash=b'', - prev_timestamp=10, - transactions=[tx1], - miner_address=b'') - - self.state.update_tx_metadata(block=block, - batch=None) - - tx_metadata = self.state.get_tx_metadata(tx1.txhash) - - self.assertEqual(tx_metadata[0].to_json(), tx1.to_json()) - self.state.rollback_tx_metadata(block, None) - self.assertIsNone(self.state.get_tx_metadata(tx1.txhash)) - - def test_update_tx_metadata(self): - alice_xmss = get_alice_xmss() - tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block_number = 5 - self.state.put_tx_metadata(tx, block_number, 10000, None) - - tx_metadata = self.state.get_tx_metadata(tx.txhash) - self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) - self.assertEqual(tx_metadata[1], block_number) - - def test_remove_tx_metadata(self): - self.assertIsNone(self.state.get_tx_metadata(b'test1')) - - alice_xmss = get_alice_xmss() - tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block_number = 5 - self.state.put_tx_metadata(tx, block_number, 10000, None) - - tx_metadata = self.state.get_tx_metadata(tx.txhash) - self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) - self.assertEqual(tx_metadata[1], block_number) - - self.state.remove_tx_metadata(tx, None) - self.assertIsNone(self.state.get_tx_metadata(tx.txhash)) - - def test_put_tx_metadata(self): - self.assertIsNone(self.state.get_tx_metadata(b'test1')) - - alice_xmss = get_alice_xmss() - tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block_number = 5 - self.state.put_tx_metadata(tx, block_number, 10000, None) - - tx_metadata = self.state.get_tx_metadata(tx.txhash) - self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) - self.assertEqual(tx_metadata[1], block_number) - - def test_get_tx_metadata(self): - self.assertIsNone(self.state.get_tx_metadata(b'test1')) - - alice_xmss = get_alice_xmss() - tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], - amounts=[1, 2], - fee=0, - xmss_pk=alice_xmss.pk) - block_number = 5 - timestamp = 10000 - self.state.put_tx_metadata(tx, block_number, timestamp, None) - - tx_metadata = self.state.get_tx_metadata(tx.txhash) - self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) - self.assertEqual(tx_metadata[1], block_number) - - def test_increase_txn_count(self): - self.assertEqual(self.state.get_txn_count(b'q1'), 0) - - self.state._increase_txn_count(0, b'q1') - self.assertEqual(self.state.get_txn_count(b'q1'), 1) - - self.state._increase_txn_count(5, b'q1') - self.assertEqual(self.state.get_txn_count(b'q1'), 6) - - def test_decrease_txn_count(self): - self.assertEqual(self.state.get_txn_count(b'q1'), 0) - - with self.assertRaises(ValueError): - self.state._decrease_txn_count(0, b'q1') - - self.state._decrease_txn_count(5, b'q1') - self.assertEqual(self.state.get_txn_count(b'q1'), 4) - - def test_get_txn_count(self): - self.assertEqual(self.state.get_txn_count(b'q1'), 0) - - self.state._increase_txn_count(10, b'q1') - self.assertEqual(self.state.get_txn_count(b'q1'), 11) - def test_fork_state(self): fork_state = qrlstateinfo_pb2.ForkState( initiator_headerhash=b'block2_right', diff --git a/tests/core/test_State_Measurements.py b/tests/core/test_State_Measurements.py index 3dff49c65..c96eb5adb 100644 --- a/tests/core/test_State_Measurements.py +++ b/tests/core/test_State_Measurements.py @@ -3,10 +3,11 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from unittest import TestCase -from mock import Mock, mock +from mock import Mock, mock, patch from qrl.core import config from qrl.core.State import State +from qrl.core.ChainManager import ChainManager from qrl.core.misc import logger from tests.misc.helper import set_qrl_dir @@ -51,7 +52,7 @@ def get_block_list_example1(): ] @staticmethod - def get_block_example1(header_hash): + def get_block_example1(state, header_hash): block_list = TestStateMeasurement.get_block_list_example1() for b in block_list: if b.headerhash == header_hash: @@ -73,57 +74,67 @@ def test_check_mock(self): self.assertEqual(0, block.block_number) self.assertEqual(b'0', block.headerhash) - def test_check_mock_get(self): + @patch('qrl.core.Block.Block.get_block') + def test_check_mock_get(self, mock_get_block): with set_qrl_dir('no_data'): with State() as state: self.assertIsNotNone(state) # to avoid warning (unused variable) - state.get_block = Mock(side_effect=TestStateMeasurement.get_block_example1) + chain_manager = ChainManager(state) + mock_get_block.side_effect = TestStateMeasurement.get_block_example1 - block = state.get_block(b'1') + block = chain_manager.get_block(b'1') self.assertEqual(1, block.block_number) self.assertEqual(160, block.timestamp) - block = state.get_block(b'3') + block = chain_manager.get_block(b'3') self.assertEqual(3, block.block_number) self.assertEqual(310, block.timestamp) - block = state.get_block(b'0') + block = chain_manager.get_block(b'0') self.assertEqual(0, block.block_number) self.assertEqual(10, block.timestamp) - def test_measurement_0(self): + @patch('qrl.core.Block.Block.get_block') + def test_measurement_0(self, mock_get_block): with set_qrl_dir('no_data'): with State() as state: self.assertIsNotNone(state) # to avoid warning (unused variable) - state.get_block = Mock(side_effect=TestStateMeasurement.get_block_example1) + chain_manager = ChainManager(state) + mock_get_block.side_effect = TestStateMeasurement.get_block_example1 parent_metadata = Mock() parent_metadata.last_N_headerhashes = [] - measurement = state.get_measurement(100, parent_headerhash=b'0', parent_metadata=parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 100, + parent_headerhash=b'0', parent_metadata=parent_metadata) self.assertEqual(60, measurement) - measurement = state.get_measurement(110, parent_headerhash=b'0', parent_metadata=parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 110, + parent_headerhash=b'0', parent_metadata=parent_metadata) self.assertEqual(60, measurement) - measurement = state.get_measurement(1000, parent_headerhash=b'0', parent_metadata=parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 1000, + parent_headerhash=b'0', parent_metadata=parent_metadata) self.assertEqual(60, measurement) - def test_measurement_1(self): + @patch('qrl.core.Block.Block.get_block') + def test_measurement_1(self, mock_get_block): with set_qrl_dir('no_data'): with State() as state: self.assertIsNotNone(state) # to avoid warning (unused variable) - state.get_block = Mock(side_effect=TestStateMeasurement.get_block_example1) + chain_manager = ChainManager(state) + mock_get_block.side_effect = TestStateMeasurement.get_block_example1 parent_metadata = Mock() parent_metadata.last_N_headerhashes = [b'0'] - measurement = state.get_measurement(210, b'1', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 210, b'1', parent_metadata) self.assertEqual(55, measurement) - measurement = state.get_measurement(250, b'1', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 250, b'1', parent_metadata) self.assertEqual(75, measurement) - def test_measurement_3(self): + @patch('qrl.core.Block.Block.get_block') + def test_measurement_3(self, mock_get_block): db_name = config.dev.db_name with mock.patch('qrl.core.config.dev') as devconfig: devconfig.N_measurement = 2 @@ -131,17 +142,19 @@ def test_measurement_3(self): with set_qrl_dir('no_data'): with State() as state: self.assertIsNotNone(state) # to avoid warning (unused variable) - state.get_block = Mock(side_effect=TestStateMeasurement.get_block_example1) + chain_manager = ChainManager(state) + mock_get_block.side_effect = TestStateMeasurement.get_block_example1 parent_metadata = Mock() parent_metadata.last_N_headerhashes = [b'1', b'2'] - measurement = state.get_measurement(350, b'3', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 350, b'3', parent_metadata) self.assertEqual(60, measurement) - measurement = state.get_measurement(370, b'3', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 370, b'3', parent_metadata) self.assertEqual(70, measurement) - def test_measurement_4(self): + @patch('qrl.core.Block.Block.get_block') + def test_measurement_4(self, mock_get_block): db_name = config.dev.db_name with mock.patch('qrl.core.config.dev') as devconfig: devconfig.N_measurement = 3 @@ -149,12 +162,13 @@ def test_measurement_4(self): with set_qrl_dir('no_data'): with State() as state: self.assertIsNotNone(state) # to avoid warning (unused variable) - state.get_block = Mock(side_effect=TestStateMeasurement.get_block_example1) + chain_manager = ChainManager(state) + mock_get_block.side_effect = TestStateMeasurement.get_block_example1 parent_metadata = Mock() parent_metadata.last_N_headerhashes = [b'0', b'1', b'2'] - measurement = state.get_measurement(350, b'3', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 350, b'3', parent_metadata) self.assertEqual(63, measurement) - measurement = state.get_measurement(370, b'3', parent_metadata) + measurement = chain_manager.get_measurement(config.dev, 370, b'3', parent_metadata) self.assertEqual(70, measurement) diff --git a/tests/core/test_TokenMetadata.py b/tests/core/test_TokenMetadata.py new file mode 100644 index 000000000..f397edace --- /dev/null +++ b/tests/core/test_TokenMetadata.py @@ -0,0 +1,101 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from mock import MagicMock +from unittest import TestCase +from pyqrllib.pyqrllib import sha2_256 + +from tests.misc.helper import get_slave_xmss +from qrl.core.misc import logger +from qrl.core.State import State +from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction +from qrl.core.TokenMetadata import TokenMetadata + +from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_bob_xmss, get_token_transaction + +logger.initialize_default() + +alice = get_alice_xmss() +slave = get_slave_xmss() + + +class TestTokenMetadata(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + + def test_create_token_metadata(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + + token_transaction = get_token_transaction(alice_xmss, bob_xmss) + TokenMetadata.create_token_metadata(self.state, token_transaction, None) + + token_metadata = TokenMetadata.get_token_metadata(self.state, token_transaction.txhash) + self.assertEqual(token_metadata.token_txhash, token_transaction.txhash) + self.assertEqual(token_metadata.transfer_token_tx_hashes[0], token_transaction.txhash) + + def test_update_token_metadata(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + + token_transaction = get_token_transaction(alice_xmss, bob_xmss) + TokenMetadata.create_token_metadata(self.state, token_transaction, None) + + transfer_token_transaction = TransferTokenTransaction.create(token_txhash=token_transaction.txhash, + addrs_to=[alice_xmss.address], + amounts=[100000000], + fee=1, + xmss_pk=bob_xmss.pk) + + TokenMetadata.update_token_metadata(self.state, transfer_token_transaction, None) + + token_metadata = TokenMetadata.get_token_metadata(self.state, token_transaction.txhash) + self.assertEqual(len(token_metadata.transfer_token_tx_hashes), 2) + self.assertEqual(token_metadata.transfer_token_tx_hashes[0], token_transaction.txhash) + self.assertEqual(token_metadata.transfer_token_tx_hashes[1], transfer_token_transaction.txhash) + + def test_get_token_metadata(self): + token_txhash = bytes(sha2_256(b'alpha')) + token_metadata = TokenMetadata.create(token_txhash, + [bytes(sha2_256(b'delta')), + bytes(sha2_256(b'gamma'))]) + self.state._db.get_raw = MagicMock(return_value=token_metadata.serialize()) + self.assertEqual(TokenMetadata.get_token_metadata(self.state, token_txhash).to_json(), + token_metadata.to_json()) + + def test_remove_transfer_token_metadata(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + + token_transaction = get_token_transaction(alice_xmss, bob_xmss) + TokenMetadata.create_token_metadata(self.state, token_transaction, None) + + transfer_token = TransferTokenTransaction.create(token_txhash=token_transaction.txhash, + addrs_to=[alice_xmss.address], + amounts=[100000000], + fee=1, + xmss_pk=bob_xmss.pk) + transfer_token.sign(alice_xmss) + + TokenMetadata.update_token_metadata(self.state, transfer_token, None) + token_metadata = TokenMetadata.get_token_metadata(self.state, transfer_token.token_txhash) + self.assertIn(transfer_token.txhash, + token_metadata.transfer_token_tx_hashes) + + TokenMetadata.remove_transfer_token_metadata(self.state, transfer_token, None) + token_metadata = TokenMetadata.get_token_metadata(self.state, transfer_token.token_txhash) + self.assertNotIn(transfer_token.txhash, + token_metadata.transfer_token_tx_hashes) + + def test_remove_token_metadata(self): + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + + token_tx = get_token_transaction(alice_xmss, bob_xmss) + TokenMetadata.create_token_metadata(self.state, token_tx, None) + + token_metadata = TokenMetadata.get_token_metadata(self.state, token_tx.txhash) + self.assertEqual(token_metadata.token_txhash, token_tx.txhash) + TokenMetadata.remove_token_metadata(self.state, token_tx, None) + self.assertIsNone(TokenMetadata.get_token_metadata(self.state, token_tx.txhash)) diff --git a/tests/core/test_TransactionMetadata.py b/tests/core/test_TransactionMetadata.py new file mode 100644 index 000000000..32f229add --- /dev/null +++ b/tests/core/test_TransactionMetadata.py @@ -0,0 +1,115 @@ +# coding=utf-8 +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from unittest import TestCase +from mock import MagicMock + +from qrl.core import config +from qrl.core.TransactionMetadata import TransactionMetadata +from qrl.core.misc import logger, db +from qrl.core.State import State +from qrl.core.txs.TransferTransaction import TransferTransaction +from qrl.core.Block import Block + +from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_some_address + +logger.initialize_default() + + +class TestTransactionMetadata(TestCase): + def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.m_db = MagicMock(name='mock DB', autospec=db.DB) + + def test_rollback_tx_metadata(self): + alice_xmss = get_alice_xmss() + + tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + + block = Block.create(dev_config=config.dev, + block_number=5, + prev_headerhash=b'', + prev_timestamp=10, + transactions=[tx1], + miner_address=b'', + seed_height=0, + seed_hash=None) + + TransactionMetadata.update_tx_metadata(self.state, block=block, batch=None) + + tx_metadata = TransactionMetadata.get_tx_metadata(self.state, tx1.txhash) + + self.assertEqual(tx_metadata[0].to_json(), tx1.to_json()) + TransactionMetadata.rollback_tx_metadata(self.state, block, None) + self.assertIsNone(TransactionMetadata.get_tx_metadata(self.state, tx1.txhash)) + + def test_update_tx_metadata(self): + alice_xmss = get_alice_xmss() + tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block_number = 5 + TransactionMetadata.put_tx_metadata(self.state, tx, block_number, 10000, None) + + tx_metadata = TransactionMetadata.get_tx_metadata(self.state, tx.txhash) + self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) + self.assertEqual(tx_metadata[1], block_number) + + def test_remove_tx_metadata(self): + self.assertIsNone(TransactionMetadata.get_tx_metadata(self.state, b'test1')) + + alice_xmss = get_alice_xmss() + tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block_number = 5 + TransactionMetadata.put_tx_metadata(self.state, tx, block_number, 10000, None) + + tx_metadata = TransactionMetadata.get_tx_metadata(self.state, tx.txhash) + self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) + self.assertEqual(tx_metadata[1], block_number) + + TransactionMetadata.remove_tx_metadata(self.state, tx, None) + self.assertIsNone(TransactionMetadata.get_tx_metadata(self.state, tx.txhash)) + + def test_put_tx_metadata(self): + self.assertIsNone(TransactionMetadata.get_tx_metadata(self.state, b'test1')) + + alice_xmss = get_alice_xmss() + tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block_number = 5 + TransactionMetadata.put_tx_metadata(self.state, tx, block_number, 10000, None) + + tx_metadata = TransactionMetadata.get_tx_metadata(self.state, tx.txhash) + self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) + self.assertEqual(tx_metadata[1], block_number) + + def test_get_tx_metadata(self): + self.assertIsNone(TransactionMetadata.get_tx_metadata(self.state, b'test1')) + + alice_xmss = get_alice_xmss() + tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], + amounts=[1, 2], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + block_number = 5 + timestamp = 10000 + TransactionMetadata.put_tx_metadata(self.state, tx, block_number, timestamp, None) + + tx_metadata = TransactionMetadata.get_tx_metadata(self.state, tx.txhash) + self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) + self.assertEqual(tx_metadata[1], block_number) diff --git a/tests/core/test_TransactionPool.py b/tests/core/test_TransactionPool.py index e87eb13e3..93d6fb346 100644 --- a/tests/core/test_TransactionPool.py +++ b/tests/core/test_TransactionPool.py @@ -4,18 +4,16 @@ from unittest import TestCase from mock import Mock, patch -from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.Block import Block from qrl.core.State import State +from qrl.core.ChainManager import ChainManager from qrl.core.txs.CoinBase import CoinBase from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.TransactionPool import TransactionPool from tests.misc.helper import replacement_getTime, set_qrl_dir, get_alice_xmss, get_bob_xmss from tests.misc.MockHelper.mock_function import MockFunction -logger.initialize_default() - def make_tx(txhash=b'hashbrownies', fee=1, autospec=TransferTransaction, PK=b'publickey', **kwargs): return Mock(autospec=autospec, txhash=txhash, fee=fee, PK=PK, **kwargs) @@ -245,9 +243,11 @@ def test_check_stale_txn(self, m_is_full_transaction_pool, m_config): bob_xmss = get_bob_xmss(4) alice_xmss = get_alice_xmss(4) - tx1 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[1000000], fee=1, xmss_pk=alice_xmss.pk) + tx1 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[1000000], + message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx1.sign(alice_xmss) - tx2 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[10000], fee=1, xmss_pk=alice_xmss.pk) + tx2 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[10000], + message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx2.sign(alice_xmss) m_broadcast_tx = Mock(name='Mock Broadcast TX function (in P2PFactory)') self.txpool.add_tx_to_pool(tx1, 5) @@ -256,20 +256,21 @@ def test_check_stale_txn(self, m_is_full_transaction_pool, m_config): with set_qrl_dir('no_data'): state = State() - self.txpool.check_stale_txn(state, 8) + chain_manager = ChainManager(state) + self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 0) m = MockFunction() - bob_address_state = AddressState.get_default(bob_xmss.address) + bob_address_state = OptimizedAddressState.get_default(bob_xmss.address) bob_address_state.pbdata.balance = 1000000000000 m.put(bob_xmss.address, bob_address_state) - state.get_address_state = m.get - tx3 = TransferTransaction.create(addrs_to=[alice_xmss.address], amounts=[10000], fee=1, - xmss_pk=bob_xmss.pk) + chain_manager.get_optimized_address_state = m.get + tx3 = TransferTransaction.create(addrs_to=[alice_xmss.address], amounts=[10000], + message_data=None, fee=1, xmss_pk=bob_xmss.pk) tx3.sign(bob_xmss) self.txpool.add_tx_to_pool(tx3, 5) - self.txpool.check_stale_txn(state, 8) + self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 1) diff --git a/tests/core/test_VoteStats.py b/tests/core/test_VoteStats.py new file mode 100644 index 000000000..73ab3c1e3 --- /dev/null +++ b/tests/core/test_VoteStats.py @@ -0,0 +1,920 @@ +from unittest import TestCase + +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.VoteStats import VoteStats +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_qrl_dir + +logger.initialize_default() + + +class TestVoteStats(TestCase): + def setUp(self) -> None: + with set_qrl_dir('no_data'): + self.state = State() + + self.alice = get_alice_xmss() + self.bob = get_bob_xmss() + self.random = get_alice_xmss(4) + self.random_signer = get_bob_xmss(4) + self.signatories = [self.alice.address, self.bob.address, self.random.address] + self.weights = [20, 30, 10] + self.threshold = 30 + + def test_apply_and_put(self): + """ + Test execution of multisig spend txn, when threshold is not met. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put(self): + """ + Test execution of multisig spend txn, when threshold is not met and then reverting the txn. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx.revert(self.state, state_container) + + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_apply_and_put2(self): + """ + Test execution of multi sig txn, when threshold is met. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=4, + xmss_pk=self.bob.pk) + tx2.sign(self.bob) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + bob_address_state = OptimizedAddressState.get_default(address=self.bob.address) + bob_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + tx2.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + # Expected balance is 1, as 4 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 1) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put2(self): + """ + Test execution of multi sig txn, when threshold is met and then reverting the txn. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=4, + xmss_pk=self.bob.pk) + tx2.sign(self.bob) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + bob_address_state = OptimizedAddressState.get_default(address=self.bob.address) + bob_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + tx2.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + # Expected balance is 1, as 4 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 1) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx1.revert(self.state, state_container) + tx2.revert(self.state, state_container) + + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 5) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_apply_and_put3(self): + """ + Test execution of multisig spend txn, when threshold is met by a single txn. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put3(self): + """ + Test execution of multisig spend txn, when threshold is met by a single txn and then reverting the txn. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx.revert(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_apply_and_put4(self): + """ + Test execution of multisig spend txn, when threshold is met but multi_sig address doesn't have + sufficient balance. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=90, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + # Expected balance is 90, as multi_sig_spend txn is not executed due to insufficient balance + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put4(self): + """ + Test execution of multisig spend txn, when threshold is met but multi_sig address doesn't have + sufficient balance and then reverting the txn. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=90, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + # Expected balance is 90, as multi_sig_spend txn is not executed due to insufficient balance + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx.revert(self.state, state_container) + + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_apply_and_put5(self): + """ + Test execution of multisig spend txn, when threshold is met but multi_sig address doesn't have + sufficient balance, later somehow multi sig address gets sufficient balance, before expiry. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=90, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + # Expected balance is 90, as multi_sig_spend txn is not executed due to insufficient balance + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + multi_sig_address_state.pbdata.balance = 100 + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=True, + fee=0, + xmss_pk=self.alice.pk) + tx2.sign(self.alice) + + tx2.apply(self.state, state_container) + VoteStats.put_all(self.state, state_container) + # Expected balance is 100 + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + tx3 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=0, + xmss_pk=self.alice.pk) + tx3.sign(self.alice) + tx3.apply(self.state, state_container) + VoteStats.put_all(self.state, state_container) + # Expected balance is 0, as multi_sig_spend txn has been executed + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put5(self): + """ + Test execution of multisig spend txn, when threshold is met but multi_sig address doesn't have + sufficient balance, later somehow multi sig address gets sufficient balance, before expiry. + Then fork recovery is called. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=90, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=4, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + # Expected balance is 90, as multi_sig_spend txn is not executed due to insufficient balance + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + # Expected balance is 0, as 5 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + multi_sig_address_state.pbdata.balance = 100 + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=True, + fee=0, + xmss_pk=self.alice.pk) + tx2.sign(self.alice) + + tx2.apply(self.state, state_container) + VoteStats.put_all(self.state, state_container) + # Expected balance is 100 + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + tx3 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=0, + xmss_pk=self.alice.pk) + tx3.sign(self.alice) + tx3.apply(self.state, state_container) + VoteStats.put_all(self.state, state_container) + # Expected balance is 0, as multi_sig_spend txn has been executed + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 0) + # Expected balance is 100, as 5 quanta paid in MultiSigVote txn as a fee + # and 100 quanta received by multi sig spend txn + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 100) + self.assertTrue(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx3.revert(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + multi_sig_address_state.pbdata.balance = 90 + + VoteStats.revert_all(self.state, state_container) + tx2.revert(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + + VoteStats.revert_all(self.state, state_container) + tx1.revert(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 90) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + + def test_apply_and_put6(self): + """ + Test execution of multi sig txn, when threshold is met but after the block expiry. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=4, + xmss_pk=self.bob.pk) + tx2.sign(self.bob) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + bob_address_state = OptimizedAddressState.get_default(address=self.bob.address) + bob_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=15001, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + tx2.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + # Expected balance is 1, as 4 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 1) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + def test_revert_and_put6(self): + """ + Test execution of multi sig txn, when threshold is met but after the block expiry. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx1 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx1.sign(self.alice) + + tx2 = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=4, + xmss_pk=self.bob.pk) + tx2.sign(self.bob) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + bob_address_state = OptimizedAddressState.get_default(address=self.bob.address) + bob_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', self.state._db), + slaves=Indexer(b'slave', self.state._db), + lattice_pk=Indexer(b'lattice_pk', self.state._db), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=15001, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx1.apply(self.state, state_container) + tx2.apply(self.state, state_container) + + VoteStats.put_all(self.state, state_container) + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 0) + # Expected balance is 1, as 4 quanta paid in MultiSigVote txn as a fee + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 1) + self.assertFalse(vote_stats[spend_tx.txhash].executed) + + VoteStats.revert_all(self.state, state_container) + tx2.revert(self.state, state_container) + tx1.revert(self.state, state_container) + + self.assertEqual(state_container.addresses_state[multi_sig_address].balance, 100) + self.assertEqual(state_container.addresses_state[self.alice.address].balance, 5) + self.assertEqual(state_container.addresses_state[self.bob.address].balance, 5) + self.assertFalse(vote_stats[spend_tx.txhash].executed) diff --git a/tests/core/test_block.py b/tests/core/test_block.py index 0ceafab08..e6e05b5c6 100644 --- a/tests/core/test_block.py +++ b/tests/core/test_block.py @@ -2,13 +2,16 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from unittest import TestCase -from mock import patch, Mock, PropertyMock +from mock import patch, Mock, PropertyMock, MagicMock from pyqrllib.pyqrllib import sha2_256 from collections import OrderedDict from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss from qrl.core import config -from qrl.core.AddressState import AddressState +from qrl.generated import qrl_pb2 +from qrl.core.State import State +from qrl.core.ChainManager import ChainManager +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.Block import Block from qrl.core.BlockHeader import BlockHeader from qrl.core.txs.Transaction import Transaction @@ -16,7 +19,8 @@ from qrl.core.txs.CoinBase import CoinBase from qrl.crypto.misc import merkle_tx_hash -from tests.misc.helper import replacement_getTime +from tests.misc.helper import replacement_getTime, set_qrl_dir +from tests.misc.MockHelper.mock_function import MockFunction alice = get_alice_xmss() bob = get_bob_xmss() @@ -27,14 +31,17 @@ class TestBlockReal(TestCase): # These tests rely on a real BlockHeader def setUp(self): - self.block = Block.create(block_number=5, + self.block = Block.create(dev_config=config.dev, + block_number=5, prev_headerhash=bytes(sha2_256(b'test')), prev_timestamp=10, transactions=[], - miner_address=alice.address) + miner_address=alice.address, + seed_height=0, + seed_hash=None) def test_update_mining_address(self): - self.block.update_mining_address(mining_address=bob.address) + self.block.update_mining_address(dev_config=config.dev, mining_address=bob.address) coinbase_tx = Transaction.from_pbdata(self.block.transactions[0]) self.assertTrue(isinstance(coinbase_tx, CoinBase)) self.assertEqual(coinbase_tx.addr_to, bob.address) @@ -44,10 +51,10 @@ def test_update_mining_address(self): self.assertEqual(self.block.blockheader.tx_merkle_root, merkle_tx_hash(hashedtransactions)) def test_mining_blob(self): - self.block.set_nonces(mining_nonce=5, extra_nonce=4) + self.block.set_nonces(dev_config=config.dev, mining_nonce=5, extra_nonce=4) - mining_blob = self.block.mining_blob - self.assertEqual(len(mining_blob), config.dev.mining_blob_size) + mining_blob = self.block.mining_blob(config.dev) + self.assertEqual(len(mining_blob), config.dev.mining_blob_size_in_bytes) mining_nonce_bytes = mining_blob[config.dev.mining_nonce_offset:config.dev.mining_nonce_offset + 4] extra_nonce_bytes = mining_blob[config.dev.extra_nonce_offset:config.dev.extra_nonce_offset + 8] @@ -70,32 +77,31 @@ def setUp(self): headerhash=bytes(sha2_256(b'mock headerhash')), prev_headerhash=bytes(sha2_256(b'test'))) - self.block = Block.create(block_number=5, + self.block = Block.create(dev_config=config.dev, + block_number=5, prev_headerhash=bytes(sha2_256(b'test')), prev_timestamp=10, transactions=[], - miner_address=alice.address) + miner_address=alice.address, + seed_height=0, + seed_hash=None) self.block.blockheader = self.blockheader def test_set_mining_nonce_from_blob(self): current_mining_nonce = self.block.mining_nonce current_headerhash = self.block.headerhash - mining_blob = self.block.mining_blob + mining_blob = self.block.mining_blob(config.dev) self.block.blockheader.set_mining_nonce_from_blob(mining_blob) self.assertEqual(self.block.blockheader.mining_nonce, current_mining_nonce) self.assertEqual(self.block.headerhash, current_headerhash) - self.assertEqual(self.block.blockheader.mining_blob, mining_blob) - - def test_epoch(self): - # Epoch should follow this formula: block_number // blocks_per_epoch - self.assertEqual(self.block.epoch, int(self.block.block_number // config.dev.blocks_per_epoch)) + self.assertEqual(self.block.blockheader.mining_blob(config.dev), mining_blob) def test_verify_blob(self): m_blockheader = Mock() self.block.blockheader = m_blockheader - self.block.verify_blob(b'blob') - m_blockheader.verify_blob.assert_called_once_with(b'blob') + self.block.verify_blob(b'blob', config.dev) + m_blockheader.verify_blob.assert_called_once_with(b'blob', config.dev) def test_validate(self): # 1. Set up all the mocking so that Block.validate() should pass @@ -103,6 +109,7 @@ def test_validate(self): attrs_all_pass = { 'get_block_is_duplicate.return_value': False, 'validate_mining_nonce.return_value': True, + 'get_config_by_block_number.return_value': config.dev, } m_chain_manager.configure_mock(**attrs_all_pass) self.block._validate_parent_child_relation = Mock(return_value=True) @@ -159,11 +166,11 @@ def test_validate(self): def test_is_future_block(self): self.blockheader.timestamp = replacement_getTime() + config.dev.block_max_drift + 1 - result = self.block.is_future_block() + result = self.block.is_future_block(config.dev) self.assertTrue(result) self.blockheader.timestamp = replacement_getTime() - result = self.block.is_future_block() + result = self.block.is_future_block(config.dev) self.assertFalse(result) def test_validate_parent_child_relation(self): @@ -172,12 +179,12 @@ def test_validate_parent_child_relation(self): @patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) -@patch('qrl.core.txs.CoinBase.CoinBase.apply_state_changes', name='mock CoinBase.apply_state_changes()', +@patch('qrl.core.txs.CoinBase.CoinBase.apply', name='mock CoinBase.apply()', return_value=True) -@patch('qrl.core.txs.TransferTransaction.TransferTransaction.apply_state_changes', - name='mock Transfer.apply_state_changes()', return_value=True) -@patch('qrl.core.txs.TransferTransaction.TransferTransaction.validate_extended', - name='mock Transfer.validate_extended()', return_value=True) +@patch('qrl.core.txs.TransferTransaction.TransferTransaction.apply', + name='mock TransferTransaction.apply()', return_value=True) +@patch('qrl.core.txs.Transaction.Transaction.validate_slave', + name='mock Transaction.validate_slave()', return_value=True) @patch('qrl.core.txs.TransferTransaction.TransferTransaction.validate', name='mock Transfer.validate()', return_value=True) class TestBlockApplyStateChanges(TestCase): @@ -199,58 +206,79 @@ class TestBlockApplyStateChanges(TestCase): def generate_address_states(self, alice_attrs, bob_attrs, slave_attrs): address_states = { - self.alice.address: Mock(name='self.alice AddressState', autospec=AddressState, **alice_attrs), - self.bob.address: Mock(name='self.bob AddressState', autospec=AddressState, **bob_attrs), - self.slave.address: Mock(name='self.slave AddressState', autospec=AddressState, **slave_attrs) + self.alice.address: Mock(name='self.alice OptimizedAddressState', autospec=OptimizedAddressState, **alice_attrs), + self.bob.address: Mock(name='self.bob OptimizedAddressState', autospec=OptimizedAddressState, **bob_attrs), + self.slave.address: Mock(name='self.slave OptimizedAddressState', autospec=OptimizedAddressState, **slave_attrs) } return address_states def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.chain_manager = ChainManager(self.state) self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() - self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], fee=1, xmss_pk=self.alice.pk) - self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], fee=1, xmss_pk=self.slave.pk, + self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], + message_data=None, fee=1, xmss_pk=self.alice.pk) + self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], + message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) - # self.tx1 = Mock(autospec=TransferTransaction, addrs_to=[self.bob.address], amounts=[10], fee=1, - # xmss_pk=self.alice.pk) - # self.tx2 = Mock(autospec=TransferTransaction, addrs_to=[self.bob.address], amounts=[10], fee=1, - # xmss_pk=self.slave.pk, master_addr=self.alice.address) self.tx1._data.nonce = 3 self.tx2._data.nonce = 6 self.tx1.sign(self.alice) self.tx2.sign(self.slave) self.block_attrs = { + "dev_config": config.dev, "block_number": 5, "prev_headerhash": bytes(sha2_256(b'test')), "prev_timestamp": 10, "transactions": [self.tx1, self.tx2], - "miner_address": self.alice.address + "miner_address": self.alice.address, + "seed_height": 0, + "seed_hash": None, } - self.alice_addrstate_attrs = {'nonce': 2, 'ots_key_reuse.return_value': False} - self.slave_addrstate_attrs = {'nonce': 5, 'ots_key_reuse.return_value': False} + self.coinbase_addrstate_attrs = OptimizedAddressState.get_default(config.dev.coinbase_address) + self.coinbase_addrstate_attrs.update_balance(None, + int(config.dev.coin_remaining_at_genesis * config.dev.shor_per_quanta)) + self.bob_addrstate_attrs = OptimizedAddressState.get_default(self.bob.address) + self.bob_addrstate_attrs.update_balance(None, 20) + self.alice_addrstate_attrs = OptimizedAddressState.get_default(self.alice.address) + self.alice_addrstate_attrs.update_balance(None, 100) + self.alice_addrstate_attrs.pbdata.nonce = 2 + self.slave_addrstate_attrs = OptimizedAddressState.get_default(self.slave.address) + self.slave_addrstate_attrs.pbdata.nonce = 5 def test_all_ok(self, m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) + get_optimized_address_state = MockFunction() + get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs) + get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs) + get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs) + get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs) + self.chain_manager.get_optimized_address_state = get_optimized_address_state.get block = Block.create(**self.block_attrs) - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertTrue(result) def test_extra_coinbase_tx(self, m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) + get_optimized_address_state = MockFunction() + get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs) + get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs) + get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs) + get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs) - coinbase_extra = CoinBase.create(500, self.alice.address, 5) + coinbase_extra = CoinBase.create(config.dev, 500, self.alice.address, 5) self.block_attrs["transactions"] = [self.tx1, coinbase_extra, self.tx2] block = Block.create(**self.block_attrs) - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) def test_bad_nonce_or_ots_reused(self, m_TransferTransaction_validate, @@ -259,45 +287,97 @@ def test_bad_nonce_or_ots_reused(self, m_TransferTransaction_validate, m_CoinBase_apply_state_changes): # If a TX was signed by a Slave XMSS, apply_state_changes() should check against the Slave's AddressState.nonce. # In this case, tx.nonce = 3 but slave addrstate.nonce = 0 - self.slave_addrstate_attrs['nonce'] = 0 - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) + self.slave_addrstate_attrs.pbdata.nonce = 0 + get_optimized_address_state = MockFunction() + get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs) + get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs) + get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs) + get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs) block = Block.create(**self.block_attrs) - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) - self.slave_addrstate_attrs['nonce'] = 5 + self.slave_addrstate_attrs.pbdata.nonce = 5 # Now we pretend that Alice's OTS key has been reused. - self.alice_addrstate_attrs['ots_key_reuse.return_value'] = True - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) - self.alice_addrstate_attrs['ots_key_reuse.return_value'] = False # Now we pretend that Slave's OTS key has been reused. - self.slave_addrstate_attrs['ots_key_reuse.return_value'] = True - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) def test_tx_validation_fails(self, m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): - address_states = self.generate_address_states(self.alice_addrstate_attrs, {}, self.slave_addrstate_attrs) + get_optimized_address_state = MockFunction() + get_optimized_address_state.put(self.coinbase_addrstate_attrs.address, self.coinbase_addrstate_attrs) + get_optimized_address_state.put(self.bob_addrstate_attrs.address, self.bob_addrstate_attrs) + get_optimized_address_state.put(self.alice_addrstate_attrs.address, self.alice_addrstate_attrs) + get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs) + block = Block.create(**self.block_attrs) m_TransferTransaction_validate.return_value = False - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) m_TransferTransaction_validate.return_value = True m_TransferTransaction_validate_extended.return_value = False - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) m_TransferTransaction_validate_extended.return_value = True with patch('qrl.core.txs.CoinBase.CoinBase.validate_extended') as m_validate_extended: m_validate_extended.return_value = False - result = block.apply_state_changes(address_states) + result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) + + def test_put_block_number_mapping(self, m_TransferTransaction_validate, + m_TransferTransaction_validate_extended, + m_TransferTransaction_apply_state_changes, + m_CoinBase_apply_state_changes): + bm = qrl_pb2.BlockNumberMapping() + Block.put_block_number_mapping(self.state, 0, bm, None) + read_bm = Block.get_block_number_mapping(self.state, 0) + self.assertEqual(bm.SerializeToString(), + read_bm.SerializeToString()) + self.assertIsNone(Block.get_block_by_number(self.state, 4)) + + def test_get_block_number_mapping(self, m_TransferTransaction_validate, + m_TransferTransaction_validate_extended, + m_TransferTransaction_apply_state_changes, + m_CoinBase_apply_state_changes): + self.assertIsNone(Block.get_block_number_mapping(self.state, 0)) + bm = qrl_pb2.BlockNumberMapping() + Block.put_block_number_mapping(self.state, 0, bm, None) + read_bm = Block.get_block_number_mapping(self.state, 0) + self.assertEqual(bm.SerializeToString(), + read_bm.SerializeToString()) + + def test_get_block_by_number(self, m_TransferTransaction_validate, + m_TransferTransaction_validate_extended, + m_TransferTransaction_apply_state_changes, + m_CoinBase_apply_state_changes): + bm = qrl_pb2.BlockNumberMapping() + Block.put_block_number_mapping(self.state, 0, bm, None) + self.assertIsNone(Block.get_block_by_number(self.state, 4)) + + def test_last_block(self, m_TransferTransaction_validate, + m_TransferTransaction_validate_extended, + m_TransferTransaction_apply_state_changes, + m_CoinBase_apply_state_changes): + def get_block_by_number(state, block_number): + block = Block() + block.blockheader._data.block_number = block_number + return block + + self.assertIsNone(Block.last_block(self.state)) + with patch("qrl.core.Block.Block.get_block_by_number") as mock_get_block_by_number: + mock_get_block_by_number.side_effect = get_block_by_number + self.state.update_mainchain_height(10, None) + self.assertEqual(Block.last_block(self.state).block_number, 10) + + self.state.update_mainchain_height(1, None) + self.assertEqual(Block.last_block(self.state).block_number, 1) diff --git a/tests/core/test_blockheader.py b/tests/core/test_blockheader.py index 365e05000..34b4f9709 100644 --- a/tests/core/test_blockheader.py +++ b/tests/core/test_blockheader.py @@ -18,7 +18,14 @@ class TestBlockHeader(TestCase): def setUp(self): with mock.patch('qrl.core.misc.ntp.getTime', return_value=1615270948) as time_mock: - self.block_header = BlockHeader.create(1, sha256(b'prev'), time_mock.return_value, sha256(b'txs'), 10) + self.block_header = BlockHeader.create(config.dev, + 1, + sha256(b'prev'), + time_mock.return_value, + sha256(b'txs'), + 10, + 0, + None) self.fee_reward = 10 self.coinbase_amount = self.block_header.block_reward + self.fee_reward @@ -32,26 +39,29 @@ def setUp(self): ) def test_create(self, time_mock): - b = BlockHeader.create(blocknumber=1, prev_headerhash=b'headerhash', prev_timestamp=10, - hashedtransactions=b'some_data', fee_reward=1) + b = BlockHeader.create(dev_config=config.dev, blocknumber=1, prev_headerhash=b'headerhash', + prev_timestamp=10, hashedtransactions=b'some_data', fee_reward=1, + seed_height=0, seed_hash=None) self.assertIsNotNone(b) - b = BlockHeader.create(blocknumber=1, prev_headerhash=b'headerhash', prev_timestamp=10, - hashedtransactions=b'some_data', fee_reward=1) - self.assertEqual(b.epoch, 0) + b = BlockHeader.create(dev_config=config.dev, blocknumber=1, prev_headerhash=b'headerhash', + prev_timestamp=10, hashedtransactions=b'some_data', fee_reward=1, + seed_height=0, seed_hash=None) def test_create_fails_when_prev_timestamp_is_negative(self, time_mock): # The only way to get it to fail in this mode is to pass a negative timestamp. Which should never happen IRL. time_mock.return_value = 0 - b = BlockHeader.create(1, sha256(b'prev'), -10, sha256(b'txs'), 10) + b = BlockHeader.create(config.dev, 1, sha256(b'prev'), -10, sha256(b'txs'), 10, seed_height=0, seed_hash=None) self.assertIsNone(b) def test_create_uses_prev_timestamp_when_genesis_block(self, time_mock): - genesis = BlockHeader.create(0, sha256(b'Random Scifi Book Title'), time_mock.return_value, sha256(b'txs'), 10) + genesis = BlockHeader.create(config.dev, 0, sha256(b'Random Scifi Book Title'), + time_mock.return_value, sha256(b'txs'), 10, 0, None) self.assertEqual(genesis.timestamp, time_mock.return_value) def test_block_reward_calc_genesis_is_total_coin_supply(self, time_mock): - genesis = BlockHeader.create(0, sha256(b'Random Scifi Book Title'), time_mock.return_value, sha256(b'txs'), 10) + genesis = BlockHeader.create(config.dev, 0, sha256(b'Random Scifi Book Title'), + time_mock.return_value, sha256(b'txs'), 10, 0, None) self.assertEqual(config.dev.supplied_coins, genesis.block_reward) def test_init(self, time_mock): @@ -64,11 +74,11 @@ def test_init2(self, time_mock): def test_blob(self, time_mock): self.assertEquals('00501846b24200c31fca7172a7f701ae50322579cfdf1d7777daab4ce6ead70b76debb2c51a1' 'c700000000000000000000000000000000002b80aecec05ad5c7c4f2259c8f69e2966a6ce102', - bin2hstr(self.block_header.mining_blob)) - self.assertEquals(config.dev.mining_blob_size, len(self.block_header.mining_blob)) + bin2hstr(self.block_header.mining_blob(config.dev))) + self.assertEquals(config.dev.mining_blob_size_in_bytes, len(self.block_header.mining_blob(config.dev))) def test_hash(self, time_mock): - header_hash = self.block_header.generate_headerhash() + header_hash = self.block_header.generate_headerhash(config.dev) self.assertEquals('ac021e63df860ea930ea9de05e350d3f74af35341688134f92957f1dac3a62fb', bin2hstr(header_hash)) @@ -77,9 +87,9 @@ def test_hash(self, time_mock): self.assertEquals(32, len(self.block_header.headerhash)) def test_hash_nonce(self, time_mock): - self.block_header.set_nonces(100, 0) + self.block_header.set_nonces(config.dev, 100, 0) - header_hash = self.block_header.generate_headerhash() + header_hash = self.block_header.generate_headerhash(config.dev) self.assertEquals('b6f937020f9876f3c6887e7a6759201411ed8826ed9ce4283ffe48e1aa90d692', bin2hstr(header_hash)) @@ -90,45 +100,52 @@ def test_hash_nonce(self, time_mock): self.assertEquals(32, len(self.block_header.headerhash)) def test_validate_pass(self, time_mock): - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, self.block_header.tx_merkle_root) + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + self.block_header.tx_merkle_root, config.dev) self.assertTrue(result) def test_validate_fail_timestamp_checks(self, time_mock): # The Block's timestamp is too far in the future time_mock.return_value = 10 # set our current_time way backwards - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, self.block_header.tx_merkle_root) + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) time_mock.return_value = 1615270948 # Block came out before Genesis block?! self.block_header._data.timestamp_seconds = 0 - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, self.block_header.tx_merkle_root) + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) self.block_header._data.timestamp_seconds = 1615270948 def test_validate_fail_headerhash(self, time_mock): # BlockHeader recalculates the headerhash. If the recalculation is different... with mock.patch('qrl.core.BlockHeader.BlockHeader.generate_headerhash', return_value=b'nonsense'): - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, self.block_header.tx_merkle_root) + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) def test_validate_fail_rewards_and_wrong_merkleroot(self, time_mock): # Recalculates the expected block_reward for this block_number. If the recalculation is different... with mock.patch('qrl.core.BlockHeader.BlockHeader.block_reward_calc', return_value=0): - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, self.block_header.tx_merkle_root) + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) # The function above says that the fee_reward should be 3, but the BlockHeader thought it was 10 - result = self.block_header.validate(3, self.block_header.block_reward + 3, self.block_header.tx_merkle_root) + result = self.block_header.validate(3, self.block_header.block_reward + 3, + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) # coinbase_amount should be BlockHeader.block_reward + BlockHeader.fee_reward result = self.block_header.validate(self.fee_reward, self.block_header.block_reward + 5, - self.block_header.tx_merkle_root) + self.block_header.tx_merkle_root, config.dev) self.assertFalse(result) # The function above says that the Merkle root should be something else - result = self.block_header.validate(self.fee_reward, self.coinbase_amount, b'some other merkle root') + result = self.block_header.validate(self.fee_reward, self.coinbase_amount, + b'some other merkle root', config.dev) self.assertFalse(result) def test_validate_parent_child_relation(self, time_mock): @@ -160,27 +177,27 @@ def test_validate_parent_child_relation_parent_block_must_be_older(self, time_mo def test_verify_blob(self, time_mock): # verify_blob() ensures the miner did not tamper with anything other than the mining nonce. - blob = bytearray(self.block_header.mining_blob) + blob = bytearray(self.block_header.mining_blob(config.dev)) # if we meddle with the bytes between mining_nonce_offset and mining_nonce_offset + 17, the blob should pass for i in range(config.dev.mining_nonce_offset, config.dev.mining_nonce_offset + 17): blob[i] = 6 # it should still pass verification - result = self.block_header.verify_blob(blob) + result = self.block_header.verify_blob(blob, config.dev) self.assertTrue(result) # But if we change the bits outside of this range, verification will fail. blob[56] = 6 - result = self.block_header.verify_blob(blob) + result = self.block_header.verify_blob(blob, config.dev) self.assertFalse(result) def test_update_merkle_root(self, time_mock): # update_merkle_root() changes the BlockHeader's merkle root, # calls set_nonces() to reset the nonces to 0 and # recalculates the blockhash. - self.block_header.set_nonces(1, 1) + self.block_header.set_nonces(config.dev, 1, 1) old_hash = self.block_header.headerhash - self.block_header.update_merkle_root(b'new merkle root') + self.block_header.update_merkle_root(config.dev, b'new merkle root') self.assertEqual(self.block_header.mining_nonce, 0) self.assertEqual(self.block_header.extra_nonce, 0) @@ -200,7 +217,7 @@ def test_set_mining_nonce_from_blob(self, time_mock): for i in range(config.dev.extra_nonce_offset + 8, config.dev.extra_nonce_offset + 14): mock_blob[i] = 3 - self.block_header.set_mining_nonce_from_blob(mock_blob) + self.block_header.set_mining_nonce_from_blob(mock_blob, config.dev) self.assertEqual(self.block_header.mining_nonce, 16843009) self.assertEqual(self.block_header.extra_nonce, 144680345676153346) diff --git a/tests/core/test_formulas.py b/tests/core/test_formulas.py index cb23dac79..82389f247 100644 --- a/tests/core/test_formulas.py +++ b/tests/core/test_formulas.py @@ -4,6 +4,7 @@ from decimal import Decimal from unittest import TestCase +from qrl.core import config from qrl.core.misc import logger from qrl.core.formulas import calc_coeff, remaining_emission @@ -15,10 +16,10 @@ def __init__(self, *args, **kwargs): super(TestFormulas, self).__init__(*args, **kwargs) def test_calc_coeff(self): - self.assertEqual(calc_coeff(), Decimal('1.664087503734056374552843909E-7')) + self.assertEqual(calc_coeff(config.dev), Decimal('1.664087503734056374552843909E-7')) # TODO: Test more values def test_remaining_emission(self): - logger.info(remaining_emission(100)) - self.assertEqual(remaining_emission(100), Decimal('39999334370536850')) + logger.info(remaining_emission(100, config.dev)) + self.assertEqual(remaining_emission(100, config.dev), Decimal('39999334370536850')) # TODO: Test more values diff --git a/tests/core/test_messagereceipt.py b/tests/core/test_messagereceipt.py index 004f79597..038f64322 100644 --- a/tests/core/test_messagereceipt.py +++ b/tests/core/test_messagereceipt.py @@ -26,7 +26,10 @@ def test_create(self): LegacyMessage.MT, LegacyMessage.TK, LegacyMessage.TT, - LegacyMessage.SL]) + LegacyMessage.SL, + LegacyMessage.MC, + LegacyMessage.MS, + LegacyMessage.MV]) def test_register(self): mr = MessageReceipt() diff --git a/tests/core/test_node.py b/tests/core/test_node.py index 428c80ffd..08e83fde0 100644 --- a/tests/core/test_node.py +++ b/tests/core/test_node.py @@ -10,7 +10,7 @@ from tests.misc.helper import get_alice_xmss, get_random_xmss from qrl.core import config from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.ESyncState import ESyncState from qrl.core.GenesisBlock import GenesisBlock from qrl.core.node import POW @@ -98,7 +98,8 @@ def test_sync_state_change_synced(self): chain_manager.get_block_metadata = MagicMock(return_value=get_block_metadata_response) alice_xmss = get_alice_xmss() - chain_manager._state.get_address_state = MagicMock(return_value=AddressState.get_default(alice_xmss.address)) + chain_manager._state.get_address_state = MagicMock( + return_value=OptimizedAddressState.get_default(alice_xmss.address)) chain_manager._state.get_measurement = MagicMock(return_value=60) p2p_factory = Mock() diff --git a/tests/core/test_qrlnode.py b/tests/core/test_qrlnode.py index f56de49f5..69b934bfd 100644 --- a/tests/core/test_qrlnode.py +++ b/tests/core/test_qrlnode.py @@ -1,9 +1,9 @@ -from unittest import TestCase, expectedFailure -from mock import Mock, patch, PropertyMock, mock +from unittest import TestCase +from mock import Mock, patch, PropertyMock, mock, MagicMock from qrl.core import config from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.Block import Block from qrl.core.BlockMetadata import BlockMetadata from qrl.core.ESyncState import ESyncState @@ -92,7 +92,8 @@ def setUp(self): self.qrlnode.set_chain_manager(self.chain_manager) - def test_monitor_chain_state_no_peer_with_higher_difficulty_found(self): + @patch('qrl.core.BlockMetadata.BlockMetadata.get_block_metadata') + def test_monitor_chain_state_no_peer_with_higher_difficulty_found(self, mock_get_block_metadata): """ QRLNode.monitor_chain_state() basically: 1. Tells P2PPeerManager to clean the list of channels/P2PProtocols, i.e. remove any we haven't heard @@ -105,7 +106,7 @@ def test_monitor_chain_state_no_peer_with_higher_difficulty_found(self): m_block = Mock(autospec=Block, name='mock last Block', block_number=2, headerhash=b'deadbeef') m_block_metadata = Mock(autospec=BlockMetadata, cumulative_difficulty=hstr2bin('01')) self.qrlnode.peer_manager.get_better_difficulty.return_value = None - self.db_state.get_block_metadata.return_value = m_block_metadata + mock_get_block_metadata.return_value = m_block_metadata self.chain_manager.last_block.return_value = m_block self.qrlnode.monitor_chain_state() @@ -113,7 +114,8 @@ def test_monitor_chain_state_no_peer_with_higher_difficulty_found(self): self.qrlnode.peer_manager.monitor_chain_state.assert_called_once() self.qrlnode.peer_manager.get_better_difficulty.assert_called_once() - def test_monitor_chain_state_peer_with_higher_difficulty_found(self): + @patch('qrl.core.BlockMetadata.BlockMetadata.get_block_metadata') + def test_monitor_chain_state_peer_with_higher_difficulty_found(self, mock_get_block_metadata): """ QRLNode.monitor_chain_state() basically: 1. Tells P2PPeerManager to clean the list of channels/P2PProtocols, i.e. remove any we haven't heard @@ -127,7 +129,7 @@ def test_monitor_chain_state_peer_with_higher_difficulty_found(self): m_block_metadata = Mock(autospec=BlockMetadata, cumulative_difficulty=hstr2bin('01')) m_channel = Mock(autospec=P2PProtocol, addr_remote='1.1.1.1') self.qrlnode.peer_manager.get_better_difficulty.return_value = m_channel - self.db_state.get_block_metadata.return_value = m_block_metadata + mock_get_block_metadata.return_value = m_block_metadata self.chain_manager._last_block = m_block self.qrlnode.monitor_chain_state() @@ -164,40 +166,48 @@ def test_get_address_is_used(self): with self.assertRaises(ValueError): self.qrlnode.get_address_is_used(b'fdsa') - def test_get_transactions_by_address(self): + @patch('qrl.core.PaginatedData.PaginatedData.get_paginated_data') + @patch('qrl.core.OptimizedAddressState.OptimizedAddressState.get_optimized_address_state') + @patch('qrl.core.TransactionMetadata.TransactionMetadata.get_tx_metadata') + def test_get_mini_transactions_by_address(self, + mock_get_tx_metadata, + mock_get_optimized_address_state, + mock_get_paginated_data): """ QRLNode.get_transactions_by_address() returns all the changes in balance caused by a transaction. """ - mock_get_tx_metadata = GetTXMetadata() + get_tx_metadata = GetTXMetadata() xmss = get_alice_xmss() xmss2 = get_random_xmss() - addr_state = AddressState.get_default(xmss.address) + addr_state = OptimizedAddressState.get_default(xmss.address) addr_state.pbdata.balance = 100 + addr_state.pbdata.transaction_hash_count = 3 + mock_get_optimized_address_state.return_value = addr_state - tx1 = CoinBase.create(100, xmss.address, 5) - mock_get_tx_metadata.register_tx_metadata(tx1, 5) - addr_state.transaction_hashes.append(tx1.txhash) + tx1 = CoinBase.create(config.dev, 100, xmss.address, 5) + get_tx_metadata.register_tx_metadata(tx1, 1) tx2 = TransferTransaction.create(addrs_to=[xmss2.address], amounts=[10], + message_data=None, fee=1, xmss_pk=xmss.pk) tx2.sign(xmss) - mock_get_tx_metadata.register_tx_metadata(tx2, 99) - addr_state.transaction_hashes.append(tx2.txhash) + get_tx_metadata.register_tx_metadata(tx2, 1) tx3 = TransferTransaction.create(addrs_to=[xmss.address], amounts=[100], + message_data=None, fee=1, xmss_pk=xmss2.pk) tx3.sign(xmss) - mock_get_tx_metadata.register_tx_metadata(tx3, 101) - addr_state.transaction_hashes.append(tx3.txhash) + get_tx_metadata.register_tx_metadata(tx3, 2) - self.db_state.get_address_state.return_value = addr_state - self.db_state.get_tx_metadata = mock_get_tx_metadata.get_tx_metadata - result, balance = self.qrlnode.get_transactions_by_address(alice.address) + mock_get_paginated_data.return_value = [tx1.txhash, tx2.txhash, tx3.txhash] + mock_get_tx_metadata.side_effect = get_tx_metadata.get_tx_metadata + response = self.qrlnode.get_mini_transactions_by_address(alice.address, 3, 1) + result, balance = response.mini_transactions, response.balance self.assertEqual(len(result), 3) self.assertEqual(result[0].amount, 100) @@ -209,21 +219,22 @@ def test_get_transactions_by_address(self): self.assertEqual(result[2].amount, 100) self.assertEqual(result[2].out, False) - self.assertEqual(balance, 189) + self.assertEqual(balance, 100) - def test_get_address_state(self): + @patch('qrl.core.OptimizedAddressState.OptimizedAddressState.get_optimized_address_state') + def test_get_address_state(self, mock_get_optimized_address_state): """ QRLNode.get_address_state() asks the DB (State) for an Address's AddressState, like its nonce, ots index... It also validates the address before sending it to the State. """ - m_addr_state = Mock(autospec=AddressState) - self.db_state.get_address_state.return_value = m_addr_state + m_addr_state = Mock(autospec=OptimizedAddressState) + mock_get_optimized_address_state.return_value = m_addr_state result = self.qrlnode.get_address_state(alice.address) self.assertEqual(m_addr_state, result) # Fetching AddressState for Coinbase Address - m_addr_state = Mock(autospec=AddressState) - self.db_state.get_address_state.return_value = m_addr_state + m_addr_state = Mock(autospec=OptimizedAddressState) + mock_get_optimized_address_state.return_value = m_addr_state result = self.qrlnode.get_address_state(config.dev.coinbase_address) self.assertEqual(m_addr_state, result) @@ -242,9 +253,10 @@ def test_get_addr_from(self): self.assertEqual(answer, slave.address) # Just testing that these wrapper functions are doing what they're supposed to do. - def test_get_transaction(self): + @patch("qrl.core.TransactionMetadata.TransactionMetadata.get_tx_metadata") + def test_get_transaction(self, mock_get_tx_metadata): self.qrlnode.get_transaction(b'a txhash') - self.db_state.get_tx_metadata.assert_called_once_with(b'a txhash') + mock_get_tx_metadata.assert_called_once_with(self.db_state, b'a txhash') def test_get_unconfirmed_transaction(self): self.qrlnode.get_unconfirmed_transaction(b'a txhash') @@ -253,35 +265,40 @@ def test_get_unconfirmed_transaction(self): def test_get_block_last(self): self.assertEqual(self.qrlnode.get_block_last().block_number, 2) - def test_get_block_from_hash(self): + @patch('qrl.core.Block.Block.get_block') + def test_get_block_from_hash(self, mock_get_block): self.qrlnode.get_block_from_hash(b'a blockhash') - self.db_state.get_block.assert_called_once_with(b'a blockhash') + mock_get_block.assert_called_once_with(self.db_state, b'a blockhash') - def test_get_block_from_index(self): + @patch('qrl.core.Block.Block.get_block_by_number') + def test_get_block_from_index(self, mock_get_block_by_number): self.qrlnode.get_block_from_index(3) - self.db_state.get_block_by_number.assert_called_once_with(3) + mock_get_block_by_number.assert_called_once_with(self.db_state, 3) - def test_get_blockidx_from_txhash(self): - self.db_state.get_tx_metadata.return_value = (Mock(name='Mock TX'), 3) + @patch('qrl.core.TransactionMetadata.TransactionMetadata.get_tx_metadata') + def test_get_blockidx_from_txhash(self, mock_get_tx_metadata): + # self.db_state.get_tx_metadata.return_value = (Mock(name='Mock TX'), 3) + mock_get_tx_metadata.return_value = (Mock(name='Mock TX'), 3) result = self.qrlnode.get_blockidx_from_txhash(b'a txhash') self.assertEqual(result, 3) - self.db_state.get_tx_metadata.return_value = None + mock_get_tx_metadata.return_value = None result = self.qrlnode.get_blockidx_from_txhash(b'a txhash') self.assertIsNone(result) - def test_get_block_to_mine(self): + @patch('qrl.core.BlockMetadata.BlockMetadata.get_block_metadata') + def test_get_block_to_mine(self, m_get_block_metadata): m_block = Mock(autospec=Block, name='mock Block') m_block_metadata = Mock(autospec=BlockMetadata, name='mock BlockMetadata', block_difficulty=0) with mock._patch_object(ChainManager, 'last_block') as m_last_block: m_last_block.__get__ = Mock(return_value=m_block) - self.chain_manager._state.get_block_metadata.return_value = m_block_metadata + m_get_block_metadata.return_value = m_block_metadata self.qrlnode.get_block_to_mine(alice.address) m_last_block.__get__.assert_called_once() - self.chain_manager._state.get_block_metadata.assert_called_once() + m_get_block_metadata.assert_called_once() self.qrlnode._pow.miner.get_block_to_mine.assert_called_once_with(alice.address, self.chain_manager.tx_pool, m_block, 0) @@ -294,13 +311,14 @@ def test_get_node_info(self): ans = self.qrlnode.get_node_info() self.assertIsInstance(ans, qrl_pb2.NodeInfo) - def test_get_latest_transactions(self): + @patch('qrl.core.LastTransactions.LastTransactions.get_last_txs') + def test_get_latest_transactions(self, mock_get_last_txs): """ This returns the last n txs, just like get_latest_blocks(). Useful for the Block Explorer, presumably. """ # get_last_txs returns the latest transactions - self.db_state.get_last_txs.return_value = [Mock(name='mock TX {}'.format(i), i=i) for i in range(19, -1, -1)] + mock_get_last_txs.return_value = [Mock(name='mock TX {}'.format(i), i=i) for i in range(19, -1, -1)] # Given [0, 1, 2... 19], with offset 0 count 1 should return [19] result = self.qrlnode.get_latest_transactions(0, 1) @@ -314,27 +332,6 @@ def test_get_latest_transactions(self): self.assertEqual(result[1].i, 16) self.assertEqual(result[2].i, 15) - @expectedFailure - def test_get_latest_transactions_unconfirmed(self): - """ - This should return the last n unconfirmed txs in the txpool. - Useful for the Block Explorer, presumably. - FAIL: this returns the first n unconfirmed transactions. - """ - self.chain_manager.tx_pool.transactions = [(0, Mock(name='mock TX {}'.format(i), i=i)) for i in range(0, 20)] - - # Given [0, 1, 2... 19], with offset 0 count 1 should return [19] - result = self.qrlnode.get_latest_transactions_unconfirmed(0, 1) - self.assertEqual(len(result), 1) - self.assertEqual(result[0].i, 19) - - # Given [0, 1, 2... 19], with offset 2 count 3 should return [15, 16, 17] - result = self.qrlnode.get_latest_transactions_unconfirmed(2, 3) - self.assertEqual(len(result), 3) - self.assertEqual(result[0].i, 15) - self.assertEqual(result[1].i, 16) - self.assertEqual(result[2].i, 17) - def test_get_block_timeseries(self): """ get_block_timeseries() returns a list of stats for the last n blocks. @@ -355,7 +352,7 @@ def test_get_block_timeseries(self): def replacement_get_block_datapoint(headerhash_current): return m_blockdps.get(headerhash_current) - self.chain_manager._state.get_block_datapoint = replacement_get_block_datapoint + self.chain_manager.get_block_datapoint = replacement_get_block_datapoint # Get last 5 blocks should return [BlockDatapoint 1, BlockDatapoint 2... BlockDatapoint 5] result = self.qrlnode.get_block_timeseries(5) @@ -385,8 +382,10 @@ def replacement_get_block_datapoint(headerhash_current): result_converted_from_iterator = [r for r in result] self.assertEqual(result_converted_from_iterator, m_blockdps_as_list) - @patch('qrl.core.qrlnode.ChainManager.height', new_callable=PropertyMock, return_value=3) - def test_get_blockheader_and_metadata(self, m_height): + @patch('qrl.core.BlockMetadata.BlockMetadata.get_block_metadata') + @patch('qrl.core.Block.Block.get_block_by_number') + @patch('qrl.core.ChainManager.ChainManager.height', new_callable=PropertyMock, return_value=3) + def test_get_blockheader_and_metadata(self, m_height, m_get_block_by_number, m_get_block_metadata): blocks = [] for i in range(0, 4): m = Mock(name='mock Block {}'.format(i), i=i) @@ -400,14 +399,14 @@ def test_get_blockheader_and_metadata(self, m_height): b'3': Mock(name='mock BlockMetadata 3', i=3), } - def replacement_get_block_by_number(idx): + def replacement_get_block_by_number(state, idx): return blocks[idx] - def replacement_get_block_metadata(headerhash): + def replacement_get_block_metadata(state, headerhash): return block_metadata[headerhash] - self.db_state.get_block_by_number = replacement_get_block_by_number - self.db_state.get_block_metadata = replacement_get_block_metadata + m_get_block_by_number.side_effect = replacement_get_block_by_number + m_get_block_metadata.side_effect = replacement_get_block_metadata # Because we're just using indexes of a list, we can't actually ever return blocks[0] # But this shouldn't be a problem because IRL this uses hashes, not indexes. @@ -427,7 +426,7 @@ def replacement_get_block_metadata(headerhash): self.assertEqual(result_metadata, block_metadata[b'3']) # If get_block_by_number() couldn't find the corresponding block, we should get a (None, None) - self.db_state.get_block_by_number = Mock(return_value=None) + m_get_block_by_number.side_effect = Mock(return_value=None) result_header, result_metadata = self.qrlnode.get_blockheader_and_metadata(2) self.assertIsNone(result_header) self.assertIsNone(result_metadata) @@ -493,13 +492,15 @@ def test_epoch(self): self.m_chain_manager._last_block = Mock(block_number=256) self.assertEqual(self.qrlnode.epoch, (256 // config.dev.blocks_per_epoch)) - def test_uptime_network(self): + @patch('qrl.core.Block.Block.get_block_by_number') + def test_uptime_network(self, mock_get_block_by_number): # If there is no block after the genesis block, this property should return 0 + mock_get_block_by_number.return_value = None self.assertEqual(self.qrlnode.uptime_network, 0) # However, if there is a block after the genesis block, use its timestamp to calculate our uptime. with patch('qrl.core.misc.ntp.getTime') as m_getTime: - self.m_chain_manager._state.get_block_by_number.return_value = Mock(timestamp=1000000) + mock_get_block_by_number.return_value = Mock(timestamp=1000000) m_getTime.return_value = 1500000 self.assertEqual(self.qrlnode.uptime_network, 500000) @@ -511,19 +512,21 @@ def test_block_last_reward(self): self.m_chain_manager._last_block = Mock(block_reward=53) self.assertEqual(self.qrlnode.block_last_reward, 53) - def test_block_time_mean(self): + @patch('qrl.core.ChainManager.ChainManager.get_measurement') + @patch('qrl.core.BlockMetadata.BlockMetadata.get_block_metadata') + def test_block_time_mean(self, mock_get_block_metadata, mock_get_measurement): # FIXME # For this function to work, last_block() must not return a None. If it does, bad things will happen. self.m_chain_manager._last_block = Mock(name='mock Block') # If this particular function returns None, this property should just return the config value - self.m_chain_manager._state.get_block_metadata.return_value = None - self.assertEqual(self.qrlnode.block_time_mean, config.dev.mining_setpoint_blocktime) + mock_get_block_metadata.return_value = None + self.assertEqual(self.qrlnode.block_time_mean, config.dev.block_timing_in_seconds) # Else, it should consult state.get_measurement() - self.m_chain_manager._state.get_block_metadata.return_value = Mock(name='mock BlockMetadata') + mock_get_block_metadata.return_value = Mock(name='mock BlockMetadata') self.qrlnode.block_time_mean() - self.m_chain_manager._state.get_measurement.assert_called_once() + mock_get_measurement.assert_called_once() def test_coin_supply(self): with mock._patch_object(ChainManager, 'total_coin_supply') as m_total_coin_supply: diff --git a/tests/core/txs/multisig/__init__.py b/tests/core/txs/multisig/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/core/txs/multisig/test_MultiSigCreate.py b/tests/core/txs/multisig/test_MultiSigCreate.py new file mode 100644 index 000000000..28d5e595d --- /dev/null +++ b/tests/core/txs/multisig/test_MultiSigCreate.py @@ -0,0 +1,328 @@ +from unittest import TestCase + +import simplejson as json + +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.AddressState import AddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate +from tests.core.txs.testdata import test_json_MultiSigCreate +from qrl.generated.qrl_pb2 import SlaveMetadata +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_qrl_dir, set_hard_fork_block_number + +logger.initialize_default() + + +class TestMultiSigCreate(TestCase): + def __init__(self, *args, **kwargs): + super(TestMultiSigCreate, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() + + self.alice = get_alice_xmss() + self.bob = get_bob_xmss() + self.random = get_alice_xmss(4) + self.random_signer = get_bob_xmss(4) + self.signatories = [self.alice.address, self.bob.address, self.random.address] + self.weights = [20, 30, 10] + self.threshold = 30 + + def test_create(self): + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 0, + self.random_signer.pk) + self.assertIsInstance(tx, MultiSigCreate) + + def test_to_json(self): + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 0, + self.random_signer.pk) + txjson = tx.to_json() + self.assertEqual(json.loads(test_json_MultiSigCreate), json.loads(txjson)) + + def test_validate_custom(self): + """ + MultiSigCreate _validate_custom() only checks if fee == 0 + """ + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 0, + self.random_signer.pk) + del tx._data.multi_sig_create.signatories[-1] + result = tx._validate_custom() + self.assertFalse(result) + + tx._data.multi_sig_create.signatories.extend(self.signatories) + result = tx._validate_custom() + self.assertFalse(result) + + del tx._data.multi_sig_create.signatories[:] + tx._data.multi_sig_create.signatories.extend(self.signatories) + result = tx._validate_custom() + self.assertTrue(result) + + tx._data.multi_sig_create.threshold = 1000 + result = tx._validate_custom() + self.assertFalse(result) + + @set_hard_fork_block_number() + def test_validate_extended(self): + """ + CoinBase validate_extended() checks for + 1. valid coinbase address (the coinbase address must be config.dev.coinbase_address) + 2. valid addr_to + then calls _validate_custom() + """ + tx = MultiSigCreate.create(signatories=self.signatories, + weights=self.weights, + threshold=self.threshold, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + + addresses_state = { + self.alice.address: alice_address_state, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=None, + batch=None) + + result = tx._validate_extended(state_container) + self.assertTrue(result) + + alice_address_state.pbdata.balance = 4 + result = tx._validate_extended(state_container) + self.assertFalse(result) # False due to insufficient balance to pay the txn fee + + alice_address_state.pbdata.balance = 6 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + @set_hard_fork_block_number() + def test_validate_all(self): + tx = MultiSigCreate.create(signatories=self.signatories, + weights=self.weights, + threshold=self.threshold, + fee=5, + xmss_pk=self.random.pk, + master_addr=self.alice.address) + tx.sign(self.random) + tx.pbdata.nonce = 1 + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + random_address_state = OptimizedAddressState.get_default(address=self.random.address) + + addresses_state = { + self.alice.address: alice_address_state, + self.random.address: random_address_state, + } + slaves = Indexer(b'slave', None) + slaves.data[(self.alice.address, self.random.pk)] = SlaveMetadata(access_type=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=slaves, + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=False, + my_db=self.state._db, + batch=None) + + result = tx.validate_all(state_container) + self.assertTrue(result) + + tx.pbdata.nonce = 2 + result = tx.validate_all(state_container) + self.assertFalse(result) # False as nonce is invalid + + def test_apply_multi_sig_create_txn(self): + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.random.address: OptimizedAddressState.get_default(self.random.address), + self.random_signer.address: OptimizedAddressState.get_default(self.random_signer.address), + } + addresses_state[self.random_signer.address].pbdata.balance = 200 + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 1, + self.random_signer.pk) + tx.sign(self.random_signer) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.random_signer.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertEqual(200 - tx.fee, addresses_state[self.random_signer.address].balance) + + storage_key = state_container.paginated_tx_hash.generate_key(self.random_signer.address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + for signatory_address in self.signatories: + storage_key = state_container.paginated_tx_hash.generate_key(signatory_address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.random_signer.address, + tx.ots_key)) + AddressState.put_addresses_state(self.state, addresses_state) + multi_sig_addresses_state = MultiSigAddressState.get_multi_sig_address_state_by_address( + self.state._db, + MultiSigAddressState.generate_multi_sig_address(tx.txhash)) + + self.assertEqual(self.signatories, multi_sig_addresses_state.signatories) + self.assertEqual(self.weights, multi_sig_addresses_state.weights) + self.assertEqual(self.threshold, multi_sig_addresses_state.threshold) + + def test_revert_multi_sig_create_txn(self): + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.random.address: OptimizedAddressState.get_default(self.random.address), + self.random_signer.address: OptimizedAddressState.get_default(self.random_signer.address), + } + addresses_state[self.random_signer.address].pbdata.balance = 200 + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 1, + self.random_signer.pk) + tx.sign(self.random_signer) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.random_signer.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertEqual(200 - tx.fee, addresses_state[self.random_signer.address].balance) + + storage_key = state_container.paginated_tx_hash.generate_key(self.random_signer.address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + for signatory_address in self.signatories: + storage_key = state_container.paginated_tx_hash.generate_key(signatory_address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.random_signer.address, + tx.ots_key)) + AddressState.put_addresses_state(self.state, addresses_state) + state_container.paginated_multisig_address.put_paginated_data(None) + multi_sig_addresses_state = MultiSigAddressState.get_multi_sig_address_state_by_address( + self.state._db, + MultiSigAddressState.generate_multi_sig_address(tx.txhash)) + + self.assertEqual(self.signatories, multi_sig_addresses_state.signatories) + self.assertEqual(self.weights, multi_sig_addresses_state.weights) + self.assertEqual(self.threshold, multi_sig_addresses_state.threshold) + + for signatory_address in self.signatories: + multi_sig_addresses = state_container.paginated_multisig_address.get_paginated_data(signatory_address, 1) + self.assertEqual(len(multi_sig_addresses), 1) + + tx.revert(self.state, state_container) + state_container.paginated_multisig_address.put_paginated_data(None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.random_signer.address, + tx.ots_key)) + self.assertIsNone(MultiSigAddressState.get_multi_sig_address_state_by_address( + self.state._db, + MultiSigAddressState.generate_multi_sig_address(tx.txhash))) + + for signatory_address in self.signatories: + multi_sig_addresses = state_container.paginated_multisig_address.get_paginated_data(signatory_address, 1) + self.assertEqual(len(multi_sig_addresses), 0) + + def test_apply_multi_sig_create_txn2(self): + """ + Features Tested + - Multi Sig Create txn with duplicate signatories + + Expectation + - It should result into custom validation error throwing ValueError exception + :return: + """ + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.random.address: OptimizedAddressState.get_default(self.random.address), + self.random_signer.address: OptimizedAddressState.get_default(self.random_signer.address), + } + addresses_state[self.random_signer.address].pbdata.balance = 200 + modified_signatories = list(self.signatories) + modified_weights = list(self.weights) + + # Appending bob as signatory second time + modified_signatories.append(self.bob.address) + modified_weights.append(2) + + tx = None + with self.assertRaises(ValueError): + tx = MultiSigCreate.create(modified_signatories, + modified_weights, + self.threshold, + 1, + self.random_signer.pk) + self.assertIsNone(tx) + + def test_affected_address(self): + # This transaction can only involve 2 addresses. + affected_addresses = set() + tx = MultiSigCreate.create(self.signatories, + self.weights, + self.threshold, + 1, + self.random_signer.pk) + tx.set_affected_address(affected_addresses) + + self.assertEqual(4, len(affected_addresses)) + self.assertIn(self.random_signer.address, affected_addresses) + for signatory_address in self.signatories: + self.assertIn(signatory_address, affected_addresses) diff --git a/tests/core/txs/multisig/test_MultiSigSpend.py b/tests/core/txs/multisig/test_MultiSigSpend.py new file mode 100644 index 000000000..829d01aa6 --- /dev/null +++ b/tests/core/txs/multisig/test_MultiSigSpend.py @@ -0,0 +1,329 @@ +from unittest import TestCase + +import simplejson as json + +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from tests.core.txs.testdata import test_json_MultiSigSpend +from qrl.generated.qrl_pb2 import SlaveMetadata +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_qrl_dir, set_hard_fork_block_number + +logger.initialize_default() + + +class TestMultiSigSpend(TestCase): + def __init__(self, *args, **kwargs): + super(TestMultiSigSpend, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() + + self.alice = get_alice_xmss() + self.bob = get_bob_xmss() + self.random = get_alice_xmss(4) + self.random_signer = get_bob_xmss(4) + self.signatories = [self.alice.address, self.bob.address, self.random.address] + self.weights = [20, 30, 10] + self.threshold = 30 + + def test_create(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + self.assertIsInstance(tx, MultiSigSpend) + + def test_to_json(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + txjson = tx.to_json() + self.assertEqual(json.loads(test_json_MultiSigSpend), json.loads(txjson)) + + def test_validate_custom(self): + """ + MultiSigCreate _validate_custom() only checks if fee == 0 + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.random_signer.pk) + del tx._data.multi_sig_spend.addrs_to[-1] + result = tx._validate_custom() + self.assertFalse(result) + + tx._data.multi_sig_spend.addrs_to.extend([self.alice.address]) + result = tx._validate_custom() + self.assertTrue(result) + + del tx._data.multi_sig_spend.amounts[-1] + result = tx._validate_custom() + self.assertFalse(result) + + tx._data.multi_sig_spend.amounts.extend([100]) + result = tx._validate_custom() + self.assertTrue(result) + + tx._data.multi_sig_spend.multi_sig_address = self.bob.address + result = tx._validate_custom() + self.assertFalse(result) + + @set_hard_fork_block_number() + def test_validate_extended(self): + """ + TODO: Check by signing txn from a non signatory address + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=None, + batch=None) + + result = tx._validate_extended(state_container) + self.assertTrue(result) + + alice_address_state.pbdata.balance = 0 + result = tx._validate_extended(state_container) + self.assertFalse(result) + + alice_address_state.pbdata.balance = 5 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + multi_sig_address_state.pbdata.balance = 99 + result = tx._validate_extended(state_container) + self.assertFalse(result) + + multi_sig_address_state.pbdata.balance = 100 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + tx.pbdata.multi_sig_spend.expiry_block_number = 10 + result = tx._validate_extended(state_container) + self.assertFalse(result) + + tx.pbdata.multi_sig_spend.expiry_block_number = 15000 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + @set_hard_fork_block_number() + def test_validate_all(self): + """ + TODO: Check by signing txn from a non signatory address + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=5, + xmss_pk=self.random.pk, + master_addr=self.alice.address) + tx.sign(self.random) + tx._data.nonce = 1 + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + random_address_state = OptimizedAddressState.get_default(address=self.random.address) + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.random.address: random_address_state, + multi_sig_address: multi_sig_address_state, + } + slaves = Indexer(b'slave', None) + slaves.data[(self.alice.address, self.random.pk)] = SlaveMetadata(access_type=0) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=slaves, + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=False, + my_db=self.state._db, + batch=None) + + result = tx.validate_all(state_container) + self.assertTrue(result) + + tx._data.nonce = 2 + result = tx.validate_all(state_container) + self.assertFalse(result) # False as nonce is invalid + + def test_apply(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 5 + bob_address_state = OptimizedAddressState.get_default(self.bob.address) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + self.assertIn(tx.txhash, state_container.votes_stats) + vote_stats = state_container.votes_stats[tx.txhash] + self.assertEqual(vote_stats.shared_key, tx.txhash) + self.assertEqual(vote_stats.total_weight, 0) + self.assertEqual(vote_stats.signatories, multi_sig_address_state.signatories) + + def test_revert(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 5 + alice_address_state.update_ots_bitfield_used_page() + alice_address_state.used_ots_key_count += 1 + alice_address_state.update_multi_sig_address_count() + bob_address_state = OptimizedAddressState.get_default(self.bob.address) + addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: bob_address_state, + multi_sig_address: multi_sig_address_state, + } + + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + tx._data.nonce = 1 + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + self.assertIn(tx.txhash, state_container.votes_stats) + vote_stats = state_container.votes_stats[tx.txhash] + self.assertEqual(vote_stats.shared_key, tx.txhash) + self.assertEqual(vote_stats.total_weight, 0) + self.assertEqual(vote_stats.signatories, multi_sig_address_state.signatories) + + tx.revert(self.state, state_container) + self.assertNotIn(tx.txhash, state_container.votes_stats) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + def test_affected_address(self): + # This transaction can only involve 2 addresses. + affected_addresses = set() + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.bob.address], + amounts=[100], + expiry_block_number=15000, + fee=5, + xmss_pk=self.alice.pk) + tx.set_affected_address(affected_addresses) + + self.assertEqual(3, len(affected_addresses)) + self.assertIn(self.alice.address, affected_addresses) + self.assertIn(multi_sig_address, affected_addresses) diff --git a/tests/core/txs/multisig/test_MultiSigVote.py b/tests/core/txs/multisig/test_MultiSigVote.py new file mode 100644 index 000000000..30450ba9f --- /dev/null +++ b/tests/core/txs/multisig/test_MultiSigVote.py @@ -0,0 +1,394 @@ +from unittest import TestCase + +import simplejson as json + +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.misc import logger +from qrl.core.VoteStats import VoteStats +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.MultiSigAddressState import MultiSigAddressState +from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend +from qrl.core.txs.multisig.MultiSigVote import MultiSigVote +from tests.core.txs.testdata import test_json_MultiSigVote +from qrl.generated.qrl_pb2 import SlaveMetadata +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_qrl_dir, set_hard_fork_block_number + +logger.initialize_default() + + +class TestMultiSigVote(TestCase): + def __init__(self, *args, **kwargs): + super(TestMultiSigVote, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() + + self.alice = get_alice_xmss() + self.bob = get_bob_xmss() + self.random = get_alice_xmss(4) + self.random_signer = get_bob_xmss(4) + self.signatories = [self.alice.address, self.bob.address, self.random.address] + self.weights = [20, 30, 10] + self.threshold = 30 + + def test_create(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=0, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + self.assertIsInstance(tx, MultiSigVote) + + def test_to_json(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=0, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + txjson = tx.to_json() + self.assertEqual(json.loads(test_json_MultiSigVote), json.loads(txjson)) + + def test_validate_custom(self): + """ + MultiSigCreate _validate_custom() only checks if fee == 0 + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=0, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + result = tx._validate_custom() + self.assertTrue(result) + + @set_hard_fork_block_number() + def test_validate_extended(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=None, + batch=None) + + result = tx._validate_extended(state_container) + self.assertTrue(result) + + tx._data.multi_sig_vote.unvote = True + result = tx._validate_extended(state_container) + self.assertFalse(result) + + tx._data.multi_sig_vote.unvote = False + result = tx._validate_extended(state_container) + self.assertTrue(result) + + alice_address_state.pbdata.balance = 0 + result = tx._validate_extended(state_container) + self.assertFalse(result) + + alice_address_state.pbdata.balance = 5 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + state_container.block_number = 15000 + result = tx._validate_extended(state_container) + self.assertTrue(result) + + state_container.block_number = 15001 + result = tx._validate_extended(state_container) + self.assertFalse(result) + + @set_hard_fork_block_number() + def test_validate_all(self): + """ + Test for Validate Extended when transaction has been signed by slave. + :return: + """ + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.random.pk, + master_addr=self.alice.address) + tx.sign(self.random) + tx._data.nonce = 1 + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + random_address_state = OptimizedAddressState.get_default(address=self.random.address) + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + self.random.address: random_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + slaves = Indexer(b'slave', None) + slaves.data[(self.alice.address, self.random.pk)] = SlaveMetadata(access_type=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=slaves, + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=False, + my_db=self.state._db, + batch=None) + + result = tx.validate_all(state_container) + self.assertTrue(result) + + tx._data.nonce = 2 + result = tx.validate_all(state_container) + self.assertFalse(result) # False as nonce is invalid + + def test_apply(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + self.assertIn(spend_tx.txhash, state_container.votes_stats) + vote_stats = state_container.votes_stats[spend_tx.txhash] + unvote, index = vote_stats.get_unvote_by_address(tx.addr_from) + self.assertNotEqual(index, -1) + self.assertFalse(unvote) + self.assertEqual(vote_stats.shared_key, spend_tx.txhash) + self.assertEqual(vote_stats.total_weight, 4) + self.assertEqual(vote_stats.signatories, multi_sig_address_state.signatories) + + def test_revert(self): + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + + alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) + alice_address_state.pbdata.balance = 5 + multi_sig_address_state = MultiSigAddressState.create(creation_tx_hash=b'', + balance=100, + signatories=[self.alice.address, self.bob.address], + weights=[4, 6], + threshold=5, + transaction_hash_count=0) + addresses_state = { + self.alice.address: alice_address_state, + multi_sig_address: multi_sig_address_state, + } + vote_stats = { + spend_tx.txhash: VoteStats.create(multi_sig_address=multi_sig_address, + shared_key=spend_tx.txhash, + signatories=multi_sig_address_state.signatories, + expiry_block_number=spend_tx.expiry_block_number), + } + multi_sig_spend_txs = { + spend_tx.txhash: spend_tx, + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=multi_sig_spend_txs, + votes_stats=vote_stats, + block_number=10, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + tx.apply(self.state, state_container) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + self.assertIn(spend_tx.txhash, state_container.votes_stats) + vote_stats = state_container.votes_stats[spend_tx.txhash] + unvote, index = vote_stats.get_unvote_by_address(tx.addr_from) + self.assertNotEqual(index, -1) + self.assertFalse(unvote) + self.assertEqual(vote_stats.shared_key, spend_tx.txhash) + self.assertEqual(vote_stats.total_weight, 4) + self.assertEqual(vote_stats.signatories, multi_sig_address_state.signatories) + + tx.revert(self.state, state_container) + self.assertIn(spend_tx.txhash, state_container.votes_stats) + vote_stats = state_container.votes_stats[spend_tx.txhash] + unvote, index = vote_stats.get_unvote_by_address(tx.addr_from) + self.assertNotEqual(index, -1) + self.assertTrue(unvote) + self.assertEqual(vote_stats.shared_key, spend_tx.txhash) + self.assertEqual(vote_stats.total_weight, 0) + self.assertEqual(vote_stats.signatories, multi_sig_address_state.signatories) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + tx.ots_key)) + + def test_affected_address(self): + # This transaction can only involve 2 addresses. + affected_addresses = set() + multi_sig_address = MultiSigAddressState.generate_multi_sig_address(b'') + spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address, + addrs_to=[self.alice.address], + amounts=[100], + expiry_block_number=15000, + fee=0, + xmss_pk=self.alice.pk) + spend_tx.sign(self.alice) + tx = MultiSigVote.create(shared_key=spend_tx.txhash, + unvote=False, + fee=5, + xmss_pk=self.alice.pk) + tx.sign(self.alice) + tx.set_affected_address(affected_addresses) + + self.assertEqual(1, len(affected_addresses)) + self.assertIn(self.alice.address, affected_addresses) diff --git a/tests/core/txs/test_CoinBase.py b/tests/core/txs/test_CoinBase.py index 008e466d1..6f54b8069 100644 --- a/tests/core/txs/test_CoinBase.py +++ b/tests/core/txs/test_CoinBase.py @@ -5,14 +5,16 @@ from pyqrllib.pyqrllib import bin2hstr from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.BlockHeader import BlockHeader -from qrl.core.ChainManager import ChainManager from qrl.core.txs.CoinBase import CoinBase from qrl.crypto.misc import sha256 from tests.core.txs.testdata import test_json_CoinBase -from tests.misc.helper import get_alice_xmss +from tests.misc.helper import get_alice_xmss, set_qrl_dir logger.initialize_default() @@ -21,6 +23,8 @@ class TestCoinBase(TestCase): def __init__(self, *args, **kwargs): super(TestCoinBase, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() self.alice = get_alice_xmss() self.alice.set_ots_index(11) @@ -37,18 +41,18 @@ def __init__(self, *args, **kwargs): self.maxDiff = None def test_create(self, m_logger): - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) self.assertIsInstance(tx, CoinBase) def test_to_json(self, m_logger): amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward - tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, amount, self.alice.address, self.mock_blockheader.block_number) txjson = tx.to_json() self.assertEqual(json.loads(test_json_CoinBase), json.loads(txjson)) def test_from_txdict(self, m_logger): amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward - tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, amount, self.alice.address, self.mock_blockheader.block_number) self.assertIsInstance(tx, CoinBase) # Test that common Transaction components were copied over. @@ -63,7 +67,7 @@ def test_validate_custom(self, m_logger): """ CoinBase _validate_custom() only checks if fee == 0 """ - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) tx._data.fee = 1 result = tx._validate_custom() self.assertFalse(result) @@ -79,75 +83,93 @@ def test_validate_extended(self, m_logger): 2. valid addr_to then calls _validate_custom() """ - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) tx._data.master_addr = self.alice.address - result = tx.validate_extended(self.mock_blockheader.block_number) + result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) self.assertFalse(result) tx._data.master_addr = config.dev.coinbase_address with patch('qrl.core.txs.CoinBase.CoinBase.addr_to', new_callable=PropertyMock) as m_addr_to: m_addr_to.return_value = b'Fake Address' - result = tx.validate_extended(self.mock_blockheader.block_number) + result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) self.assertFalse(result) - result = tx.validate_extended(self.mock_blockheader.block_number) + result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) self.assertTrue(result) - def test_apply_state_changes(self, m_logger): + def test_apply_coinbase_txn(self, m_logger): """ Alice earned some coins. """ addresses_state = { - config.dev.coinbase_address: Mock(autospec=AddressState, name='CoinBase AddressState', - transaction_hashes=[], balance=1000000), - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=0), + config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address), + self.alice.address: OptimizedAddressState.get_default(self.alice.address), } - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) - - tx.apply_state_changes(addresses_state) + addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000 + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=self.mock_blockheader.block_number, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + # self.state.apply(tx, addresses_state) + tx.apply(self.state, state_container) self.assertEqual(1000000 - tx.amount, addresses_state[config.dev.coinbase_address].balance) - self.assertEqual([tx.txhash], addresses_state[config.dev.coinbase_address].transaction_hashes) + + storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) self.assertEqual(tx.amount, addresses_state[self.alice.address].balance) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - # A blank addresses_state doesn't get modified at all (but in practice, every node should have an AddressState - # for the CoinBase addr - addresses_state_empty = {} - tx.apply_state_changes(addresses_state_empty) - self.assertEqual({}, addresses_state_empty) + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) - def test_revert_state_changes(self, m_logger): + def test_revert_coinbase_txn(self, m_logger): """ Alice earned some coins. Undo this. """ - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) addresses_state = { - config.dev.coinbase_address: Mock(autospec=AddressState, name='CoinBase AddressState', - transaction_hashes=[tx.txhash], balance=1000000 - self.amount), - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[tx.txhash], - balance=self.amount), + config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address), + self.alice.address: OptimizedAddressState.get_default(self.alice.address), } - unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - - tx.revert_state_changes(addresses_state, unused_chain_manager_mock) + addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000 + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=self.mock_blockheader.block_number, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) self.assertEqual(1000000, addresses_state[config.dev.coinbase_address].balance) - self.assertEqual([], addresses_state[config.dev.coinbase_address].transaction_hashes) + + storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) self.assertEqual(0, addresses_state[self.alice.address].balance) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - # A blank addresses_state doesn't get modified at all (but in practice, every node should have an AddressState - # for the CoinBase addr - addresses_state_empty = {} - tx.revert_state_changes(addresses_state_empty, unused_chain_manager_mock) - self.assertEqual({}, addresses_state_empty) + storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) def test_affected_address(self, m_logger): # This transaction can only involve 2 addresses. affected_addresses = set() - tx = CoinBase.create(self.amount, self.alice.address, self.mock_blockheader.block_number) + tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) tx.set_affected_address(affected_addresses) self.assertEqual(2, len(affected_addresses)) diff --git a/tests/core/txs/test_MessageTransaction.py b/tests/core/txs/test_MessageTransaction.py index 40a3ce669..d55d19622 100644 --- a/tests/core/txs/test_MessageTransaction.py +++ b/tests/core/txs/test_MessageTransaction.py @@ -4,8 +4,11 @@ from mock import patch, Mock, PropertyMock from pyqrllib.pyqrllib import bin2hstr -from qrl.core.AddressState import AddressState +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger +from qrl.core.StateContainer import StateContainer from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.core.txs.Transaction import Transaction from tests.core.txs.testdata import test_json_MessageTransaction, test_signature_MessageTransaction @@ -26,18 +29,21 @@ def setUp(self): self.params = { "message_hash": b'Test Message', + "addr_to": None, "fee": 1, "xmss_pk": self.alice.pk } def test_create(self, m_logger): tx = MessageTransaction.create(message_hash=b'Test Message', + addr_to=None, fee=1, xmss_pk=self.alice.pk) self.assertTrue(tx) def test_to_json(self, m_logger): tx = MessageTransaction.create(message_hash=b'Test Message', + addr_to=None, fee=1, xmss_pk=self.alice.pk) txjson = tx.to_json() @@ -74,13 +80,6 @@ def test_validate_tx(self, m_logger): self.assertTrue(tx.validate_or_raise()) def test_validate_tx2(self, m_logger): - self.params["message_hash"] = b'T' * 81 - - # Validation should fail, as we have entered a message of more than 80 lengths - with self.assertRaises(ValueError): - MessageTransaction.create(**self.params) - - def test_validate_tx3(self, m_logger): tx = Transaction.from_json(test_json_MessageTransaction) tx.sign(self.alice) @@ -106,39 +105,55 @@ def test_validate_extended(self, m_validate_slave, m_logger): 3. addr_from has enough funds for the fee 4. addr_from ots_key reuse """ - m_addr_from_state = Mock(autospec=AddressState, name='addr_from State', balance=100) + m_addr_from_state = Mock(autospec=OptimizedAddressState, name='addr_from State', balance=100) - m_addr_from_pk_state = Mock(autospec=AddressState, name='addr_from_pk State') + m_addr_from_pk_state = Mock(autospec=OptimizedAddressState, name='addr_from_pk State') m_addr_from_pk_state.ots_key_reuse.return_value = False + addresses_state = { + self.alice.address: m_addr_from_state + } + tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=None, + batch=None) + result = tx._validate_extended(state_container) self.assertTrue(result) - # Invalid master XMSS/slave XMSS relationship - m_validate_slave.return_value = False - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - m_validate_slave.return_value = True - # fee = -1 with patch('qrl.core.txs.MessageTransaction.MessageTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + result = tx._validate_extended(state_container) self.assertFalse(result) # balance = 0, cannot pay the Transaction fee m_addr_from_state.balance = 0 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + result = tx._validate_extended(state_container) self.assertFalse(result) m_addr_from_state.balance = 100 # addr_from_pk has used this OTS key before - m_addr_from_pk_state.ots_key_reuse.return_value = True - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) + # m_addr_from_pk_state.ots_key_reuse.return_value = True + # result = tx.validate_extended(m_addr_from_state, 0) + # self.assertFalse(result) + + self.params["message_hash"] = b'T' * 81 + + # Validation should fail, as we have entered a message of more than 80 lengths + tx = MessageTransaction.create(**self.params) + self.assertFalse(tx._validate_extended(state_container)) def test_set_affected_address(self, m_logger): result = set() diff --git a/tests/core/txs/test_MessageTransactionStateChanges.py b/tests/core/txs/test_MessageTransactionStateChanges.py index 6afe12df7..2b766489f 100644 --- a/tests/core/txs/test_MessageTransactionStateChanges.py +++ b/tests/core/txs/test_MessageTransactionStateChanges.py @@ -1,81 +1,89 @@ from unittest import TestCase -from mock import patch, Mock +from mock import Mock +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.ChainManager import ChainManager from qrl.core.txs.MessageTransaction import MessageTransaction -from tests.misc.helper import get_alice_xmss +from tests.misc.helper import get_alice_xmss, set_qrl_dir logger.initialize_default() -@patch('qrl.core.txs.Transaction.Transaction._revert_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.Transaction._apply_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.logger') class TestMessageTransactionStateChanges(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + self.addresses_state = { + self.alice.address: alice_address_state + } self.params = { "message_hash": b'Test Message', + "addr_to": None, "fee": 1, "xmss_pk": self.alice.pk } self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - def generate_addresses_state(self, tx): - addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=100), - } - return addresses_state - - def test_apply_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_apply_message_txn(self): tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 99) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) - m_apply_state_PK.assert_called_once() - - def test_apply_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_revert_message_txn(self): tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = {} - tx.apply_state_changes(addresses_state) - - self.assertEqual({}, addresses_state) - m_apply_state_PK.assert_called_once() - - def test_revert_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): - tx = MessageTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 100) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - - m_revert_state_PK.assert_called_once() - - def test_revert_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): - tx = MessageTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = {} - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) - - self.assertEqual({}, addresses_state) - m_revert_state_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - def test_validate_tx(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_validate_tx(self): tx = MessageTransaction.create(**self.params) tx.sign(self.alice) diff --git a/tests/core/txs/test_SimpleTransaction.py b/tests/core/txs/test_SimpleTransaction.py index 8ecaf8897..20c0d3ea6 100644 --- a/tests/core/txs/test_SimpleTransaction.py +++ b/tests/core/txs/test_SimpleTransaction.py @@ -4,14 +4,17 @@ from mock import patch, PropertyMock, Mock from pyqrllib.pyqrllib import bin2hstr +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState -from qrl.core.ChainManager import ChainManager +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.TransactionInfo import TransactionInfo from qrl.core.txs.Transaction import Transaction from qrl.core.txs.TransferTransaction import TransferTransaction from tests.core.txs.testdata import test_json_Simple, test_signature_Simple -from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, replacement_getTime +from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, replacement_getTime, set_qrl_dir logger.initialize_default() @@ -21,6 +24,9 @@ class TestSimpleTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestSimpleTransaction, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() @@ -32,14 +38,17 @@ def setUp(self): self.tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) + self.tx._data.nonce = 1 def test_create(self, m_logger): # Alice sending coins to Bob tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk) self.assertTrue(tx) @@ -48,6 +57,7 @@ def test_create_negative_amount(self, m_logger): with self.assertRaises(ValueError): TransferTransaction.create(addrs_to=[self.bob.address], amounts=[-100], + message_data=None, fee=1, xmss_pk=self.alice.pk) @@ -55,12 +65,14 @@ def test_create_negative_fee(self, m_logger): with self.assertRaises(ValueError): TransferTransaction.create(addrs_to=[self.bob.address], amounts=[-100], + message_data=None, fee=-1, xmss_pk=self.alice.pk) def test_to_json(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk) txjson = tx.to_json() @@ -103,6 +115,7 @@ def test_validate_tx2(self, m_logger): tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) @@ -120,6 +133,7 @@ def test_validate_tx3(self, m_logger): tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) @@ -187,35 +201,39 @@ def test_validate_extended(self, m_logger): 3. OTS key reuse from AddressState :return: """ - m_addr_state = Mock(autospec=AddressState, balance=200) - m_addr_from_pk_state = Mock(autospec=AddressState) - m_addr_from_pk_state.ots_key_reuse.return_value = False + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + addresses_state = { + self.alice.address: alice_address_state + } + alice_address_state.pbdata.balance = 200 self.tx.validate_slave = Mock(autospec=Transaction.validate_slave, return_value=True) self.tx.sign(self.alice) - - result = self.tx.validate_extended(m_addr_state, m_addr_from_pk_state) - + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + result = self.tx.validate_all(state_container) self.assertTrue(result) # Suppose there was ots key reuse. The function should then return false. - m_addr_from_pk_state.ots_key_reuse.return_value = True - result = self.tx.validate_extended(m_addr_state, m_addr_from_pk_state) - self.assertFalse(result) - - # Reset conditions from above - m_addr_from_pk_state.ots_key_reuse.return_value = False - # Suppose the slave XMSS address does not have permission for this type of Transaction. It should return False. - self.tx.validate_slave.return_value = False - result = self.tx.validate_extended(m_addr_state, m_addr_from_pk_state) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.tx.addr_from, self.tx.ots_key) + result = self.tx.validate_all(state_container) self.assertFalse(result) - # Reset conditions from above - self.tx.validate_slave.return_value = True # Suppose the address doesn't have enough coins. - m_addr_state.balance = 99 - result = self.tx.validate_extended(m_addr_state, m_addr_from_pk_state) + alice_address_state.pbdata.balance = 99 + state_container.paginated_bitfield.set_ots_key(addresses_state, self.tx.addr_from, self.tx.ots_key) + result = self.tx.validate_all(state_container) self.assertFalse(result) def test_validate_transaction_pool(self, m_logger): @@ -228,6 +246,7 @@ def test_validate_transaction_pool(self, m_logger): tx2 = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) @@ -249,6 +268,7 @@ def test_validate_transaction_pool_reusing_ots_index(self, m_logger): tx2 = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=5, xmss_pk=self.alice.pk ) @@ -276,6 +296,7 @@ def test_validate_transaction_pool_different_pk_same_ots_index(self, m_logger): tx2 = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.bob.pk ) @@ -290,87 +311,120 @@ def test_validate_transaction_pool_different_pk_same_ots_index(self, m_logger): result = tx.validate_transaction_pool(transaction_pool) self.assertTrue(result) - def test_apply_state_changes(self, m_logger): + def test_apply_transfer_txn(self, m_logger): """ apply_state_changes() is the part that actually updates everybody's balances. Then it forwards the addresses_state to _apply_state_changes_for_PK(), which updates everybody's addresses's nonce, OTS key index, and associated TX hashes If there is no AddressState for a particular Address, nothing is done. """ + self.tx.sign(self.alice) + ots_key = self.alice.ots_index - 1 addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=200), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) } - self.tx._apply_state_changes_for_PK = Mock(autospec=TransferTransaction._apply_state_changes_for_PK) - - self.tx.apply_state_changes(addresses_state) + addresses_state[self.alice.address].pbdata.balance = 200 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + self.tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) # Now Alice should have 99 coins left (200 - 100 - 1) and Bob should have 100 coins. self.assertEqual(99, addresses_state[self.alice.address].balance) self.assertEqual(100, addresses_state[self.bob.address].balance) - self.tx._apply_state_changes_for_PK.assert_called_once() - # If there are no AddressStates related to the Addresses in this transaction, do nothing. - self.tx._apply_state_changes_for_PK.reset_mock() - addresses_state_dummy = { - b'a': 'ABC', - b'b': 'DEF' - } - self.tx.apply_state_changes(addresses_state_dummy) - self.assertEqual(addresses_state_dummy, {b'a': 'ABC', b'b': 'DEF'}) - self.tx._apply_state_changes_for_PK.assert_called_once() - - def test_apply_state_changes_tx_sends_to_self(self, m_logger): + def test_apply_transfer_txn_tx_sends_to_self(self, m_logger): """ If you send coins to yourself, you should only lose the fee for the Transaction. """ addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=200), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) } + addresses_state[self.alice.address].pbdata.balance = 200 + tx = TransferTransaction.create( addrs_to=[self.alice.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) - tx._apply_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) - - tx.apply_state_changes(addresses_state) + tx.sign(self.alice) + ots_key = self.alice.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) self.assertEqual(199, addresses_state[self.alice.address].balance) - self.assertIn(tx.txhash, addresses_state[self.alice.address].transaction_hashes) + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(tx.txhash, state_container.paginated_tx_hash.key_value[storage_key]) - def test_apply_state_changes_multi_send(self, m_logger): + def test_apply_transfer_txn_multi_send(self, m_logger): """ Test that apply_state_changes() also works with multiple recipients. """ addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=200), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) } + addresses_state[self.alice.address].pbdata.balance = 200 tx_multisend = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[20, 20], + message_data=None, fee=1, xmss_pk=self.alice.pk ) - tx_multisend._apply_state_changes_for_PK = Mock(autospec=TransferTransaction._apply_state_changes_for_PK) - - tx_multisend.apply_state_changes(addresses_state) + tx_multisend.sign(self.alice) + ots_key = self.alice.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + tx_multisend.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) - # Now Alice should have 159 coins left (200 - 20 - 20 - 1) and Bob should have 100 coins. self.assertEqual(159, addresses_state[self.alice.address].balance) self.assertEqual(20, addresses_state[self.bob.address].balance) self.assertEqual(20, addresses_state[self.slave.address].balance) - tx_multisend._apply_state_changes_for_PK.assert_called_once() def test_apply_state_changes_for_PK(self, m_logger): """ @@ -380,15 +434,29 @@ def test_apply_state_changes_for_PK(self, m_logger): txs that address is associated with. :return: """ - addr_state = { - self.alice.address: Mock(autospec=AddressState) + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address) } - old_ots_index = self.alice.ots_index self.tx.sign(self.alice) - self.tx._apply_state_changes_for_PK(addr_state) - - addr_state[self.alice.address].increase_nonce.assert_called_once() - addr_state[self.alice.address].set_ots_key.assert_called_once_with(old_ots_index) + ots_key = self.alice.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + self.tx._apply_state_changes_for_PK(state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + + self.assertEqual(1, addresses_state[self.alice.address].nonce) def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger): """ @@ -398,162 +466,261 @@ def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger): tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address ) - addr_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState'), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState') + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) } - old_ots_index = self.slave.ots_index tx.sign(self.slave) - tx._apply_state_changes_for_PK(addr_state) - - addr_state[self.slave.address].increase_nonce.assert_called_once() - addr_state[self.slave.address].set_ots_key.assert_called_once_with(old_ots_index) - addr_state[self.slave.address].transaction_hashes.append.assert_called_once() - - def test_revert_state_changes(self, m_logger): + ots_key = self.slave.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.slave.address, ots_key)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, self.alice.ots_index)) + tx._apply_state_changes_for_PK(state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.slave.address, ots_key)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, self.alice.ots_index)) + + self.assertEqual(1, addresses_state[self.slave.address].nonce) + self.assertEqual(0, addresses_state[self.alice.address].nonce) + + def test_revert_transfer_txn(self, m_logger): """ Alice has sent 100 coins to Bob, using 1 as Transaction fee. Now we need to undo this. """ + self.tx.sign(self.alice) + ots_key = self.alice.ots_index - 1 + addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', - transaction_hashes=[self.tx.txhash], - balance=99), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[self.tx.txhash], - balance=100), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address) } - - unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - self.tx._revert_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) - - self.tx.revert_state_changes(addresses_state, unused_chain_manager_mock) + addresses_state[self.alice.address].pbdata.balance = 200 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, + self.alice.address, + ots_key) + state_container.paginated_bitfield.put_addresses_bitfield(None) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + ots_key)) + self.tx.apply(self.state, state_container) + self.tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, + ots_key)) + self.assertEqual(0, addresses_state[self.alice.address].nonce) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - self.tx._revert_state_changes_for_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - # If there are no AddressStates related to the Addresses in this transaction, do nothing. - self.tx._revert_state_changes_for_PK.reset_mock() - addresses_state_dummy = { - b'a': 'ABC', - b'b': 'DEF' - } - self.tx.revert_state_changes(addresses_state_dummy, unused_chain_manager_mock) - self.assertEqual(addresses_state_dummy, {b'a': 'ABC', b'b': 'DEF'}) - self.tx._revert_state_changes_for_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - def test_revert_state_changes_multi_send(self, m_logger): + def test_revert_transfer_txn_multi_send(self, m_logger): """ Alice has sent 20 coins to Bob and Slave each, using 1 as Transaction fee. Now we need to undo this. """ - addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', - transaction_hashes=[self.tx.txhash], - balance=159), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[self.tx.txhash], - balance=20), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', - transaction_hashes=[self.tx.txhash], balance=20) - } - unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - tx_multisend = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[20, 20], + message_data=None, fee=1, xmss_pk=self.alice.pk ) - tx_multisend._revert_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) + tx_multisend.sign(self.alice) + ots_key = self.alice.ots_index - 1 - tx_multisend.revert_state_changes(addresses_state, unused_chain_manager_mock) + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, ots_key) + state_container.paginated_bitfield.put_addresses_bitfield(None) + addresses_state[self.alice.address].pbdata.balance = 200 + addresses_state[self.bob.address].pbdata.balance = 0 + addresses_state[self.slave.address].pbdata.balance = 0 + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + tx_multisend.apply(self.state, state_container) + tx_multisend.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance) self.assertEqual(0, addresses_state[self.slave.address].balance) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - self.assertEqual([], addresses_state[self.slave.address].transaction_hashes) - tx_multisend._revert_state_changes_for_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - def test_revert_state_changes_tx_sends_to_self(self, m_logger): + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(self.slave.address, 1) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + def test_revert_transfer_txn_tx_sends_to_self(self, m_logger): """ Alice sent coins to herself, but she still lost the Transaction fee. Undo this. """ addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', - transaction_hashes=[self.tx.txhash], - balance=199), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], - balance=0), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.bob.address: OptimizedAddressState.get_default(self.bob.address) } - - unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') + addresses_state[self.alice.address].pbdata.balance = 200 tx = TransferTransaction.create( addrs_to=[self.alice.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) - - tx._revert_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) - - tx.revert_state_changes(addresses_state, unused_chain_manager_mock) + tx.sign(self.alice) + ots_key = self.alice.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, ots_key) + state_container.paginated_bitfield.put_addresses_bitfield(None) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - - tx._revert_state_changes_for_PK.assert_called_once() def test_revert_state_changes_for_PK(self, m_logger): """ This is just an undo function. :return: """ + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address) + } + addresses_state[self.alice.address].pbdata.balance = 101 + addresses_state[self.alice.address].pbdata.nonce = 1 + tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) - addr_state = { - self.alice.address: Mock(autospec=AddressState) - } tx.sign(self.alice) - tx._revert_state_changes_for_PK(addr_state, Mock(name='unused State Mock')) - - addr_state[self.alice.address].decrease_nonce.assert_called_once() - addr_state[self.alice.address].unset_ots_key.assert_called_once() + ots_key = self.alice.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, ots_key) + state_container.paginated_bitfield.put_addresses_bitfield(None) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) + tx._apply_state_changes_for_PK(state_container) + tx._revert_state_changes_for_PK(state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, ots_key)) def test_revert_state_changes_for_PK_master_slave_XMSS(self, m_logger): + addresses_state = { + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + self.slave.address: OptimizedAddressState.get_default(self.slave.address) + } + addresses_state[self.alice.address].pbdata.balance = 101 + addresses_state[self.slave.address].pbdata.nonce = 1 + tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], + message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address ) - addr_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState'), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState') - } tx.sign(self.slave) - tx._revert_state_changes_for_PK(addr_state, Mock(name='unused State Mock')) - - addr_state[self.slave.address].decrease_nonce.assert_called_once() - addr_state[self.slave.address].unset_ots_key.assert_called_once() - addr_state[self.slave.address].transaction_hashes.remove.assert_called_once() + ots_key = self.slave.ots_index - 1 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.slave.address, ots_key) + state_container.paginated_bitfield.put_addresses_bitfield(None) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.slave.address, ots_key)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, self.alice.ots_index)) + tx._apply_state_changes_for_PK(state_container) + tx._revert_state_changes_for_PK(state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.slave.address, ots_key)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, self.alice.ots_index)) def test_affected_address(self, m_logger): # The default transaction params involve only two addresses. @@ -566,6 +733,7 @@ def test_affected_address(self, m_logger): tx = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[100, 100], + message_data=None, fee=1, xmss_pk=self.alice.pk ) diff --git a/tests/core/txs/test_SlaveTransaction.py b/tests/core/txs/test_SlaveTransaction.py index 4bb050057..7abb48899 100644 --- a/tests/core/txs/test_SlaveTransaction.py +++ b/tests/core/txs/test_SlaveTransaction.py @@ -2,16 +2,22 @@ from mock import patch, Mock, PropertyMock -from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core import config +from qrl.core.Indexer import Indexer +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.SlaveTransaction import SlaveTransaction -from tests.misc.helper import get_alice_xmss, get_slave_xmss, get_bob_xmss - -logger.initialize_default() +from tests.misc.helper import get_alice_xmss, get_slave_xmss, get_bob_xmss, set_qrl_dir @patch('qrl.core.txs.Transaction.logger') class TestSlaveTransaction(TestCase): + def __init__(self, *args, **kwargs): + super(TestSlaveTransaction, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() + def setUp(self): self.alice = get_alice_xmss() self.slave = get_slave_xmss() @@ -36,19 +42,6 @@ def test_validate_custom(self, m_logger): 2. if len(slave_pks) != len(access_types) 3. access_types can only be 0, 1 """ - # We're going to need all the XMSS trees we can get here - bob = get_bob_xmss() - - # Too many slave_pks - with patch('qrl.core.txs.SlaveTransaction.config', autospec=True) as m_config: - m_config.dev.transaction_multi_output_limit = 2 - params = self.params.copy() - params["slave_pks"] = [self.alice.pk, bob.pk, self.slave.pk] - params["access_types"] = [0, 0, 0] - - with self.assertRaises(ValueError): - SlaveTransaction.create(**params) - # Unequal length slave_pks and access_types params = self.params.copy() params["slave_pks"] = [self.slave.pk] @@ -71,40 +64,70 @@ def test_validate_extended(self, m_validate_slave, m_logger): 3. addr_from has enough funds for the fee 4. addr_from ots_key reuse """ - m_addr_from_state = Mock(autospec=AddressState, name='addr_from State', balance=100) - - m_addr_from_pk_state = Mock(autospec=AddressState, name='addr_from_pk State') - m_addr_from_pk_state.ots_key_reuse.return_value = False + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + addresses_state = { + alice_address_state.address: alice_address_state + } tx = SlaveTransaction.create(**self.params) tx.sign(self.alice) - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + result = tx._validate_extended(state_container) self.assertTrue(result) # Invalid master XMSS/slave XMSS relationship m_validate_slave.return_value = False - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + result = tx.validate_all(state_container) self.assertFalse(result) m_validate_slave.return_value = True # fee = -1 with patch('qrl.core.txs.SlaveTransaction.SlaveTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + result = tx._validate_extended(state_container) self.assertFalse(result) # balance = 0, cannot pay the Transaction fee - m_addr_from_state.balance = 0 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + alice_address_state.pbdata.balance = 0 + result = tx._validate_extended(state_container) self.assertFalse(result) - m_addr_from_state.balance = 100 + alice_address_state.pbdata.balance = 100 + addresses_state = { + self.alice.address: alice_address_state + } # addr_from_pk has used this OTS key before - m_addr_from_pk_state.ots_key_reuse.return_value = True - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + state_container.paginated_bitfield.set_ots_key(addresses_state, alice_address_state.address, tx.ots_key) + result = tx.validate_all(state_container) self.assertFalse(result) + bob = get_bob_xmss() + # Too many slave_pks + with patch('qrl.core.config', autospec=True) as m_config: + m_config.dev = config.dev.create(config.dev.prev_state_key, config.dev.current_state_key, + b'', 10, True, True) + m_config.dev.pbdata.transaction.multi_output_limit = 2 + state_container.current_dev_config = m_config.dev + params = self.params.copy() + params["slave_pks"] = [self.alice.pk, bob.pk, self.slave.pk] + params["access_types"] = [0, 0, 0] + + tx = SlaveTransaction.create(**params) + self.assertFalse(tx._validate_extended(state_container)) + def test_validate_tx(self, m_logger): tx = SlaveTransaction.create(**self.params) tx.sign(self.alice) diff --git a/tests/core/txs/test_SlaveTransactionStateChanges.py b/tests/core/txs/test_SlaveTransactionStateChanges.py index 05f531c75..45eaf91b1 100644 --- a/tests/core/txs/test_SlaveTransactionStateChanges.py +++ b/tests/core/txs/test_SlaveTransactionStateChanges.py @@ -1,23 +1,35 @@ from unittest import TestCase -from mock import patch, Mock +from mock import Mock +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.ChainManager import ChainManager from qrl.core.txs.SlaveTransaction import SlaveTransaction -from tests.misc.helper import get_alice_xmss, get_slave_xmss +from qrl.generated.qrl_pb2 import SlaveMetadata +from tests.misc.helper import get_alice_xmss, get_slave_xmss, set_qrl_dir logger.initialize_default() -@patch('qrl.core.txs.Transaction.Transaction._revert_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.Transaction._apply_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.logger') class TestSlaveTransactionStateChanges(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() self.slave = get_slave_xmss() + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + self.addresses_state = { + self.alice.address: alice_address_state, + self.slave.address: OptimizedAddressState.get_default(self.slave.address) + } + self.params = { "slave_pks": [self.slave.pk], "access_types": [0], @@ -26,59 +38,63 @@ def setUp(self): } self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - def generate_addresses_state(self, tx): - addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], - balance=100), - self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], - balance=0), - } - return addresses_state - - def test_apply_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_apply_slave_txn(self): tx = SlaveTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 99) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.slave.address].transaction_hashes) - addresses_state[self.alice.address].add_slave_pks_access_type.assert_called_once() - addresses_state[self.slave.address].add_slave_pks_access_type.assert_not_called() - m_apply_state_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) - def test_apply_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): - tx = SlaveTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = {} - tx.apply_state_changes(addresses_state) + self.assertIn((tx.addr_from, tx.slave_pks[0]), state_container.slaves.data) + data = state_container.slaves.data[(tx.addr_from, tx.slave_pks[0])] + self.assertIsInstance(data, SlaveMetadata) + self.assertEqual(tx.access_types[0], data.access_type) + self.assertEqual(tx.txhash, data.tx_hash) - self.assertEqual({}, addresses_state) - m_apply_state_PK.assert_called_once() - - def test_revert_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_revert_slave_txn(self): tx = SlaveTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 100) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.slave.address].transaction_hashes) - addresses_state[self.alice.address].remove_slave_pks_access_type.assert_called_once() - addresses_state[self.slave.address].remove_slave_pks_access_type.assert_not_called() - - m_revert_state_PK.assert_called_once() - - def test_revert_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): - tx = SlaveTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = {} - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) - - self.assertEqual({}, addresses_state) - m_revert_state_PK.assert_called_once() + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertIn((tx.addr_from, tx.slave_pks[0]), state_container.slaves.data) + data = state_container.slaves.data[(tx.addr_from, tx.slave_pks[0])] + self.assertIsInstance(data, SlaveMetadata) + self.assertEqual(tx.access_types[0], data.access_type) + self.assertEqual(tx.txhash, data.tx_hash) diff --git a/tests/core/txs/test_TokenTransaction.py b/tests/core/txs/test_TokenTransaction.py index e092cb6a9..1a6c8007d 100644 --- a/tests/core/txs/test_TokenTransaction.py +++ b/tests/core/txs/test_TokenTransaction.py @@ -4,13 +4,17 @@ from mock import patch, PropertyMock, Mock from pyqrllib.pyqrllib import bin2hstr +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.TokenTransaction import TokenTransaction from qrl.core.txs.Transaction import Transaction from qrl.generated import qrl_pb2 from tests.core.txs.testdata import test_json_Token, test_signature_Token -from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss +from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, set_qrl_dir logger.initialize_default() @@ -20,6 +24,8 @@ class TestTokenTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestTokenTransaction, self).__init__(*args, **kwargs) + with set_qrl_dir('no_data'): + self.state = State() self.alice = get_alice_xmss() self.bob = get_bob_xmss() self._decimals = 15 @@ -169,31 +175,151 @@ def test_validate_tx4(self, m_logger): with self.assertRaises(ValueError): tx.validate_or_raise() - def test_validate_custom(self, m_logger): + # def test_validate_custom(self, m_logger): + # # Token symbol too long + # with self.assertRaises(ValueError): + # tx = self.make_tx(symbol=b'QRLSQRLSQRL') + # tx.sign(self.alice) + # + # # Token name too long + # with self.assertRaises(ValueError): + # tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum') + # tx.sign(self.alice) + # + # # Token symbol missing + # with self.assertRaises(ValueError): + # tx = self.make_tx(symbol=b'') + # tx.sign(self.alice) + # + # # Token name missing + # with self.assertRaises(ValueError): + # tx = self.make_tx(name=b'') + # tx.sign(self.alice) + # + # # Empty initial_balances + # with self.assertRaises(ValueError): + # tx = self.make_tx(initial_balances=[]) + # tx.sign(self.alice) + # + # # Invalid initial balances... 0! + # with self.assertRaises(ValueError): + # initial_balances_0_0 = [qrl_pb2.AddressAmount(address=self.alice.address, amount=0), + # qrl_pb2.AddressAmount(address=self.bob.address, amount=0)] + # tx = self.make_tx(initial_balances=initial_balances_0_0) + # tx.sign(self.alice) + # + # # Fee is -1 + # with patch('qrl.core.txs.TokenTransaction.TokenTransaction.fee', new_callable=PropertyMock) as m_fee: + # m_fee.return_value = -1 + # with self.assertRaises(ValueError): + # tx = self.make_tx() + # tx.sign(self.alice) + # + # # Invalid initial balances... -1! + # # tx = self.make_tx() + # # tx.sign(self.alice) + # # with patch('qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances', new_callable=PropertyMock) as m_i_balances: + # # m_i_balances.return_value = [-1, -1] + # # with self.assertRaises(ValueError): + # # tx.validate_or_raise() + + @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) + def test_validate_extended(self, m_validate_slave, m_logger): + """ + TokenTransaction.validate_extended checks for: + 1. valid master/slave + 2. from address is valid + 3. owner address is valid + 4. addresses that own the initial balances are valid + 5. that the AddressState has enough coins to pay the Transaction fee (because no coins are being transferred) + 6. OTS key reuse + """ + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + + tx = TokenTransaction.create(**self.params) + tx.sign(self.alice) + addresses_state = { + alice_address_state.address: alice_address_state + } + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + result = tx._validate_extended(state_container) + self.assertTrue(result) + + m_validate_slave.return_value = False + result = tx.validate_all(state_container) + self.assertFalse(result) + m_validate_slave.return_value = True + + with patch('qrl.core.txs.TokenTransaction.TokenTransaction.addr_from', + new_callable=PropertyMock) as m_addr_from: + m_addr_from.return_value = b'Invalid Address' + result = tx._validate_extended(state_container) + self.assertFalse(result) + + with patch('qrl.core.txs.TokenTransaction.TokenTransaction.owner', new_callable=PropertyMock) as m_owner: + m_owner.return_value = b'Invalid Address' + result = tx._validate_extended(state_container) + self.assertFalse(result) + + with patch('qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances', + new_callable=PropertyMock) as m_address_balance: + m_address_balance.return_value = [qrl_pb2.AddressAmount(address=b'Invalid Address 1', amount=1000), + qrl_pb2.AddressAmount(address=b'Invalid Address 2', amount=1000)] + result = tx._validate_extended(state_container) + self.assertFalse(result) + + alice_address_state.pbdata.balance = 0 + result = tx._validate_extended(state_container) + self.assertFalse(result) + alice_address_state.pbdata.balance = 100 + + addresses_state = { + self.alice.address: alice_address_state + } + # addr_from_pk has used this OTS key before + state_container.paginated_bitfield.set_ots_key(addresses_state, alice_address_state.address, tx.ots_key) + result = tx.validate_all(state_container) + self.assertFalse(result) + # Token symbol too long - with self.assertRaises(ValueError): - tx = self.make_tx(symbol=b'QRLSQRLSQRL') - tx.sign(self.alice) + tx = self.make_tx(symbol=b'QRLSQRLSQRL') + tx.sign(self.alice) + self.assertFalse(tx._validate_extended(state_container)) # Token name too long - with self.assertRaises(ValueError): - tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum') - tx.sign(self.alice) + tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum') + tx.sign(self.alice) + self.assertFalse(tx._validate_extended(state_container)) # Token symbol missing with self.assertRaises(ValueError): tx = self.make_tx(symbol=b'') tx.sign(self.alice) + self.assertFalse(tx._validate_extended(state_container)) # Token name missing with self.assertRaises(ValueError): tx = self.make_tx(name=b'') tx.sign(self.alice) + tx._validate_extended(state_container) # Empty initial_balances with self.assertRaises(ValueError): tx = self.make_tx(initial_balances=[]) tx.sign(self.alice) + self.assertFalse(tx._validate_extended(state_container)) # Invalid initial balances... 0! with self.assertRaises(ValueError): @@ -201,6 +327,7 @@ def test_validate_custom(self, m_logger): qrl_pb2.AddressAmount(address=self.bob.address, amount=0)] tx = self.make_tx(initial_balances=initial_balances_0_0) tx.sign(self.alice) + self.assertFalse(tx._validate_extended(state_container)) # Fee is -1 with patch('qrl.core.txs.TokenTransaction.TokenTransaction.fee', new_callable=PropertyMock) as m_fee: @@ -217,58 +344,6 @@ def test_validate_custom(self, m_logger): # with self.assertRaises(ValueError): # tx.validate_or_raise() - @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) - def test_validate_extended(self, m_validate_slave, m_logger): - """ - TokenTransaction.validate_extended checks for: - 1. valid master/slave - 2. from address is valid - 3. owner address is valid - 4. addresses that own the initial balances are valid - 5. that the AddressState has enough coins to pay the Transaction fee (because no coins are being transferred) - 6. OTS key reuse - """ - tx = TokenTransaction.create(**self.params) - - m_addr_from_state = Mock(autospec=AddressState, name='addr_from State', balance=100) - m_addr_from_pk_state = Mock(autospec=AddressState, name='addr_from_pk State') - m_addr_from_pk_state.ots_key_reuse.return_value = False - tx.sign(self.alice) - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertTrue(result) - - m_validate_slave.return_value = False - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - - m_validate_slave.return_value = True - with patch('qrl.core.txs.TokenTransaction.TokenTransaction.addr_from', - new_callable=PropertyMock) as m_addr_from: - m_addr_from.return_value = b'Invalid Address' - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - - with patch('qrl.core.txs.TokenTransaction.TokenTransaction.owner', new_callable=PropertyMock) as m_owner: - m_owner.return_value = b'Invalid Address' - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - - with patch('qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances', - new_callable=PropertyMock) as m_address_balance: - m_address_balance.return_value = [qrl_pb2.AddressAmount(address=b'Invalid Address 1', amount=1000), - qrl_pb2.AddressAmount(address=b'Invalid Address 2', amount=1000)] - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - - m_addr_from_state.balance = 0 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - m_addr_from_state.balance = 100 - - m_addr_from_pk_state.ots_key_reuse.return_value = True - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) - self.assertFalse(result) - def test_affected_address(self, m_logger): tx = TokenTransaction.create(**self.params) # Default params should result in 2 affected addresses diff --git a/tests/core/txs/test_TokenTransactionStateChanges.py b/tests/core/txs/test_TokenTransactionStateChanges.py index f52088fbe..96839942e 100644 --- a/tests/core/txs/test_TokenTransactionStateChanges.py +++ b/tests/core/txs/test_TokenTransactionStateChanges.py @@ -1,24 +1,36 @@ from unittest import TestCase -from mock import patch, Mock -from pyqrllib.pyqrllib import bin2hstr +from mock import Mock +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.ChainManager import ChainManager from qrl.core.txs.TokenTransaction import TokenTransaction from qrl.generated import qrl_pb2 -from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss +from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, set_qrl_dir logger.initialize_default() -@patch('qrl.core.txs.Transaction.logger') class TestTokenTransactionStateChanges(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() self.bob = get_bob_xmss() + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + self.addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: OptimizedAddressState.get_default(self.bob.address) + } + self.params = { "symbol": b'QRL', "name": b'Quantum Resistant Ledger', @@ -31,62 +43,57 @@ def setUp(self): self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - def generate_addresses_state(self, tx): - addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', - tokens={bin2hstr(tx.txhash): 0}, transaction_hashes=[], - balance=100), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', tokens={bin2hstr(tx.txhash): 0}, - transaction_hashes=[], - balance=0), - } - return addresses_state - - def test_apply_state_changes(self, m_logger): + def test_apply_token_txn(self): """ Alice creates a token. Obviously, she gives herself some of this token. But she also gives Bob some tokens too. """ initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] + qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)] self.params["initial_balances"] = initial_balances tx = TokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) + addresses_state = dict(self.addresses_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) # According to the State, Alice has 100 coins, and Bob has 0 coins. # After applying the Transaction, Alice and Bob should have 1000 tokens, and Alice's balance should be 99. # AddressState.transaction_hashes now also reference the TokenTransaction that created the Tokens. - tx.apply_state_changes(addresses_state) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 99) self.assertEqual(addresses_state[self.bob.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(tx.txhash, 1000) - addresses_state[self.bob.address].update_token_balance.assert_called_with(tx.txhash, 1000) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[self.bob.address].transaction_hashes) - addresses_state[self.alice.address].increase_nonce.assert_called_once() - addresses_state[self.alice.address].set_ots_key.assert_called_once() - addresses_state[self.bob.address].increase_nonce.assert_not_called() - addresses_state[self.bob.address].set_ots_key.assert_not_called() - - def test_apply_state_changes_empty_addresses_state(self, m_logger): - """ - After applying the Transaction, Alice and Bob should have 1000 tokens, and Alice's balance should be 99. - AddressState.transaction_hashes now also reference the TokenTransaction that created the Tokens. - """ - initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] - self.params["initial_balances"] = initial_balances - addresses_state_empty = {} - tx = TokenTransaction.create(**self.params) - tx.sign(self.alice) + self.assertEqual(2, len(state_container.paginated_tx_hash.key_value)) - tx.apply_state_changes(addresses_state_empty) - self.assertEqual(addresses_state_empty, {}) + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) - def test_apply_state_changes_owner_not_in_address_state(self, m_logger): + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertEqual(2, len(state_container.tokens.data)) + self.assertIn((self.alice.address, tx.txhash), state_container.tokens.data) + self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + + def test_apply_state_changes_owner_not_in_address_state(self): """ In this case, Alice didn't give herself any tokens. How generous! She gave them all to Bob. """ @@ -97,25 +104,45 @@ def test_apply_state_changes_owner_not_in_address_state(self, m_logger): tx.sign(self.alice) # Signing the TX also generates the txhash, which we need to generate the AddressState properly. - addresses_state = self.generate_addresses_state(tx) - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 99) self.assertEqual(addresses_state[self.bob.address].balance, 0) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[self.bob.address].transaction_hashes) - addresses_state[self.alice.address].increase_nonce.assert_called_once() - addresses_state[self.alice.address].set_ots_key.assert_called_once() - addresses_state[self.bob.address].increase_nonce.assert_not_called() - addresses_state[self.bob.address].set_ots_key.assert_not_called() - - def test_apply_state_changes_signed_by_slave_xmss(self, m_logger): + + self.assertEqual(2, len(state_container.paginated_tx_hash.key_value)) + + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertEqual(1, len(state_container.tokens.data)) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(1000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + + def test_apply_token_txn_signed_by_slave_xmss(self): """ Alice creates a token, gives herself and Bob some tokens. But she uses a XMSS slave to sign it. """ initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] + qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)] slave = get_slave_xmss() self.params["initial_balances"] = initial_balances self.params["xmss_pk"] = slave.pk @@ -125,74 +152,100 @@ def test_apply_state_changes_signed_by_slave_xmss(self, m_logger): # Now that we have the Slave XMSS address, we should add it to AddressState so that apply_state_changes() # can do something with it - addresses_state = self.generate_addresses_state(tx) - addresses_state[slave.address] = Mock(autospec=AddressState, - name='slave AddressState', - tokens={bin2hstr(tx.txhash): 0}, - transaction_hashes=[], - balance=0) - - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address) + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + tx.apply(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 99) - addresses_state[self.alice.address].update_token_balance.assert_called_with(tx.txhash, 1000) - addresses_state[self.bob.address].update_token_balance.assert_called_with(tx.txhash, 1000) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[slave.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[self.bob.address].transaction_hashes) - addresses_state[slave.address].increase_nonce.assert_called_once() - addresses_state[slave.address].set_ots_key.assert_called_once() - addresses_state[self.alice.address].increase_nonce.assert_not_called() - addresses_state[self.alice.address].set_ots_key.assert_not_called() - - def test_revert_state_changes(self, m_logger): + self.assertEqual(3, len(state_container.paginated_tx_hash.key_value)) + + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(slave.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertEqual(2, len(state_container.tokens.data)) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance) + self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.bob.address, 0)) + + def test_revert_token_txn(self): """ Same setup as in test_apply_state_changes(). This time though, the changes have already been applied, and we would like to roll them back. """ initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] + qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)] self.params["initial_balances"] = initial_balances tx = TokenTransaction.create(**self.params) tx.sign(self.alice) # Apply the changes! - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].tokens[bin2hstr(tx.txhash)] = 1000 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - addresses_state[self.bob.address].tokens[bin2hstr(tx.txhash)] = 1000 - addresses_state[self.bob.address].transaction_hashes = [tx.txhash] + tx = TokenTransaction.create(**self.params) + tx.sign(self.alice) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) # After applying the Transaction, it should be as if Alice had never created the tokens in the first place. - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(tx.txhash, -1000) - addresses_state[self.bob.address].update_token_balance.assert_called_with(tx.txhash, -1000) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - addresses_state[self.alice.address].decrease_nonce.assert_called_once() - addresses_state[self.alice.address].unset_ots_key.assert_called_once() - addresses_state[self.bob.address].decrease_nonce.assert_not_called() - addresses_state[self.bob.address].unset_ots_key.assert_not_called() - - def test_revert_state_changes_empty_addresses_state(self, m_logger): - """If we didn't have any AddressStates for the addresses involved in this test, do nothing""" - initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] - self.params["initial_balances"] = initial_balances - tx = TokenTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = {} + self.assertEqual(2, len(state_container.paginated_tx_hash.key_value)) - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - self.assertEqual(addresses_state, {}) + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) - def test_revert_state_changes_owner_not_in_address_state(self, m_logger): + self.assertEqual(2, len(state_container.tokens.data)) + self.assertIn((self.alice.address, tx.txhash), state_container.tokens.data) + self.assertEqual(0, state_container.tokens.data[(self.alice.address, tx.txhash)].balance) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(0, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + self.assertEqual(0, addresses_state[self.alice.address].nonce) + + def test_revert_token_txn_owner_not_in_address_state(self): """ In this case, Alice didn't give herself any tokens. How generous! She gave them all to Bob. But we want to revert this. @@ -203,33 +256,53 @@ def test_revert_state_changes_owner_not_in_address_state(self, m_logger): tx = TokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - addresses_state[self.bob.address].tokens[bin2hstr(tx.txhash)] = 1000 - addresses_state[self.bob.address].transaction_hashes = [tx.txhash] - - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_not_called() - addresses_state[self.bob.address].update_token_balance.assert_called_with(tx.txhash, -1000) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - addresses_state[self.alice.address].decrease_nonce.assert_called_once() - addresses_state[self.alice.address].unset_ots_key.assert_called_once() - addresses_state[self.bob.address].decrease_nonce.assert_not_called() - addresses_state[self.bob.address].unset_ots_key.assert_not_called() - - def test_revert_state_changes_signed_by_slave_xmss(self, m_logger): + + self.assertEqual(2, len(state_container.paginated_tx_hash.key_value)) + + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertEqual(1, len(state_container.tokens.data)) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(0, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + + def test_revert_token_txn_signed_by_slave_xmss(self): """ Alice creates a token, gives herself and Bob some tokens. But she uses a XMSS slave to sign it. Can we undo it? """ initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), - qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] + qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)] slave = get_slave_xmss() self.params["initial_balances"] = initial_balances self.params["xmss_pk"] = slave.pk @@ -239,35 +312,56 @@ def test_revert_state_changes_signed_by_slave_xmss(self, m_logger): # Now that we have the Slave XMSS address, we should add it to AddressState so that apply_state_changes() # can do something with it - addresses_state = self.generate_addresses_state(tx) - addresses_state[slave.address] = Mock(autospec=AddressState, - name='slave AddressState', - tokens={bin2hstr(tx.txhash): 0}, - transaction_hashes=[], - balance=0) - # Also, update the AddressStates manually! - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - addresses_state[self.alice.address].tokens[bin2hstr(tx.txhash)] = 1000 - addresses_state[self.bob.address].balance = 0 - addresses_state[self.bob.address].transaction_hashes = [tx.txhash] - addresses_state[self.bob.address].tokens[bin2hstr(tx.txhash)] = 1000 - addresses_state[slave.address].transaction_hashes = [tx.txhash] + addresses_state = dict(self.addresses_state) + addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address) + addresses_state[slave.address].pbdata.nonce = 1 - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + # Also, update the AddressStates manually! + addresses_state[self.alice.address].pbdata.balance = 100 + addresses_state[self.bob.address].pbdata.balance = 0 + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, slave.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) - addresses_state[self.alice.address].update_token_balance.assert_called_with(tx.txhash, -1000) - addresses_state[self.bob.address].update_token_balance.assert_called_with(tx.txhash, -1000) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[slave.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - addresses_state[slave.address].decrease_nonce.assert_called_once() - addresses_state[slave.address].unset_ots_key.assert_called_once() - addresses_state[self.alice.address].decrease_nonce.assert_not_called() - addresses_state[self.alice.address].unset_ots_key.assert_not_called() - - def test_validate_tx(self, m_logger): + self.assertEqual(3, len(state_container.paginated_tx_hash.key_value)) + + storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + storage_key = state_container.paginated_tx_hash.generate_key(slave.address, 1) + self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) + self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key]) + + self.assertEqual(2, len(state_container.tokens.data)) + self.assertIn((self.alice.address, tx.txhash), state_container.tokens.data) + self.assertEqual(0, state_container.tokens.data[(self.alice.address, tx.txhash)].balance) + self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) + self.assertEqual(0, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.bob.address, 0)) + + def test_validate_tx(self): initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] slave = get_slave_xmss() diff --git a/tests/core/txs/test_TransactionValidateSlave.py b/tests/core/txs/test_TransactionValidateSlave.py index 0dc091ac6..e358fc2c4 100644 --- a/tests/core/txs/test_TransactionValidateSlave.py +++ b/tests/core/txs/test_TransactionValidateSlave.py @@ -2,10 +2,14 @@ from mock import patch, Mock +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.MessageTransaction import MessageTransaction -from tests.misc.helper import get_alice_xmss, get_bob_xmss +from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_qrl_dir logger.initialize_default() @@ -13,26 +17,30 @@ @patch('qrl.core.txs.Transaction.logger') class TestTransactionValidateSlave(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() self.params = { "message_hash": b'Test Message', + "addr_to": None, "fee": 1, "xmss_pk": self.alice.pk } - self.m_addr_state = Mock(autospec=AddressState, name='addr_state', balance=200) - self.m_addr_from_pk_state = Mock(autospec=AddressState, name='addr_from_pk_state') + self.m_addr_state = Mock(autospec=OptimizedAddressState, name='addr_state', balance=200) + self.m_addr_from_pk_state = Mock(autospec=OptimizedAddressState, name='addr_from_pk_state') def test_validate_slave_valid(self, m_logger): tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - result = tx.validate_slave(self.m_addr_state, self.m_addr_from_pk_state) + result = tx.validate_slave(0) self.assertTrue(result) def test_validate_slave_master_addr_same_as_signing_addr(self, m_logger): self.params["master_addr"] = self.alice.address tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - result = tx.validate_slave(self.m_addr_state, self.m_addr_from_pk_state) + result = tx.validate_slave(None) self.assertFalse(result) def test_validate_slave_signing_xmss_state_has_no_slave_permissions_in_state(self, m_logger): @@ -42,35 +50,19 @@ def test_validate_slave_signing_xmss_state_has_no_slave_permissions_in_state(sel self.params["xmss_pk"] = bob.pk # We need to add extra data to the mock AddressState. - self.m_addr_state.slave_pks_access_type = {} tx = MessageTransaction.create(**self.params) tx.sign(self.alice) - result = tx.validate_slave(self.m_addr_state, self.m_addr_from_pk_state) + state_container = StateContainer(addresses_state=dict(), + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + result = tx.validate_slave(state_container) self.assertFalse(result) - - def test_validate_slave_has_insufficient_permissions(self, m_logger): - """ - Master's AddressState says the Slave has permission 0. - But Slave's AddressState says the Slave is good for permission 2. - Therefore the Slave does not have enough permissions. - """ - bob = get_bob_xmss() - # Let's say Alice is Bob's master. - self.params["master_addr"] = self.alice.address - self.params["xmss_pk"] = bob.pk - - tx = MessageTransaction.create(**self.params) - tx.sign(self.alice) - - # The master's state says the slave can have these permissions. - self.m_addr_state.slave_pks_access_type = {str(tx.PK): 0} - # The signing slave's state can be 0 (full permissions) or 1 (mining only) but only 0 is used for now. - # Let's give an invalid number. - self.m_addr_from_pk_state.slave_pks_access_type = {str(tx.PK): 2} - result = tx.validate_slave(self.m_addr_state, self.m_addr_from_pk_state) - self.assertFalse(result) - - # Let's give a valid number, that matches what the master's state says (0) - self.m_addr_from_pk_state.slave_pks_access_type = {str(tx.PK): 0} - result = tx.validate_slave(self.m_addr_state, self.m_addr_from_pk_state) - self.assertTrue(result) diff --git a/tests/core/txs/test_TransferTokenTransaction.py b/tests/core/txs/test_TransferTokenTransaction.py index 1ba7ecd41..424700ff2 100644 --- a/tests/core/txs/test_TransferTokenTransaction.py +++ b/tests/core/txs/test_TransferTokenTransaction.py @@ -4,12 +4,16 @@ from mock import patch, PropertyMock, Mock from pyqrllib.pyqrllib import bin2hstr +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer from qrl.core.txs.Transaction import Transaction from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction from tests.core.txs.testdata import test_json_TransferToken, test_signature_TransferToken -from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss +from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, set_qrl_dir logger.initialize_default() @@ -18,6 +22,8 @@ class TestTransferTokenTransaction(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() self.alice = get_alice_xmss() self.bob = get_bob_xmss() @@ -142,16 +148,6 @@ def test_state_validate_tx_custom(self, m_logger): with self.assertRaises(ValueError): tx.validate_or_raise() - params = self.default_params() - params["addrs_to"] = [self.bob.address, slave.address, self.alice.address] - params["amounts"] = [2, 3, 5] - tx = TransferTokenTransaction.create(**params) - tx.sign(self.alice) - with patch('qrl.core.txs.TransferTokenTransaction.config', autospec=True) as m_config: - m_config.dev.transaction_multi_output_limit = 1 - with self.assertRaises(ValueError): - tx.validate_or_raise() - # TX signing already fails if addrs_to and amounts are unequal length params = self.default_params() tx = TransferTokenTransaction.create(**params) @@ -184,23 +180,39 @@ def test_validate_extended(self, m_validate_slave, m_logger): 5. if addr_from has enough tokens 6. addr_from ots_key reuse """ - m_addr_from_state = Mock(autospec=AddressState, name='addr_from State', balance=100) - m_addr_from_state.is_token_exists.return_value = True - m_addr_from_state.get_token_balance.return_value = 1000 - - m_addr_from_pk_state = Mock(autospec=AddressState, name='addr_from_pk State') - m_addr_from_pk_state.ots_key_reuse.return_value = False + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + addresses_state = { + alice_address_state.address: alice_address_state + } + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + result = tx._validate_extended(state_container) self.assertTrue(result) # Invalid master XMSS/slave XMSS relationship m_validate_slave.return_value = False - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + state_container.tokens = Indexer(b'token', None) + state_container.tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + result = tx.validate_all(state_container) self.assertFalse(result) m_validate_slave.return_value = True @@ -208,39 +220,66 @@ def test_validate_extended(self, m_validate_slave, m_logger): with patch('qrl.core.txs.TransferTokenTransaction.TransferTokenTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + state_container.tokens = tokens + result = tx._validate_extended(state_container) self.assertFalse(result) # total_amount = -1 with patch('qrl.core.txs.TransferTokenTransaction.TransferTokenTransaction.total_amount', new_callable=PropertyMock) as m_total_amount: m_total_amount.return_value = -100 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + state_container.tokens = tokens + result = tx._validate_extended(state_container) self.assertFalse(result) # balance = 0, cannot pay the Transaction fee - m_addr_from_state.balance = 0 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + alice_address_state.pbdata.balance = 0 + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + state_container.tokens = tokens + result = tx._validate_extended(state_container) self.assertFalse(result) - m_addr_from_state.balance = 100 + alice_address_state.pbdata.balance = 100 # addr_from doesn't have these tokens - m_addr_from_state.is_token_exists.return_value = False - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + state_container.tokens = Indexer(b'token', None) + result = tx._validate_extended(state_container) self.assertFalse(result) - m_addr_from_state.is_token_exists.return_value = True # addr_from doesn't have enough tokens - m_addr_from_state.get_token_balance.return_value = 99 - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = 99 + state_container.tokens = tokens + result = tx._validate_extended(state_container) self.assertFalse(result) - m_addr_from_state.get_token_balance.return_value = 1000 # addr_from_pk has used this OTS key before - m_addr_from_pk_state.ots_key_reuse.return_value = True - result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state) + addresses_state = { + self.alice.address: alice_address_state + } + state_container.addresses_state = addresses_state + # addr_from_pk has used this OTS key before + state_container.paginated_bitfield.set_ots_key(addresses_state, alice_address_state.address, tx.ots_key) + result = tx.validate_all(state_container) self.assertFalse(result) + slave = get_slave_xmss() + params = self.default_params() + params["addrs_to"] = [self.bob.address, slave.address, self.alice.address] + params["amounts"] = [2, 3, 5] + tx = TransferTokenTransaction.create(**params) + tx.sign(self.alice) + with patch('qrl.core.config', autospec=True) as m_config: + m_config.dev = config.dev.create(config.dev.prev_state_key, config.dev.current_state_key, + b'', 10, True, True) + m_config.dev.pbdata.transaction.multi_output_limit = 1 + state_container.current_dev_config = m_config.dev + self.assertFalse(tx._validate_extended(state_container=state_container)) + def test_set_affected_address(self, m_logger): result = set() params = self.default_params() diff --git a/tests/core/txs/test_TransferTokenTransactionStateChanges.py b/tests/core/txs/test_TransferTokenTransactionStateChanges.py index bb278c909..03483ed6d 100644 --- a/tests/core/txs/test_TransferTokenTransactionStateChanges.py +++ b/tests/core/txs/test_TransferTokenTransactionStateChanges.py @@ -1,24 +1,36 @@ from unittest import TestCase -from mock import patch, Mock +from mock import Mock +from qrl.core import config +from qrl.core.Indexer import Indexer from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.State import State +from qrl.core.StateContainer import StateContainer +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.ChainManager import ChainManager from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction -from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss +from qrl.generated.qrl_pb2 import TokenBalance +from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, set_qrl_dir logger.initialize_default() -@patch('qrl.core.txs.Transaction.Transaction._revert_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.Transaction._apply_state_changes_for_PK') -@patch('qrl.core.txs.Transaction.logger') class TestTransferTokenTransactionStateChanges(TestCase): def setUp(self): + with set_qrl_dir('no_data'): + self.state = State() + self.alice = get_alice_xmss() self.bob = get_bob_xmss() + alice_address_state = OptimizedAddressState.get_default(self.alice.address) + alice_address_state.pbdata.balance = 100 + self.addresses_state = { + self.alice.address: alice_address_state, + self.bob.address: OptimizedAddressState.get_default(self.bob.address) + } + self.params = { "token_txhash": b'I declare the TEST token', "addrs_to": [self.bob.address], @@ -29,37 +41,39 @@ def setUp(self): self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') - def generate_addresses_state(self, tx): - addresses_state = { - self.alice.address: Mock(autospec=AddressState, name='alice AddressState', - tokens={self.params["token_txhash"]: 1000}, transaction_hashes=[], - balance=100), - self.bob.address: Mock(autospec=AddressState, name='bob AddressState', - tokens={self.params["token_txhash"]: 0}, - transaction_hashes=[], - balance=0), - } - return addresses_state - - def test_apply_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_apply_transfer_token_txn(self): """ Alice has 1000 tokens and 100 QRL, Bob has none. Alice sends some tokens to Bob. """ tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=150) + tokens.data[(self.bob.address, tx.token_txhash)] = TokenBalance(balance=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 99) self.assertEqual(addresses_state[self.bob.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(b'I declare the TEST token', -100) - addresses_state[self.bob.address].update_token_balance.assert_called_with(b'I declare the TEST token', 100) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[self.bob.address].transaction_hashes) - m_apply_state_PK.assert_called_once() + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 50) + self.assertEqual(tokens.data[(self.bob.address, tx.token_txhash)].balance, 100) - def test_apply_state_changes_multi_send(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_apply_transfer_token_txn_multi_send(self): """ Alice has 1000 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave. """ @@ -70,84 +84,108 @@ def test_apply_state_changes_multi_send(self, m_logger, m_apply_state_PK, m_reve tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[slave.address] = Mock(autospec=AddressState, name='slave AddressState', - tokens={self.params["token_txhash"]: 0}, - transaction_hashes=[], - balance=0) - - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=200) + tokens.data[(self.bob.address, tx.token_txhash)] = TokenBalance(balance=0) + tokens.data[(slave.address, tx.token_txhash)] = TokenBalance(balance=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 99) self.assertEqual(addresses_state[self.bob.address].balance, 0) self.assertEqual(addresses_state[slave.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(b'I declare the TEST token', -200) - addresses_state[self.bob.address].update_token_balance.assert_called_with(b'I declare the TEST token', 100) - addresses_state[slave.address].update_token_balance.assert_called_with(b'I declare the TEST token', 100) - self.assertEqual([tx.txhash], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[self.bob.address].transaction_hashes) - self.assertEqual([tx.txhash], addresses_state[slave.address].transaction_hashes) - m_apply_state_PK.assert_called_once() + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 0) + self.assertEqual(tokens.data[(self.bob.address, tx.token_txhash)].balance, 100) + self.assertEqual(tokens.data[(slave.address, tx.token_txhash)].balance, 100) - def test_apply_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): - """ - Alice has 1000 tokens and 100 QRL, Bob has none. Alice sends some tokens to Bob. - But this node has no AddressState corresponding to these parties. - """ - tx = TransferTokenTransaction.create(**self.params) - tx.sign(self.alice) - addresses_state = {} - tx.apply_state_changes(addresses_state) - - self.assertEqual({}, addresses_state) - m_apply_state_PK.assert_called_once() - - def test_apply_state_changes_send_tokens_to_self(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_apply_transfer_token_txn_send_tokens_to_self(self): """ Alice has 1000 tokens and 100 QRL. She sends some tokens to herself. What happens next? """ self.params["addrs_to"] = [self.alice.address] tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - tx.apply_state_changes(addresses_state) + addresses_state = dict(self.addresses_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=100) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 99) - # Unfortunately importing mock.call results in some sort of ValueError so I can't check the arguments. - self.assertEqual(addresses_state[self.alice.address].update_token_balance.call_count, 2) + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 100) - m_apply_state_PK.assert_called_once() - - def test_revert_state_changes(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_revert_transfer_token_txn(self): """ Alice has 1000 tokens and 100 QRL, Bob has none. Alice sends some tokens to Bob. Let's undo this. """ tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].tokens[self.params["token_txhash"]] = 900 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - addresses_state[self.bob.address].balance = 0 - addresses_state[self.bob.address].tokens[self.params["token_txhash"]] = 100 - addresses_state[self.bob.address].transaction_hashes = [tx.txhash] - - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + addresses_state[self.bob.address].pbdata.balance = 0 + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=1000) + tokens.data[(self.bob.address, tx.token_txhash)] = TokenBalance(balance=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(b'I declare the TEST token', 100) - addresses_state[self.bob.address].update_token_balance.assert_called_with(b'I declare the TEST token', -100) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - m_revert_state_PK.assert_called_once() + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 1000) + self.assertEqual(tokens.data[(self.bob.address, tx.token_txhash)].balance, 0) - def test_revert_state_changes_multi_send(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_revert_transfer_token_txn_multi_send(self): """ - Alice has 1000 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave. + Alice has 1100 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave. Undo this. """ slave = get_slave_xmss() @@ -156,46 +194,75 @@ def test_revert_state_changes_multi_send(self, m_logger, m_apply_state_PK, m_rev tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].tokens[self.params["token_txhash"]] = 900 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - addresses_state[self.bob.address].balance = 0 - addresses_state[self.bob.address].tokens[self.params["token_txhash"]] = 100 - addresses_state[self.bob.address].transaction_hashes = [tx.txhash] - addresses_state[slave.address] = Mock(autospec=AddressState, name='slave AddressState', - tokens={self.params["token_txhash"]: 100}, - transaction_hashes=[tx.txhash], - balance=0) - - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + addresses_state[self.bob.address].pbdata.balance = 0 + addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=1100) + tokens.data[(self.bob.address, tx.token_txhash)] = TokenBalance(balance=0) + tokens.data[(slave.address, tx.token_txhash)] = TokenBalance(balance=0) + + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) self.assertEqual(addresses_state[slave.address].balance, 0) - addresses_state[self.alice.address].update_token_balance.assert_called_with(b'I declare the TEST token', 200) - addresses_state[self.bob.address].update_token_balance.assert_called_with(b'I declare the TEST token', -100) - addresses_state[slave.address].update_token_balance.assert_called_with(b'I declare the TEST token', -100) - self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) - self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) - self.assertEqual([], addresses_state[slave.address].transaction_hashes) - m_revert_state_PK.assert_called_once() + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 1100) + self.assertEqual(tokens.data[(self.bob.address, tx.token_txhash)].balance, 0) + self.assertEqual(tokens.data[(slave.address, tx.token_txhash)].balance, 0) - def test_revert_state_changes_empty_addresses_state(self, m_logger, m_apply_state_PK, m_revert_state_PK): + def test_revert_transfer_token_txn_empty_addresses_state(self): """ If we didn't have any AddressStates for the addresses involved in this test, do nothing """ tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = {} - - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) - - self.assertEqual(addresses_state, {}) - m_revert_state_PK.assert_called_once() - - def test_revert_state_changes_send_tokens_to_self(self, m_logger, m_apply_state_PK, m_revert_state_PK): + addresses_state = dict(self.addresses_state) + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=100) + tokens.data[(self.bob.address, tx.token_txhash)] = TokenBalance(balance=0) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + + self.assertEqual(100, tokens.data[(self.alice.address, tx.token_txhash)].balance) + self.assertEqual(0, tokens.data[(self.bob.address, tx.token_txhash)].balance) + + def test_revert_transfer_token_txn_send_tokens_to_self(self): """ Alice has 1000 tokens and 100 QRL. She sends some tokens to herself. Can we undo this? @@ -203,13 +270,29 @@ def test_revert_state_changes_send_tokens_to_self(self, m_logger, m_apply_state_ self.params["addrs_to"] = [self.alice.address] tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) - addresses_state = self.generate_addresses_state(tx) - addresses_state[self.alice.address].balance = 99 - addresses_state[self.alice.address].transaction_hashes = [tx.txhash] - tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) + addresses_state = dict(self.addresses_state) + addresses_state[self.alice.address].pbdata.balance = 100 + tokens = Indexer(b'token', None) + tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=100) + state_container = StateContainer(addresses_state=addresses_state, + tokens=tokens, + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=1, + total_coin_supply=1000, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) + + self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) + tx.apply(self.state, state_container) + tx.revert(self.state, state_container) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) # Unfortunately importing mock.call results in some sort of ValueError so I can't check the arguments. - self.assertEqual(addresses_state[self.alice.address].update_token_balance.call_count, 2) - - m_revert_state_PK.assert_called_once() + self.assertEqual(tokens.data[(self.alice.address, tx.token_txhash)].balance, 100) diff --git a/tests/core/txs/testdata.py b/tests/core/txs/testdata.py index c7ef2e657..8e1ada452 100644 --- a/tests/core/txs/testdata.py +++ b/tests/core/txs/testdata.py @@ -59,6 +59,44 @@ "messageHash": "VGVzdCBNZXNzYWdl" } }""" +test_json_MultiSigCreate = """{ + "multiSigCreate": { + "signatories": [ + "AQMAodonTmjIiwzPRI4LGRb6eJsB6y7U6a1WXOJkyTkHgqnGGsAv", + "AQMAHWXX5ZrtXvvq5kJG4PMYTXxCQRQh6zhbow8sHABahevEQZz9", + "AQIAZwJGsAJkNrcX8Znj7FMgumq2HV7d/4EawZmp6bhx0ygBeLND" + ], + "threshold": 30, + "weights": [ + 20, + 30, + 10 + ] + }, + "publicKey": "AQIAsGVJRyiiO8joHbY4VZG1roHa31u5nxY+ITxV1jMdC38Q3DZ80OopZx3kIiEaiH+z0Zmwp/GzwC+qYq3DTTpdqw==" +}""" +test_json_MultiSigSpend = """{ + "multiSigSpend": { + "addrsTo": [ + "AQMAHWXX5ZrtXvvq5kJG4PMYTXxCQRQh6zhbow8sHABahevEQZz9" + ], + "amounts": [ + "100" + ], + "expiryBlockNumber": "15000", + "multiSigAddress": "EQAAOQFwwkX2TVVwVgQi6XffhVe7j7F0BmGgPdcBXaOaTQOGQq0C" + }, + "publicKey": "AQMAOOpjdQafgnLMGmYBs8dsIVGUVWA9NwA2uXx3mto1ZYVOOYO9VkKYxJri5/puKNS5VNjNWTmPEiWwjWFEhUruDg==" +}""" +test_json_MultiSigVote = """{ + "multiSigVote": { + "sharedKey": "+J13jHTkcybczOMHDHqDjo97JhvUYsRx+adev5c/a4E=" + }, + "publicKey": "AQMAOOpjdQafgnLMGmYBs8dsIVGUVWA9NwA2uXx3mto1ZYVOOYO9VkKYxJri5/puKNS5VNjNWTmPEiWwjWFEhUruDg==", + "signature": "AAAAAf74AYshiQcUSML+mEUhVKN1ygsXoCIkHp9B4WTgwHtUHUjy8Gw1YLz3tAGNBEixP+yNIEIQEXp7cuXbRDXaXrNFvdGlxUBQdNCdzSd24gx6/NxQHmVpnTdlhfrWwxV0h0zPkp5Ni5mb+qBH5MuTtQSD294oU9exZmEkpTuuQDND+h/5jVESUGCdf8BQMEAPorbtOrEM7whhLKwHzQ0I7mrGUgV0v4zg3XG6UfYELvLaPV2rB+tD+V0KYNA90hAIlEw7+K3fYmVzrnsvWFqeNCpvkItgwVvm79ld96FIxZxBcqVF3F0BZHpETP4/5kmw+UPbAwpdQW6dncCeTvcfKH567Cs7qZKAPiuyvR7WZhI6cNJcCL1wxJkIVmRCj3RgS65BgjOy4LJQkKniBgXLYh8/GB+Qpf2xGp3JSUQKm/3v1H9KUP8LdcymtxfwwoRsEjzhyza/PWvVMwZ02wMMAT18rfniq5zzc1JgKyAtdDOvYTCxJ96OmES5f4cqpoGrMgwrsDJEPC2NUrKEcGc7Un+rEvsXmBhBWgcbeKZTZRimW3C0OzMHnw3taaMYM6TCZMKpRi+qOj/mr1JSnab0Ju6Xez/Aq98x4kuL5WaXZ26Qpc9qI0uct5bOZk9I2tg8CJkn6BlyDGnVmPukyVZcCm1YbkaUlv2SNnS81Cx7fiwE4wbPP+CVBiKozma+dAOTyNasDBU5ABc1A8aO/WTN+OmjOiyeKSSjtrtex9INqnPcDulKQbh+QVNYGahvFMLQPrEMsn9TdyhvvV6g1sAqsq9h09ubyOYPItfWQCS0gpgXoLcv9LRFg4m5GA0xOjPmLTlc90or4EaGecoarIfsltY1DEoeUsYyssVDzME6B6N5ilF/7+ccNjVvw4Mzqg3+ZGCH3+EpxZdOhuYXXfiRzHa1Pb6/dhH0pMlbpxqNKku4/RXdqBeI0xckzmyWICbQtDa0Uo7V+W6BfcWvtaOifhzsnmDjd5sfQ7keZSPn4HYsyeSkyG+lpOJLgipajGrmE1Zzh51hftqYNQCre142+Onj7tEEwQeDqQs1eJQosgt1CIJ/yY5RQHTQeVXf9kj2j7r6LU1VpG1gkeaCfEKb+okWOFL4Dg4NEgKkC3wCaCGiPzfYUqtNcmMdbkXU3IlEyCZC3GVTcJRhBn2dG+WDSFDzha6oFxUSP/4rsUPd+SuSvVbxI/ofZLNmRg+jtF5UdO8UH0C4rAeXF7XNAWRqbQbbw3vge2rwLbJ6UGpisxcU2jkcZe3ZMTUCoiyEmwXJHwipQpKyNwD3DsJozK8uUoLYdnK6oj/pZ7J59Jj+O34o+LvEe8biYXN5wRtOjktaM9VPQB79dZOY6NI3EUxTibPVEQDpSpBb3U67UKJ6FUBEeVYnFAN2LY5hBae5BqIcZk6LgM3c9nujrTpxW6GRLJF9omFiQosHVbUojDePQ73LyVO+0I01IQBJ/TAsmO2PmR9ldGY3IDunoqyWki05zBaARB+xsfXQCP7JExNfjfNHhqO2EUNVLr+2VDPEVZ9ME9QMMFvy8n+6lpxKMx5Tu8otxsxqhDCASJbSsHwXLIPnmZe4/QJNCEWh4OE5jkRSjauQud0kP1kRDvOSLAl/GZxmUJDDFMz+wsyCcTCvN7RyXPDLsTw+MJcOgK3tP2kFjR1HRvx0gceoyOCdcNfRdA34aYkgVQF6zjd5Cup0UZgYXu/bs3zyu9enCcM5CQdRG9wIEzJjNAjg3vctrKHMHbfxRuofNK0Imto3Hb4EW67X78SKPJdil81Hu6VmTQVRi+bqWbO0q1k7JJYidNIdNVYz64hvR1izjPNTpPXGTe5F01HPYbJh/pmGMJCrXAUItl2BY7ofmuVVAPwy544hoaYS+i3+SZpXsb6eVt+FWwaKOBYcgGwElX5aMtTwxs+TOhW5MiY91rGLir+iVyJIyY7OdGX331jjaxKEJERWqFsMV40jLP6cIPjO3qQiy62VFTQ74C1vtxdaaS/4YL1E85qmC9C/8O58dxW8q2nNtpd/OL68hetNoTufWoJ/0+zwsuQow4E1nVLEWbZ05hnahUNdwtXsen/9h/+8UB6ObB70MbRKu5jP1CuVT2DtPFMfSCk2t5SjbVQ8W7ZgkSKqxAqk/gxT9OnMDi/j+jD06itIo+NR9QmLu0EGKA5o93reLHEVjrRb6jVL4cIZ5RKoJFRSVUUxsr2QOX46CjmZBLNaXszzKU6C7QPdS/iRXNn6C5XCZ3ABnYNPBD9cKjzqwn+eUSeOrLTeLJJdRcpf9GIClF0eeAzfeA+YJik4cvnShq7sNzCBeYsgEFu+WfdmJ52azT5BcB5qN42l8kGT7ZIG45XRXpJ80ksTRqyzYk2x5G8bpyh37zftJV4t4GA+3fFvGAJpkWyTUqqZajGOwZxNkenBmHjcYbGhljgecz0xAMDG6rxlqF6/2uZjgbnfNgJxf7ER0fotRNZEblth2LF7gga2sVdf2lP6oH17maL8V61MhBiQJGJLiZzE6JhKQaXmR/r9PNou1p6zvt2uJr1xqosvbH2ADd2ScpnSc4Y53wHJRZPMbIi4OA8r3dImNMmSGnp3OWG8l4n+1+7FaCpVvYf1rWewQ7qB4TH2ZfjB0gkkPSHbB1xVIRl116tC4iGC3w1clR/g24gDJCa4PzOJ48rgoXBdQfZ+ACbCMhx0VER7mo2lVzcSYljgbYnJa3ZgzSBoa8/xWY3RzsDlodzKU+hfhGLrUa0hMKuKtU5uRtuGt9ujBsZbT9LYPk5+s8uFqkoPMWVE9tuONnVuieay+SyWv/v2kKsQxea0hHJvK5ITECSTgaV3Fi6HToua6pPm9J3MlJa7nNnofYMpF55BmrxDEaK8qCkt9/5Rmr/VZ47bd2pvaKPLezTL/yFC3IRrqrFyp4NbIdSbqtpz028Gdti52myxLUgWMdMITiFw6v46402sZIbgO44rqhYWtY5yzjimUnTbSIJG7WinCylJKNon75sk7lkscj2RoC0j7pYAcsxfwSILx494Z+MoZyL+9u3vPwzgkEUAQds8ratzbyVLaL961jxwhXicK2UalH8Jhw404VXvPCxUK//0EsfWtvb8kLCpWmNe7Q+lChJqXSS3jJFcIQ2/XpJjP4PygtC55OCkf0nz0ySYKJhnXu0=", + "transactionHash": "6BCuJYD5HpCZBY9JeUo1LNJlb7IzLZEDRNwD6KDd3D4=" +}""" + test_signature_Simple = "0000000a899e73cfbf8c57027f5a0f853b9906701ee378ad169d34ce45153f13" \ "3c3f3f6cd87250b2ad225ced6b8c902a5fa1ecfacaa6744f6f42323ee586d873" \ "f066388ab9f17ad396aed963678edeab3e6e35c082ecd7bb8ef568f2da92fb2a" \ diff --git a/tests/daemon/test_walletd.py b/tests/daemon/test_walletd.py index 171036f2a..01aee68fe 100644 --- a/tests/daemon/test_walletd.py +++ b/tests/daemon/test_walletd.py @@ -1,6 +1,8 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import grpc +from concurrent.futures import ThreadPoolExecutor from unittest import TestCase from mock import Mock @@ -8,7 +10,13 @@ from qrl.daemon.walletd import WalletD from qrl.generated import qrl_pb2 -from qrl.core.AddressState import AddressState +from qrl.core import config +from qrl.core.State import State +from qrl.core.qrlnode import QRLNode +from qrl.generated.qrl_pb2_grpc import add_PublicAPIServicer_to_server +from qrl.services.PublicAPIService import PublicAPIService +from qrl.core.ChainManager import ChainManager +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.daemon.helper.DaemonHelper import WalletDecryptionError @@ -54,10 +62,62 @@ def test_authenticate(self): with self.assertRaises(ValueError): walletd.authenticate() - def test_get_slave(self): + def test_get_unused_ots_index(self): + with set_qrl_dir("wallet_ver1"): + walletd = WalletD() + + walletd._public_stub.PushTransaction = Mock( + return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=10, unused_ots_index_found=True)) + + qaddress = walletd.add_new_address_with_slaves(height=10) + walletd.encrypt_wallet(self.passphrase) + walletd.unlock_wallet(self.passphrase) + + ots_index = walletd.get_unused_ots_index(walletd.qaddress_to_address(qaddress), 0) + self.assertEqual(10, ots_index) + + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=10, unused_ots_index_found=False)) + + ots_index = walletd.get_unused_ots_index(walletd.qaddress_to_address(qaddress), 0) + self.assertIsNone(ots_index) + + def test_is_slave(self): with set_qrl_dir("wallet_ver1"): + walletd = WalletD() + + walletd._public_stub.PushTransaction = Mock( + return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + + qaddress = walletd.add_new_address_with_slaves(height=10) + walletd.encrypt_wallet(self.passphrase) + walletd.unlock_wallet(self.passphrase) + + self.assertTrue(walletd.is_slave(walletd.qaddress_to_address(qaddress), walletd.qaddress_to_address(qaddress))) + + def test_get_slave(self): + with set_qrl_dir("wallet_ver1") and set_qrl_dir('no_data'): + state = State() + chain_manager = ChainManager(state) + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + + public_api_server = grpc.server(ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=1) + + add_PublicAPIServicer_to_server(PublicAPIService(qrlnode), public_api_server) + public_api_server.add_insecure_port("{0}:{1}".format(config.user.public_api_host, + config.user.public_api_port)) + public_api_server.start() + walletd = WalletD() m = MockFunction() + walletd.get_address_state = m.get walletd._public_stub.PushTransaction = Mock( @@ -67,37 +127,46 @@ def test_get_slave(self): walletd.encrypt_wallet(self.passphrase) walletd.unlock_wallet(self.passphrase) - master_addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + master_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) m.put(qaddress, master_addr_state) slaves = walletd.get_slave_list(qaddress) + slaves_state = { + (master_addr_state.address, bytes(hstr2bin(slaves[0][0].pk))): (0, b'txhash0'), + (master_addr_state.address, bytes(hstr2bin(slaves[0][1].pk))): (0, b'txhash0'), + (master_addr_state.address, bytes(hstr2bin(slaves[0][2].pk))): (0, b'txhash0'), + } + state.put_slaves(slaves_state) + self.assertEqual(len(slaves), 1) self.assertEqual(len(slaves[0]), 3) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][1].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][2].pk)), 0) - slave00_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[0][0].qaddress)) - slave01_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[0][1].qaddress)) - slave02_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[0][2].qaddress)) + slave00_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][0].qaddress)) + slave01_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][1].qaddress)) + slave02_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][2].qaddress)) + addresses_bitfield = dict() + addresses_state = { + slave00_addr_state.address: slave00_addr_state, + slave01_addr_state.address: slave01_addr_state, + slave02_addr_state.address: slave02_addr_state, + } self.assertEqual(slaves[0][0].index, 0) for i in range(0, 1024): - slave00_addr_state.set_ots_key(i) + state.set_ots_key(addresses_bitfield, addresses_state, slave00_addr_state.address, i) walletd._wallet.set_slave_ots_index(0, 0, 0, 1020) m.put(slaves[0][0].qaddress, slave00_addr_state) self.assertEqual(slaves[0][1].index, 0) for i in range(0, 1024): - slave01_addr_state.set_ots_key(i) - walletd._wallet.set_slave_ots_index(0, 0, 1, 1020) + state.set_ots_key(addresses_bitfield, addresses_state, slave01_addr_state.address, i) m.put(slaves[0][1].qaddress, slave01_addr_state) self.assertEqual(slaves[0][2].index, 5) for i in range(5, 1000): - slave02_addr_state.set_ots_key(i) - walletd._wallet.set_slave_ots_index(0, 0, 2, 1018) + state.set_ots_key(addresses_bitfield, addresses_state, slave02_addr_state.address, i) + state.put_addresses_bitfield(addresses_bitfield) m.put(slaves[0][2].qaddress, slave02_addr_state) walletd.get_slave(qaddress) @@ -105,29 +174,38 @@ def test_get_slave(self): self.assertEqual(len(slaves), 2) walletd._wallet.set_slave_ots_index(0, 0, 2, 1019) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[1][0].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[1][1].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[1][2].pk)), 0) - slave10_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[1][0].qaddress)) - slave11_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[1][1].qaddress)) - slave12_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[1][2].qaddress)) + slave10_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][0].qaddress)) + slave11_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][1].qaddress)) + slave12_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][2].qaddress)) + slaves_state = { + (master_addr_state.address, bytes(hstr2bin(slaves[1][0].pk))): (0, b'txhash1'), + (master_addr_state.address, bytes(hstr2bin(slaves[1][1].pk))): (0, b'txhash1'), + (master_addr_state.address, bytes(hstr2bin(slaves[1][2].pk))): (0, b'txhash1'), + } + state.put_slaves(slaves_state) + addresses_bitfield = dict() + addresses_state = { + slave10_addr_state.address: slave10_addr_state, + slave11_addr_state.address: slave11_addr_state, + slave12_addr_state.address: slave12_addr_state, + } self.assertEqual(slaves[1][0].index, 0) for i in range(0, 1024): - slave10_addr_state.set_ots_key(i) + state.set_ots_key(addresses_bitfield, addresses_state, slave10_addr_state.address, i) walletd._wallet.set_slave_ots_index(0, 1, 0, 1020) m.put(slaves[1][0].qaddress, slave10_addr_state) self.assertEqual(slaves[1][1].index, 0) for i in range(0, 1024): - slave11_addr_state.set_ots_key(i) + state.set_ots_key(addresses_bitfield, addresses_state, slave11_addr_state.address, i) walletd._wallet.set_slave_ots_index(0, 1, 1, 1020) m.put(slaves[1][1].qaddress, slave11_addr_state) self.assertEqual(slaves[1][2].index, 5) for i in range(5, 1000): - slave12_addr_state.set_ots_key(i) - walletd._wallet.set_slave_ots_index(0, 1, 2, 1018) + state.set_ots_key(addresses_bitfield, addresses_state, slave12_addr_state.address, i) + state.put_addresses_bitfield(addresses_bitfield) m.put(slaves[1][2].qaddress, slave12_addr_state) walletd.get_slave(qaddress) @@ -135,29 +213,38 @@ def test_get_slave(self): self.assertEqual(len(slaves), 3) walletd._wallet.set_slave_ots_index(0, 1, 2, 1019) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[2][0].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[2][1].pk)), 0) - master_addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[2][2].pk)), 0) - slave20_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[2][0].qaddress)) - slave21_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[2][1].qaddress)) - slave22_addr_state = AddressState.get_default(walletd.qaddress_to_address(slaves[2][2].qaddress)) + slave20_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][0].qaddress)) + slave21_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][1].qaddress)) + slave22_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][2].qaddress)) + slaves_state = { + (master_addr_state.address, bytes(hstr2bin(slaves[2][0].pk))): (0, b'txhash2'), + (master_addr_state.address, bytes(hstr2bin(slaves[2][1].pk))): (0, b'txhash2'), + (master_addr_state.address, bytes(hstr2bin(slaves[2][2].pk))): (0, b'txhash2'), + } + state.put_slaves(slaves_state) + addresses_bitfield = dict() + addresses_state = { + slave20_addr_state.address: slave20_addr_state, + slave21_addr_state.address: slave21_addr_state, + slave22_addr_state.address: slave22_addr_state, + } self.assertEqual(slaves[2][0].index, 0) for i in range(0, 1024): - slave20_addr_state.set_ots_key(i) + state.set_ots_key(addresses_bitfield, addresses_state, slave20_addr_state.address, i) walletd._wallet.set_slave_ots_index(0, 2, 0, 1020) m.put(slaves[2][0].qaddress, slave20_addr_state) self.assertEqual(slaves[2][1].index, 0) for i in range(0, 1024): - slave21_addr_state.set_ots_key(i) + state.set_ots_key(addresses_bitfield, addresses_state, slave21_addr_state.address, i) walletd._wallet.set_slave_ots_index(0, 2, 1, 1020) - m.put(slaves[2][1].qaddress, slave21_addr_state) + m.put(slaves[2][1].qaddress, slave20_addr_state) self.assertEqual(slaves[2][2].index, 5) for i in range(5, 1000): - slave22_addr_state.set_ots_key(i) - walletd._wallet.set_slave_ots_index(0, 2, 2, 1018) + state.set_ots_key(addresses_bitfield, addresses_state, slave22_addr_state.address, i) + state.put_addresses_bitfield(addresses_bitfield) m.put(slaves[2][2].qaddress, slave22_addr_state) walletd.get_slave(qaddress) @@ -344,6 +431,7 @@ def test_sign_and_push_transaction(self): bob_xmss = get_bob_xmss() tx = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[1], + message_data=None, fee=1, xmss_pk=alice_xmss.pk) @@ -360,9 +448,13 @@ def test_relay_transfer_txn(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) - + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -384,9 +476,14 @@ def test_relay_transfer_txn2(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -421,7 +518,7 @@ def test_relay_transfer_txn3(self): return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -444,12 +541,15 @@ def test_relay_transfer_txn_by_slave(self): walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -469,12 +569,15 @@ def test_relay_transfer_txn2_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -503,12 +606,15 @@ def test_relay_transfer_txn3_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -539,9 +645,12 @@ def test_relay_message_txn(self): return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) tx = walletd.relay_message_txn(message='Hello QRL!', fee=100000000, @@ -555,12 +664,16 @@ def test_relay_message_txn_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + # addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -574,9 +687,13 @@ def test_relay_message_txn2(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) - + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -603,12 +720,15 @@ def test_relay_message_txn2_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -631,8 +751,13 @@ def test_relay_token_txn(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -659,10 +784,13 @@ def test_relay_token_txn_by_slave(self): walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -686,9 +814,13 @@ def test_relay_token_txn2(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) - + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -730,12 +862,15 @@ def test_relay_token_txn2_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -773,9 +908,14 @@ def test_relay_transfer_token_txn(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -816,10 +956,15 @@ def test_relay_transfer_token_txn2(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) walletd.add_new_address(height=8) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -856,12 +1001,15 @@ def test_relay_transfer_token_txn_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -894,9 +1042,14 @@ def test_relay_slave_txn(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -929,12 +1082,15 @@ def test_relay_slave_txn_by_slave(self): walletd = WalletD() walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -1025,14 +1181,18 @@ def test_change_passphrase(self): self.assertEqual(len(qaddresses), 1) self.assertEqual(qaddresses[0], qaddress) - def test_get_transactions_by_address(self): + def test_get_mini_transactions_by_address(self): with set_qrl_dir("wallet_ver1"): walletd = WalletD() - walletd._public_stub.GetTransactionsByAddress = Mock( - return_value=qrl_pb2.GetTransactionsByAddressResp(mini_transactions=[], - balance=0)) - mini_transactions, balance = walletd.get_transactions_by_address(qaddress=get_alice_xmss(4).qaddress) + walletd._public_stub.GetMiniTransactionsByAddress = Mock( + return_value=qrl_pb2.GetMiniTransactionsByAddressResp(mini_transactions=[], + balance=0)) + mini_transactions, balance = walletd.get_mini_transactions_by_address( + qaddress=get_alice_xmss(4).qaddress, + item_per_page=10, + page_number=1 + ) self.assertEqual(len(mini_transactions), 0) self.assertEqual(balance, 0) @@ -1081,12 +1241,17 @@ def test_get_total_balance(self): def test_get_ots(self): with set_qrl_dir("wallet_ver1"): walletd = WalletD() + ots_bitfield_by_page = qrl_pb2.OTSBitfieldByPage(ots_bitfield=[b'\x00'] * 10, + page_number=1) walletd._public_stub.GetOTS = Mock( - return_value=qrl_pb2.GetOTSResp(ots_bitfield=[b'\x00'] * 10, next_unused_ots_index=1)) + return_value=qrl_pb2.GetOTSResp(ots_bitfield_by_page=[ots_bitfield_by_page], + next_unused_ots_index=1, + unused_ots_index_found=True)) - ots_bitfield, next_unused_ots_index = walletd.get_ots(self.qaddress) - self.assertEqual(ots_bitfield, [b'\x00'] * 10) + ots_bitfield_by_page, next_unused_ots_index, unused_ots_index_found = walletd.get_ots(self.qaddress) + self.assertEqual(ots_bitfield_by_page, ots_bitfield_by_page) self.assertEqual(next_unused_ots_index, 1) + self.assertEqual(unused_ots_index_found, True) def test_get_height(self): with set_qrl_dir("wallet_ver1"): @@ -1135,6 +1300,7 @@ def test_get_block_by_number2(self): b'\xe5\x9a\x13\xde+\xe5{D_\x05m\x06\x1c\x8f\nG?\xed\xd6qip3' tx = MessageTransaction.create(message_hash=message, + addr_to=None, fee=1, xmss_pk=alice.pk) tx.sign(alice) @@ -1161,6 +1327,7 @@ def test_get_block_by_number3(self): b'\x1c \x9c\x861\x81\xa5\xdd\xe3\x81\x90\x89\xd6\xd4' tx = MessageTransaction.create(message_hash=message, + addr_to=None, fee=1, xmss_pk=alice.pk) tx.sign(alice) diff --git a/tests/misc/MockHelper/mock_get_tx_metadata.py b/tests/misc/MockHelper/mock_get_tx_metadata.py index 490dcb608..9a815176d 100644 --- a/tests/misc/MockHelper/mock_get_tx_metadata.py +++ b/tests/misc/MockHelper/mock_get_tx_metadata.py @@ -11,7 +11,7 @@ def __init__(self): def register_tx_metadata(self, tx: Transaction, block_number: int): self.data[tx.txhash] = [tx, block_number] - def get_tx_metadata(self, txhash): + def get_tx_metadata(self, _, txhash): if txhash in self.data: return self.data[txhash] diff --git a/tests/misc/helper.py b/tests/misc/helper.py index 892fed0c8..ac8b00b70 100644 --- a/tests/misc/helper.py +++ b/tests/misc/helper.py @@ -12,17 +12,20 @@ from mock import mock from pyqrllib.pyqrllib import XmssFast from pyqrllib.pyqrllib import bin2hstr, hstr2bin +from pyqryptonight.pyqryptonight import StringToUInt256 from qrl.core import config -from qrl.core.misc import logger +from qrl.core.Block import Block +from qrl.core.BlockMetadata import BlockMetadata +from qrl.core.ChainManager import ChainManager +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.GenesisBlock import GenesisBlock +from qrl.core.txs.Transaction import Transaction from qrl.core.txs.SlaveTransaction import SlaveTransaction from qrl.core.txs.TokenTransaction import TokenTransaction from qrl.crypto.xmss import XMSS from qrl.generated import qrl_pb2 -logger.initialize_default() - def replacement_getTime(): return int(time.time()) @@ -38,6 +41,16 @@ def set_default_balance_size(new_value=100 * int(config.dev.shor_per_quanta)): config.dev.default_account_balance = old_value +@contextlib.contextmanager +def set_hard_fork_block_number(hard_fork_index=0, new_value=1): + old_value = config.dev.hard_fork_heights[hard_fork_index] + try: + config.dev.hard_fork_heights[hard_fork_index] = new_value + yield + finally: + config.dev.hard_fork_heights[hard_fork_index] = old_value + + @contextlib.contextmanager def set_wallet_dir(wallet_name): dst_dir = tempfile.mkdtemp() @@ -73,6 +86,21 @@ def set_qrl_dir(data_name): config.user.qrl_dir = prev_val +def get_genesis_with_only_coin_base_txn(coin_base_reward_addr, dev_config): + g = GenesisBlock() + + coin_base_tx = Transaction.from_pbdata(g.transactions[0]) + coin_base_tx.update_mining_address(coin_base_reward_addr) + + # Remove all other transaction except CoinBase txn + del g.transactions[:] + + g.pbdata.transactions.extend([coin_base_tx.pbdata]) + g.blockheader.generate_headerhash(dev_config) + + return g + + def read_data_file(filename): test_path = os.path.dirname(os.path.abspath(__file__)) src_file = os.path.join(test_path, "..", "data", filename) @@ -185,3 +213,60 @@ def get_random_master(): slave_data = json.loads(json.dumps([bin2hstr(random_master.address), [random_master.extended_seed], None])) slave_data[0] = bytes(hstr2bin(slave_data[0])) return slave_data + + +def gen_blocks(block_count, state, miner_address): + blocks = [] + block = None + with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: + time_mock.return_value = 1615270948 + addresses_state = dict() + for i in range(0, block_count): + if i == 0: + block = GenesisBlock() + for genesis_balance in GenesisBlock().genesis_balance: + bytes_addr = genesis_balance.address + addresses_state[bytes_addr] = OptimizedAddressState.get_default(bytes_addr) + addresses_state[bytes_addr]._data.balance = genesis_balance.balance + else: + block = Block.create(dev_config=config.dev, + block_number=i, + prev_headerhash=block.headerhash, + prev_timestamp=block.timestamp, + transactions=[], + miner_address=miner_address, + seed_height=None, + seed_hash=None) + addresses_set = ChainManager.set_affected_address(block) + coin_base_tx = Transaction.from_pbdata(block.transactions[0]) + coin_base_tx.set_affected_address(addresses_set) + + chain_manager = ChainManager(state) + state_container = chain_manager.new_state_container(addresses_set, + block.block_number, + False, + None) + coin_base_tx.apply(state, state_container) + + for tx_idx in range(1, len(block.transactions)): + if not chain_manager.update_state_container(tx, state_container): + return False + tx = Transaction.from_pbdata(block.transactions[tx_idx]) + tx.apply(state, state_container) + + block.set_nonces(dev_config=config.dev, mining_nonce=10, extra_nonce=0) + blocks.append(block) + + metadata = BlockMetadata() + metadata.set_block_difficulty(StringToUInt256('256')) + BlockMetadata.put_block_metadata(state, block.headerhash, metadata, None) + + Block.put_block(state, block, None) + bm = qrl_pb2.BlockNumberMapping(headerhash=block.headerhash, + prev_headerhash=block.prev_headerhash) + + Block.put_block_number_mapping(state, block.block_number, bm, None) + state.update_mainchain_height(block.block_number, None) + OptimizedAddressState.put_optimized_addresses_state(state, addresses_state) + + return blocks \ No newline at end of file diff --git a/tests/services/test_MiningAPIService.py b/tests/services/test_MiningAPIService.py index d2dec96b6..7399daceb 100644 --- a/tests/services/test_MiningAPIService.py +++ b/tests/services/test_MiningAPIService.py @@ -29,10 +29,11 @@ def setUp(self): p2p_factory.sync_state = SyncState() p2p_factory.num_connections = 23 p2p_factory.pow = Mock() - + b = Block() self.chain_manager = Mock(spec=ChainManager) self.chain_manager.height = 0 - self.chain_manager.get_last_block = MagicMock(return_value=Block()) + self.chain_manager.get_last_block = MagicMock(return_value=b) + self.chain_manager.get_block_header_hash_by_number = MagicMock(return_value=b.headerhash) self.qrlnode = QRLNode(mining_address=b'') self.qrlnode.set_chain_manager(self.chain_manager) @@ -40,11 +41,14 @@ def setUp(self): self.qrlnode._pow = p2p_factory.pow self.block_header_params = { + "dev_config": config.dev, "blocknumber": 10, "prev_headerhash": sha256(b'prevblock'), "prev_timestamp": 1234567890, "hashedtransactions": sha256(b'tx1'), - "fee_reward": 1 + "fee_reward": 1, + "seed_height": 0, + "seed_hash": None, } self.service = MiningAPIService(self.qrlnode) diff --git a/tests/services/test_PublicAPIService.py b/tests/services/test_PublicAPIService.py index f9226c3bb..94aacc68d 100644 --- a/tests/services/test_PublicAPIService.py +++ b/tests/services/test_PublicAPIService.py @@ -5,12 +5,15 @@ from unittest import TestCase from grpc import ServicerContext, StatusCode -from mock import Mock, MagicMock, patch +from mock import Mock, MagicMock, patch, PropertyMock from pyqrllib.pyqrllib import str2bin, hstr2bin, bin2hstr from qrl.core import config from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.PaginatedBitfield import PaginatedBitfield from qrl.core.Block import Block +from qrl.core.TransactionMetadata import TransactionMetadata from qrl.core.ChainManager import ChainManager from qrl.core.GenesisBlock import GenesisBlock from qrl.core.State import State @@ -23,11 +26,8 @@ from qrl.crypto.misc import sha256 from qrl.generated import qrl_pb2 from qrl.services.PublicAPIService import PublicAPIService -from tests.misc.helper import get_alice_xmss, get_bob_xmss, replacement_getTime from tests.blockchain.MockedBlockchain import MockedBlockchain -from tests.misc.MockHelper.mock_function import MockFunction - -logger.initialize_default() +from tests.misc.helper import get_alice_xmss, get_bob_xmss, replacement_getTime, set_qrl_dir @patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) @@ -138,240 +138,259 @@ def test_getStats_timeseries(self): self.assertEqual(1, stats.block_time_sd) def test_getAddressState(self): - db_state = Mock(spec=State) - alice_xmss = get_alice_xmss() - address_state = AddressState.create(address=alice_xmss.address, - nonce=25, - balance=10, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - db_state.get_address_state = MagicMock(return_value=address_state) - - p2p_factory = Mock(spec=P2PFactory) - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetAddressStateReq() - service.GetAddressState(request=request, context=context) - context.set_code.assert_called() - context.set_details.assert_called() - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetAddressStateReq() - request.address = get_alice_xmss().address - response = service.GetAddressState(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(alice_xmss.address, response.state.address) - self.assertEqual(25, response.state.nonce) - self.assertEqual(10, response.state.balance) - self.assertEqual([b'\x00'] * config.dev.ots_bitfield_size, response.state.ots_bitfield) - self.assertEqual([], response.state.transaction_hashes) + with set_qrl_dir('no_data'): + db_state = State() + alice_xmss = get_alice_xmss() + optimized_address_state = OptimizedAddressState.create(address=alice_xmss.address, + nonce=25, + balance=10, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + AddressState.put_address_state(db_state, optimized_address_state) + + p2p_factory = Mock(spec=P2PFactory) + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetAddressStateReq() + service.GetAddressState(request=request, context=context) + context.set_code.assert_called() + context.set_details.assert_called() + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetAddressStateReq() + request.address = get_alice_xmss().address + response = service.GetAddressState(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(alice_xmss.address, response.state.address) + self.assertEqual(25, response.state.nonce) + self.assertEqual(10, response.state.balance) + self.assertEqual(0, response.state.ots_bitfield_used_page) + self.assertEqual(0, response.state.transaction_hash_count) def test_getObject(self): SOME_ODD_HASH = sha256(b'this should not be found') - db_state = Mock(spec=State) - db_state.get_tx_metadata = MagicMock(return_value=None) - db_state.get_block = MagicMock(return_value=None) - - p2p_factory = Mock(spec=P2PFactory) - p2p_factory.pow = Mock(spec=POW) - - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._pow = p2p_factory.pow - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - # First try an empty request - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetObjectReq() - response = service.GetObject(request=request, context=context) - context.set_code.assert_not_called() - context.set_details.assert_not_called() - self.assertFalse(response.found) - - # Some odd address - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetObjectReq() - request.query = SOME_ODD_HASH - response = service.GetObject(request=request, context=context) - context.set_code.assert_not_called() - self.assertFalse(response.found) - - # Find an address - bob_xmss = get_bob_xmss() - addr1_state = AddressState.create(address=bob_xmss.address, - nonce=25, - balance=10, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - addr1_state.transaction_hashes.append(sha256(b'0')) - addr1_state.transaction_hashes.append(sha256(b'1')) - - db_state.get_address_state = MagicMock(return_value=addr1_state) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetObjectReq() - request.query = bob_xmss.address - response = service.GetObject(request=request, context=context) - context.set_code.assert_not_called() - self.assertTrue(response.found) - self.assertIsNotNone(response.address_state) - - self.assertEqual(bob_xmss.address, response.address_state.address) - self.assertEqual(25, response.address_state.nonce) - self.assertEqual(10, response.address_state.balance) - self.assertEqual([sha256(b'0'), sha256(b'1')], response.address_state.transaction_hashes) - - # Find a transaction - alice_xmss = get_alice_xmss() - db_state.address_used = MagicMock(return_value=False) - tx1 = TransferTransaction.create( - addrs_to=[bob_xmss.address], - amounts=[125], - fee=19, - xmss_pk=bob_xmss.pk, - master_addr=alice_xmss.address) - - chain_manager.tx_pool.transaction_pool = [(0, TransactionInfo(tx1, 0))] - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetObjectReq() - request.query = tx1.txhash - response = service.GetObject(request=request, context=context) - context.set_code.assert_not_called() - self.assertTrue(response.found) - self.assertIsNotNone(response.transaction) - self.assertEqual('transfer', response.transaction.tx.WhichOneof('transactionType')) - self.assertEqual(alice_xmss.address, response.transaction.tx.master_addr) - self.assertEqual(bob_xmss.pk, response.transaction.tx.public_key) - self.assertEqual(tx1.txhash, response.transaction.tx.transaction_hash) - self.assertEqual(b'', response.transaction.tx.signature) - - self.assertEqual(bob_xmss.address, response.transaction.tx.transfer.addrs_to[0]) - self.assertEqual(125, response.transaction.tx.transfer.amounts[0]) - self.assertEqual(19, response.transaction.tx.fee) - - alice_xmss = get_alice_xmss() - # Find a block - db_state.get_block_by_number = MagicMock( - return_value=Block.create(block_number=1, - prev_headerhash=sha256(b'reveal'), - prev_timestamp=10, - transactions=[], - miner_address=alice_xmss.address)) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetObjectReq() - request.query = bytes(str2bin('1')) - response = service.GetObject(request=request, context=context) - context.set_code.assert_not_called() - self.assertTrue(response.found) - self.assertIsNotNone(response.block_extended) - self.assertEqual(1, response.block_extended.header.block_number) + with set_qrl_dir('no_data'): + db_state = State() + + p2p_factory = Mock(spec=P2PFactory) + p2p_factory.pow = Mock(spec=POW) + + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._pow = p2p_factory.pow + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + # First try an empty request + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetObjectReq() + response = service.GetObject(request=request, context=context) + context.set_code.assert_not_called() + context.set_details.assert_not_called() + self.assertFalse(response.found) + + # Some odd address + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetObjectReq() + request.query = SOME_ODD_HASH + response = service.GetObject(request=request, context=context) + context.set_code.assert_not_called() + self.assertFalse(response.found) + + # Find an address + bob_xmss = get_bob_xmss() + addr1_state = OptimizedAddressState.create(address=bob_xmss.address, + nonce=25, + balance=10, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + + AddressState.put_address_state(db_state, addr1_state, None) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetObjectReq() + request.query = bob_xmss.address + response = service.GetObject(request=request, context=context) + context.set_code.assert_not_called() + self.assertTrue(response.found) + self.assertIsNotNone(response.address_state) + + self.assertEqual(bob_xmss.address, response.address_state.address) + self.assertEqual(25, response.address_state.nonce) + self.assertEqual(10, response.address_state.balance) + + # Find a transaction + alice_xmss = get_alice_xmss() + db_state.address_used = MagicMock(return_value=False) + tx1 = TransferTransaction.create( + addrs_to=[bob_xmss.address], + amounts=[125], + message_data=None, + fee=19, + xmss_pk=bob_xmss.pk, + master_addr=alice_xmss.address) + + chain_manager.tx_pool.transaction_pool = [(0, TransactionInfo(tx1, 0))] + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetObjectReq() + request.query = tx1.txhash + response = service.GetObject(request=request, context=context) + context.set_code.assert_not_called() + self.assertTrue(response.found) + self.assertIsNotNone(response.transaction) + self.assertEqual('transfer', response.transaction.tx.WhichOneof('transactionType')) + self.assertEqual(alice_xmss.address, response.transaction.tx.master_addr) + self.assertEqual(bob_xmss.pk, response.transaction.tx.public_key) + self.assertEqual(tx1.txhash, response.transaction.tx.transaction_hash) + self.assertEqual(b'', response.transaction.tx.signature) + + self.assertEqual(bob_xmss.address, response.transaction.tx.transfer.addrs_to[0]) + self.assertEqual(125, response.transaction.tx.transfer.amounts[0]) + self.assertEqual(19, response.transaction.tx.fee) + + alice_xmss = get_alice_xmss() + # Find a block + block = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=sha256(b'reveal'), + prev_timestamp=10, + transactions=[], + miner_address=alice_xmss.address, + seed_height=0, + seed_hash=None) + + Block.put_block(db_state, block, None) + Block.put_block_number_mapping(db_state, + block.block_number, + qrl_pb2.BlockNumberMapping(headerhash=block.headerhash), + None) + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetObjectReq() + request.query = bytes(str2bin('1')) + response = service.GetObject(request=request, context=context) + context.set_code.assert_not_called() + self.assertTrue(response.found) + self.assertIsNotNone(response.block_extended) + self.assertEqual(1, response.block_extended.header.block_number) def test_getLatestData(self): - blocks = [] - txs = [] - alice_xmss = get_alice_xmss() - bob_xmss = get_bob_xmss() - for i in range(1, 4): - for j in range(1, 3): - txs.append(TransferTransaction.create(addrs_to=[bob_xmss.address], - amounts=[i * 100 + j], - fee=j, - xmss_pk=alice_xmss.pk)) - - blocks.append(Block.create(block_number=i, - prev_headerhash=sha256(b'reveal'), - prev_timestamp=10, - transactions=txs, - miner_address=alice_xmss.address)) - - txpool = [] - for j in range(10, 15): - tx = TransferTransaction.create(addrs_to=[bob_xmss.address], - amounts=[1000 + j], - fee=j, - xmss_pk=get_alice_xmss().pk) - txpool.append((tx.fee, TransactionInfo(tx, 0))) - - db_state = Mock(spec=State) - db_state.get_tx_metadata = MagicMock(return_value=None) - db_state.get_last_txs = MagicMock(return_value=txs) - db_state.get_block_by_number = Mock() - db_state.get_block_by_number.side_effect = blocks - - p2p_factory = Mock(spec=P2PFactory) - p2p_factory.pow = Mock(spec=POW) - - chain_manager = ChainManager(db_state) - chain_manager.tx_pool = Mock() - chain_manager.tx_pool.transactions = heapq.nlargest(len(txpool), txpool) - chain_manager.tx_pool.transaction_pool = txpool - chain_manager._last_block = Mock() - chain_manager._last_block.block_number = len(blocks) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode.get_block_from_index = MagicMock(return_value=None) - - qrlnode._p2pfactory = p2p_factory - qrlnode._pow = p2p_factory.pow - - service = PublicAPIService(qrlnode) - context = Mock(spec=ServicerContext) - - request = qrl_pb2.GetLatestDataReq(filter=qrl_pb2.GetLatestDataReq.ALL, - offset=1, - quantity=3) - - response = service.GetLatestData(request=request, context=context) - - context.set_code.assert_not_called() - context.set_details.assert_not_called() - - # Verify blockheaders - self.assertEqual(3, len(response.blockheaders)) - self.assertEqual(1, response.blockheaders[0].header.block_number) - self.assertEqual(2, response.blockheaders[1].header.block_number) - self.assertEqual(3, response.blockheaders[2].header.block_number) - - # Verify transactions_unconfirmed - self.assertEqual(3, len(response.transactions_unconfirmed)) - # TODO: Verify expected order - self.assertEqual(1013, response.transactions_unconfirmed[0].tx.transfer.amounts[0]) - self.assertEqual(1012, response.transactions_unconfirmed[1].tx.transfer.amounts[0]) - self.assertEqual(1011, response.transactions_unconfirmed[2].tx.transfer.amounts[0]) - - # Verify transactions - self.assertEqual(3, len(response.transactions)) - self.assertEqual(2, response.transactions[0].tx.fee) - self.assertEqual(1, response.transactions[1].tx.fee) - self.assertEqual(2, response.transactions[2].tx.fee) - - self.assertEqual(102, response.transactions[0].tx.transfer.amounts[0]) - self.assertEqual(201, response.transactions[1].tx.transfer.amounts[0]) - self.assertEqual(202, response.transactions[2].tx.transfer.amounts[0]) - - def test_GetAddressFromPK(self): + with set_qrl_dir('no_data'): + db_state = State() + chain_manager = ChainManager(db_state) + blocks = [] + txs = [] + alice_xmss = get_alice_xmss() + bob_xmss = get_bob_xmss() + for i in range(0, 4): + for j in range(1, 3): + txs.append(TransferTransaction.create(addrs_to=[bob_xmss.address], + amounts=[i * 100 + j], + message_data=None, + fee=j, + xmss_pk=alice_xmss.pk)) + + blocks.append(Block.create(dev_config=config.dev, + block_number=i, + prev_headerhash=sha256(b'reveal'), + prev_timestamp=10, + transactions=txs, + miner_address=alice_xmss.address, + seed_height=10, + seed_hash=None)) + block = blocks[i] + Block.put_block(db_state, + block, + None) + Block.put_block_number_mapping(db_state, + block.block_number, + qrl_pb2.BlockNumberMapping(headerhash=block.headerhash), + None) + TransactionMetadata.update_tx_metadata(db_state, block, None) + chain_manager._last_block = blocks[-1] + txpool = [] + txs = [] + for j in range(10, 15): + tx = TransferTransaction.create(addrs_to=[bob_xmss.address], + amounts=[1000 + j], + message_data=None, + fee=j, + xmss_pk=get_alice_xmss().pk) + txpool.append((tx.fee, TransactionInfo(tx, 0))) + txs.append(tx) + + p2p_factory = Mock(spec=P2PFactory) + p2p_factory.pow = Mock(spec=POW) + + chain_manager.tx_pool = Mock() + chain_manager.tx_pool.transactions = heapq.nlargest(len(txpool), txpool) + chain_manager.tx_pool.transaction_pool = txpool + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode.get_block_from_index = MagicMock(return_value=None) + + qrlnode._p2pfactory = p2p_factory + qrlnode._pow = p2p_factory.pow + + service = PublicAPIService(qrlnode) + context = Mock(spec=ServicerContext) + + request = qrl_pb2.GetLatestDataReq(filter=qrl_pb2.GetLatestDataReq.ALL, + offset=0, + quantity=3) + + response = service.GetLatestData(request=request, context=context) + + context.set_code.assert_not_called() + context.set_details.assert_not_called() + + # Verify blockheaders + self.assertEqual(3, len(response.blockheaders)) + self.assertEqual(1, response.blockheaders[0].header.block_number) + self.assertEqual(2, response.blockheaders[1].header.block_number) + self.assertEqual(3, response.blockheaders[2].header.block_number) + + # Verify transactions_unconfirmed + self.assertEqual(3, len(response.transactions_unconfirmed)) + # TODO: Verify expected order + self.assertEqual(1014, response.transactions_unconfirmed[0].tx.transfer.amounts[0]) + self.assertEqual(1013, response.transactions_unconfirmed[1].tx.transfer.amounts[0]) + self.assertEqual(1012, response.transactions_unconfirmed[2].tx.transfer.amounts[0]) + + # Verify transactions + self.assertEqual(3, len(response.transactions)) + self.assertEqual(2, response.transactions[0].tx.fee) + self.assertEqual(1, response.transactions[1].tx.fee) + self.assertEqual(2, response.transactions[2].tx.fee) + + self.assertEqual(302, response.transactions[0].tx.transfer.amounts[0]) + self.assertEqual(301, response.transactions[1].tx.transfer.amounts[0]) + self.assertEqual(202, response.transactions[2].tx.transfer.amounts[0]) + + def test_getAddressFromPK(self): p2p_factory = Mock(spec=P2PFactory) p2p_factory.sync_state = SyncState() p2p_factory.num_connections = 23 @@ -415,34 +434,82 @@ def test_GetTokenTxn_Error(self): service.GetTokenTxn(request=request, context=context) context.set_code.assert_called_with(StatusCode.INVALID_ARGUMENT) - def test_getTransactionsByAddress(self): - db_state = Mock(spec=State) - - p2p_factory = Mock(spec=P2PFactory) - p2p_factory.pow = Mock(spec=POW) - - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._pow = p2p_factory.pow - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - # Find a transaction - alice_xmss = get_alice_xmss() - db_state.get_address_state = MagicMock(return_value=AddressState.get_default(alice_xmss.address)) - db_state.address_used = MagicMock(return_value=False) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetTransactionsByAddressReq(address=alice_xmss.address) - response = service.GetTransactionsByAddress(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(len(response.mini_transactions), 0) - self.assertEqual(response.balance, 0) + @patch('qrl.core.config.DevConfig', new_callable=PropertyMock) + def test_getMiniTransactionsByAddress(self, mock_dev_config): + mock_dev_config.data_per_page = 5 + with set_qrl_dir('no_data'): + db_state = State() + + p2p_factory = Mock(spec=P2PFactory) + p2p_factory.pow = Mock(spec=POW) + + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._pow = p2p_factory.pow + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + # Find a transaction + alice_xmss = get_alice_xmss(8) + + context = Mock(spec=ServicerContext) + bob_xmss = get_bob_xmss(4) + txs = [] + for i in range(0, 100): + tx = TransferTransaction.create(addrs_to=[bob_xmss.address], + amounts=[10], + message_data=None, + fee=0, + xmss_pk=alice_xmss.pk) + tx.sign(alice_xmss) + txs.append(tx) + addresses_set = {bob_xmss.address, alice_xmss.address} + block = Block.create(config.dev, 10, b'', 100000000, txs, + alice_xmss.address, seed_height=0, seed_hash=None) + state_container = chain_manager.new_state_container(addresses_set, + 5, + True, + None) + for tx in txs: + chain_manager.update_state_container(tx, state_container) + + address_state = state_container.addresses_state[tx.addr_from] + state_container.paginated_tx_hash.insert(address_state, tx.txhash) + + address_state = state_container.addresses_state[tx.addrs_to[0]] + state_container.paginated_tx_hash.insert(address_state, tx.txhash) + state_container.paginated_tx_hash.put_paginated_data(None) + OptimizedAddressState.put_optimized_addresses_state(db_state, state_container.addresses_state) + + TransactionMetadata.update_tx_metadata(db_state, block, None) + request = qrl_pb2.GetMiniTransactionsByAddressReq(address=alice_xmss.address, + item_per_page=10, + page_number=1) + response = service.GetMiniTransactionsByAddress(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(len(response.mini_transactions), 10) + for i in range(0, 10): + self.assertEqual(bin2hstr(txs[len(txs) - i - 1].txhash), + response.mini_transactions[i].transaction_hash) + self.assertEqual(response.balance, 0) + + TransactionMetadata.update_tx_metadata(db_state, block, None) + request = qrl_pb2.GetMiniTransactionsByAddressReq(address=alice_xmss.address, + item_per_page=8, + page_number=3) + response = service.GetMiniTransactionsByAddress(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(len(response.mini_transactions), 8) + for i in range(0, 8): + self.assertEqual(bin2hstr(txs[len(txs) - i - 17].txhash), + response.mini_transactions[i].transaction_hash) + self.assertEqual(response.balance, 0) def test_getTransaction(self): db_state = Mock(spec=State) @@ -471,6 +538,7 @@ def test_getTransaction(self): tx1 = TransferTransaction.create( addrs_to=[bob_xmss.address], amounts=[125], + message_data=None, fee=19, xmss_pk=bob_xmss.pk, master_addr=alice_xmss.address) @@ -494,222 +562,251 @@ def test_getTransaction(self): self.assertEqual(19, response.tx.fee) def test_getBalance(self): - db_state = Mock(spec=State) - alice_xmss = get_alice_xmss() - address_state = AddressState.create(address=alice_xmss.address, - nonce=25, - balance=10, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - db_state.get_address_state = MagicMock(return_value=address_state) - - p2p_factory = Mock(spec=P2PFactory) - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetAddressStateReq() - service.GetAddressState(request=request, context=context) - context.set_code.assert_called() - context.set_details.assert_called() - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetBalanceReq() - request.address = get_alice_xmss().address - response = service.GetBalance(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(10, response.balance) + with set_qrl_dir('no_data'): + db_state = State() + alice_xmss = get_alice_xmss() + optimized_address_state = OptimizedAddressState.create(address=alice_xmss.address, + nonce=25, + balance=10, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + addresses_state = {optimized_address_state.address: optimized_address_state} + OptimizedAddressState.put_optimized_addresses_state(db_state, addresses_state) + + p2p_factory = Mock(spec=P2PFactory) + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetAddressStateReq() + service.GetAddressState(request=request, context=context) + context.set_code.assert_called() + context.set_details.assert_called() + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetBalanceReq() + request.address = get_alice_xmss().address + response = service.GetBalance(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(10, response.balance) def test_getTotalBalance(self): - db_state = Mock(spec=State) - xmss1 = get_alice_xmss() - xmss2 = get_alice_xmss(4) - xmss3 = get_bob_xmss(4) - address_state1 = AddressState.create(address=xmss1.address, - nonce=25, - balance=1000, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - address_state2 = AddressState.create(address=xmss2.address, - nonce=25, - balance=2000, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - address_state3 = AddressState.create(address=xmss3.address, - nonce=25, - balance=3000, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - m = MockFunction() - m.put(xmss1.address, address_state1) - m.put(xmss2.address, address_state2) - m.put(xmss3.address, address_state3) - db_state.get_address_state = m.get - - p2p_factory = Mock(spec=P2PFactory) - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetAddressStateReq() - service.GetAddressState(request=request, context=context) - context.set_code.assert_called() - context.set_details.assert_called() - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetTotalBalanceReq() - request.addresses.extend([xmss1.address, xmss2.address, xmss3.address]) - response = service.GetTotalBalance(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(6000, response.balance) + with set_qrl_dir('no_data'): + db_state = State() + + xmss1 = get_alice_xmss() + xmss2 = get_alice_xmss(4) + xmss3 = get_bob_xmss(4) + address_state1 = OptimizedAddressState.create(address=xmss1.address, + nonce=25, + balance=1000, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + address_state2 = OptimizedAddressState.create(address=xmss2.address, + nonce=25, + balance=2000, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + address_state3 = OptimizedAddressState.create(address=xmss3.address, + nonce=25, + balance=3000, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + AddressState.put_address_state(db_state, address_state1) + AddressState.put_address_state(db_state, address_state2) + AddressState.put_address_state(db_state, address_state3) + + p2p_factory = Mock(spec=P2PFactory) + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetAddressStateReq() + service.GetAddressState(request=request, context=context) + context.set_code.assert_called() + context.set_details.assert_called() + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetTotalBalanceReq() + request.addresses.extend([xmss1.address, xmss2.address, xmss3.address]) + response = service.GetTotalBalance(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(6000, response.balance) def test_getOTS(self): - db_state = Mock(spec=State) - alice_xmss = get_alice_xmss() - address_state = AddressState.create(address=alice_xmss.address, - nonce=25, - balance=10, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - db_state.get_address_state = MagicMock(return_value=address_state) - - p2p_factory = Mock(spec=P2PFactory) - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetOTSReq() - request.address = get_alice_xmss().address - response = service.GetOTS(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(0, response.next_unused_ots_index) - - address_state.set_ots_key(0) - - response = service.GetOTS(request=request, context=context) - context.set_code.assert_not_called() - - self.assertEqual(1, response.next_unused_ots_index) + with set_qrl_dir('no_data'): + db_state = State() + alice_xmss = get_alice_xmss() + optimized_address_state = OptimizedAddressState.create(address=alice_xmss.address, + nonce=25, + balance=10, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + addresses_state = {optimized_address_state.address: optimized_address_state} + AddressState.put_addresses_state(db_state, addresses_state) + + p2p_factory = Mock(spec=P2PFactory) + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetOTSReq(address=alice_xmss.address) + response = service.GetOTS(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(0, response.next_unused_ots_index) + + paginated_bitfield = PaginatedBitfield(True, db_state._db) + paginated_bitfield.set_ots_key(addresses_state, optimized_address_state.address, 0) + paginated_bitfield.put_addresses_bitfield(None) + + response = service.GetOTS(request=request, context=context) + context.set_code.assert_not_called() + + self.assertEqual(1, response.next_unused_ots_index) def test_getHeight(self): - db_state = Mock(spec=State) - alice_xmss = get_alice_xmss() - address_state = AddressState.create(address=alice_xmss.address, - nonce=25, - balance=10, - ots_bitfield=[b'\x00'] * config.dev.ots_bitfield_size, - tokens=dict(), - slave_pks_access_type=dict(), - ots_counter=0) - db_state.get_address_state = MagicMock(return_value=address_state) - - p2p_factory = Mock(spec=P2PFactory) - chain_manager = ChainManager(db_state) - chain_manager._last_block = Mock() - chain_manager._last_block.block_number = 100 - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetHeightReq() - response = service.GetHeight(request=request, context=context) - self.assertEqual(response.height, 100) + with set_qrl_dir('no_data'): + db_state = State() + alice_xmss = get_alice_xmss() + optimized_address_state = OptimizedAddressState.create(address=alice_xmss.address, + nonce=25, + balance=10, + ots_bitfield_used_page=0, + transaction_hash_count=0, + tokens_count=0, + lattice_pk_count=0, + slaves_count=0, + multi_sig_address_count=0) + addresses_state = {optimized_address_state.address: optimized_address_state} + AddressState.put_addresses_state(db_state, addresses_state) + + p2p_factory = Mock(spec=P2PFactory) + chain_manager = ChainManager(db_state) + chain_manager._last_block = Mock() + chain_manager._last_block.block_number = 100 + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetHeightReq() + response = service.GetHeight(request=request, context=context) + self.assertEqual(response.height, 100) def test_getBlock(self): - db_state = Mock(spec=State) - db_state.get_tx_metadata = MagicMock(return_value=None) - db_state.get_block = MagicMock(return_value=None) - - p2p_factory = Mock(spec=P2PFactory) - p2p_factory.pow = Mock(spec=POW) - - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._pow = p2p_factory.pow - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - alice_xmss = get_alice_xmss() - b = Block.create(block_number=1, - prev_headerhash=sha256(b'reveal'), - prev_timestamp=10, - transactions=[], - miner_address=alice_xmss.address) - db_state.get_block = MagicMock(return_value=b) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetBlockReq(header_hash=b.headerhash) - response = service.GetBlock(request=request, context=context) - context.set_code.assert_not_called() - self.assertEqual(1, response.block.header.block_number) + with set_qrl_dir('no_data'): + db_state = State() + + p2p_factory = Mock(spec=P2PFactory) + p2p_factory.pow = Mock(spec=POW) + + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._pow = p2p_factory.pow + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + alice_xmss = get_alice_xmss() + b = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=sha256(b'reveal'), + prev_timestamp=10, + transactions=[], + miner_address=alice_xmss.address, + seed_height=0, + seed_hash=None) + Block.put_block(db_state, b, None) + db_state.get_block = MagicMock(return_value=b) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetBlockReq(header_hash=b.headerhash) + response = service.GetBlock(request=request, context=context) + context.set_code.assert_not_called() + self.assertEqual(1, response.block.header.block_number) def test_getBlockByNumber(self): - db_state = Mock(spec=State) - db_state.get_tx_metadata = MagicMock(return_value=None) - db_state.get_block = MagicMock(return_value=None) - - p2p_factory = Mock(spec=P2PFactory) - p2p_factory.pow = Mock(spec=POW) - - chain_manager = ChainManager(db_state) - - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) - qrlnode._p2pfactory = p2p_factory - qrlnode._pow = p2p_factory.pow - qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] - - service = PublicAPIService(qrlnode) - - alice_xmss = get_alice_xmss() - b = Block.create(block_number=1, - prev_headerhash=sha256(b'reveal'), - prev_timestamp=10, - transactions=[], - miner_address=alice_xmss.address) - db_state.get_block_by_number = MagicMock(return_value=b) - - context = Mock(spec=ServicerContext) - request = qrl_pb2.GetBlockByNumberReq(block_number=b.block_number) - response = service.GetBlockByNumber(request=request, context=context) - context.set_code.assert_not_called() - self.assertEqual(1, response.block.header.block_number) + with set_qrl_dir('no_data'): + db_state = State() + + p2p_factory = Mock(spec=P2PFactory) + p2p_factory.pow = Mock(spec=POW) + + chain_manager = ChainManager(db_state) + + qrlnode = QRLNode(mining_address=b'') + qrlnode.set_chain_manager(chain_manager) + qrlnode._p2pfactory = p2p_factory + qrlnode._pow = p2p_factory.pow + qrlnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] + + service = PublicAPIService(qrlnode) + + alice_xmss = get_alice_xmss() + b = Block.create(dev_config=config.dev, + block_number=1, + prev_headerhash=sha256(b'reveal'), + prev_timestamp=10, + transactions=[], + miner_address=alice_xmss.address, + seed_height=0, + seed_hash=None) + Block.put_block(db_state, b, None) + Block.put_block_number_mapping(db_state, + b.block_number, + qrl_pb2.BlockNumberMapping(headerhash=b.headerhash), + None) + db_state.get_block_by_number = MagicMock(return_value=b) + + context = Mock(spec=ServicerContext) + request = qrl_pb2.GetBlockByNumberReq(block_number=b.block_number) + response = service.GetBlockByNumber(request=request, context=context) + context.set_code.assert_not_called() + self.assertEqual(1, response.block.header.block_number) diff --git a/tests/services/test_WalletAPIService.py b/tests/services/test_WalletAPIService.py index db82e26a0..1a38651a3 100644 --- a/tests/services/test_WalletAPIService.py +++ b/tests/services/test_WalletAPIService.py @@ -7,7 +7,7 @@ from pyqrllib.pyqrllib import bin2hstr, hstr2bin from qrl.core.misc import logger -from qrl.core.AddressState import AddressState +from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.daemon.walletd import WalletD from qrl.generated import qrlwallet_pb2, qrl_pb2 from qrl.services.WalletAPIService import WalletAPIService @@ -137,9 +137,14 @@ def test_relayTransferTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -169,12 +174,14 @@ def test_relayTransferTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) - - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -193,16 +200,19 @@ def test_relayTransferTxnBySlave(self): def test_relayMessageTxn(self): with set_qrl_dir("wallet_ver1"): walletd = WalletD() + walletd._public_stub.PushTransaction = Mock( + return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + service = WalletAPIService(walletd) resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) - - walletd._public_stub.PushTransaction = Mock( - return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) resp = service.RelayMessageTxn(qrlwallet_pb2.RelayMessageTxnReq(message=b'Hello QRL!', fee=100000000, @@ -223,12 +233,14 @@ def test_relayMessageTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) - - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) resp = service.RelayMessageTxnBySlave( qrlwallet_pb2.RelayMessageTxnReq(message=b'Hello QRL!', @@ -245,9 +257,14 @@ def test_relayTokenTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -281,12 +298,14 @@ def test_relayTokenTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) - - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -313,9 +332,14 @@ def test_relayTransferTokenTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -346,12 +370,14 @@ def test_relayTransferTokenTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) - - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) bob_xmss = get_bob_xmss(4) @@ -375,9 +401,14 @@ def test_relaySlaveTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) slave_pks = [alice_xmss.pk] @@ -406,12 +437,14 @@ def test_relaySlaveTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) - slaves = walletd.get_slave_list(qaddress) - - addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) + addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) + walletd._public_stub.IsSlave = Mock( + return_value=qrl_pb2.IsSlaveResp(result=True)) + walletd._public_stub.GetOTS = Mock( + return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, + unused_ots_index_found=True)) alice_xmss = get_alice_xmss(4) slave_pks = [alice_xmss.pk] @@ -544,17 +577,19 @@ def test_changePassphrase(self): resp = service.UnlockWallet(qrlwallet_pb2.UnlockWalletReq(passphrase=new_passphrase), context=None) self.assertEqual(resp.code, 0) - def test_getTransactionsByAddress(self): + def test_getMiniTransactionsByAddress(self): with set_qrl_dir("wallet_ver1"): walletd = WalletD() service = WalletAPIService(walletd) - walletd._public_stub.GetTransactionsByAddress = Mock( - return_value=qrl_pb2.GetTransactionsByAddressResp(mini_transactions=[], - balance=0)) + walletd._public_stub.GetMiniTransactionsByAddress = Mock( + return_value=qrl_pb2.GetMiniTransactionsByAddressResp(mini_transactions=[], + balance=0)) - resp = service.GetTransactionsByAddress( - qrlwallet_pb2.TransactionsByAddressReq(address=get_alice_xmss(4).qaddress), context=None) + resp = service.GetMiniTransactionsByAddress( + qrlwallet_pb2.MiniTransactionsByAddressReq(address=get_alice_xmss(4).qaddress, + item_per_page=10, + page_number=1), context=None) self.assertEqual(resp.code, 0) self.assertEqual(len(resp.mini_transactions), 0) @@ -614,13 +649,17 @@ def test_getOTS(self): walletd = WalletD() service = WalletAPIService(walletd) + ots_bitfield_by_page = qrl_pb2.OTSBitfieldByPage(ots_bitfield=[b'\x00'] * 10, + page_number=1) walletd._public_stub.GetOTS = Mock( - return_value=qrl_pb2.GetOTSResp(ots_bitfield=[b'\x00'] * 10, next_unused_ots_index=1)) + return_value=qrl_pb2.GetOTSResp(ots_bitfield_by_page=[ots_bitfield_by_page], + next_unused_ots_index=1, + unused_ots_index_found=True)) resp = service.GetOTS(qrlwallet_pb2.OTSReq(address=self.qaddress), context=None) - self.assertEqual(resp.code, 0) - self.assertEqual(resp.ots_bitfield, [b'\x00'] * 10) + self.assertEqual(len(resp.ots_bitfield_by_page), 1) + self.assertEqual(resp.ots_bitfield_by_page[0], ots_bitfield_by_page) self.assertEqual(resp.next_unused_ots_index, 1) def test_getHeight(self): From 53407d0aa8ff0bd79e51e13f3f3440f5bd4595dd Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 5 Feb 2020 17:59:37 +0530 Subject: [PATCH 02/67] Removed unused imports & some codacy fixes --- src/qrl/core/BlockHeader.py | 6 +- src/qrl/core/Indexer.py | 5 +- src/qrl/core/LastTransactions.py | 4 +- src/qrl/core/MultiSigAddressState.py | 4 +- src/qrl/core/PaginatedData.py | 60 -------------- src/qrl/core/State.py | 2 +- src/qrl/core/TransactionInfo.py | 1 - src/qrl/core/TransactionMetadata.py | 16 +--- src/qrl/core/config.py | 5 +- src/qrl/core/misc/db.py | 83 +------------------ src/qrl/core/misc/set_logger.py | 1 - src/qrl/core/processors/TxnProcessor.py | 3 - src/qrl/core/qrlnode.py | 8 +- src/qrl/daemon/walletd.py | 4 +- tests/core/test_Miner.py | 2 - tests/core/test_MultiSigAddressState.py | 2 +- tests/core/test_block.py | 2 +- tests/core/test_qrlnode.py | 2 +- tests/core/txs/test_SlaveTransaction.py | 2 +- tests/core/txs/test_TokenTransaction.py | 2 +- .../core/txs/test_TransferTokenTransaction.py | 2 +- tests/misc/helper.py | 2 +- 22 files changed, 26 insertions(+), 192 deletions(-) diff --git a/src/qrl/core/BlockHeader.py b/src/qrl/core/BlockHeader.py index 5b4907965..403e35696 100644 --- a/src/qrl/core/BlockHeader.py +++ b/src/qrl/core/BlockHeader.py @@ -68,10 +68,12 @@ def extra_nonce(self): def mining_nonce(self): return self._data.mining_nonce - def nonce_offset(self, dev_config: DevConfig): + @staticmethod + def nonce_offset(dev_config: DevConfig): return dev_config.mining_nonce_offset - def extra_nonce_offset(self, dev_config: DevConfig): + @staticmethod + def extra_nonce_offset(dev_config: DevConfig): return dev_config.extra_nonce_offset def mining_blob(self, dev_config: DevConfig) -> bytes: diff --git a/src/qrl/core/Indexer.py b/src/qrl/core/Indexer.py index 2955154e4..d70d114ab 100644 --- a/src/qrl/core/Indexer.py +++ b/src/qrl/core/Indexer.py @@ -2,12 +2,11 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. -from qrl.core.misc import db from qrl.generated.qrl_pb2 import SlaveMetadata class Indexer: - def __init__(self, name: bytes, db: db): + def __init__(self, name: bytes, db): self._name = name self._db = db # self._data = IndexerData(self._name) @@ -35,7 +34,7 @@ def load(self, key) -> bool: return True def remove(self, batch=None): - for key, value in self._data.items(): + for key in self._data.items(): self._db.delete(self.generate_key(key), batch) def generate_key(self, keys) -> bytes: diff --git a/src/qrl/core/LastTransactions.py b/src/qrl/core/LastTransactions.py index c4852d8f3..116072408 100644 --- a/src/qrl/core/LastTransactions.py +++ b/src/qrl/core/LastTransactions.py @@ -45,7 +45,7 @@ def _remove_last_tx(state: State, block: Block, batch): try: last_txn = LastTransactions.deserialize(state._db.get_raw(b'last_txn')) - except: # noqa + except KeyError: return for protobuf_txn in block.transactions: @@ -68,7 +68,7 @@ def _update_last_tx(state: State, block: Block, batch): try: last_txn = LastTransactions.deserialize(state._db.get_raw(b'last_txn')) - except: # noqa + except KeyError: pass for protobuf_txn in block.transactions[-20:]: diff --git a/src/qrl/core/MultiSigAddressState.py b/src/qrl/core/MultiSigAddressState.py index 9f9d568e1..2366d5735 100644 --- a/src/qrl/core/MultiSigAddressState.py +++ b/src/qrl/core/MultiSigAddressState.py @@ -178,11 +178,9 @@ def get_multi_sig_address_state_by_address(db, @staticmethod def get_multi_sig_address_by_shared_key(state: State, shared_key: bytes): - tx, block_number = TransactionMetadata.get_tx_metadata(state, shared_key) + tx, _ = TransactionMetadata.get_tx_metadata(state, shared_key) if tx is None: return None - # if not isinstance(tx, MultiSigSpend): - # return None return tx.multi_sig_address @staticmethod diff --git a/src/qrl/core/PaginatedData.py b/src/qrl/core/PaginatedData.py index 64ead409c..e32641683 100644 --- a/src/qrl/core/PaginatedData.py +++ b/src/qrl/core/PaginatedData.py @@ -50,37 +50,6 @@ def remove(self, address_state, value: bytes): del self.key_value[storage_key][-1] - """ - states_with_counter: It could be address state, vote stats, proposal vote stats, proposal record - """ - # def put_paginated_data(self, states_with_counter: dict, batch) -> bool: - # data = dict() - # key_value = self.key_value - # self.key_value = dict() - # for key in key_value: - # my_state = states_with_counter[key] - # t = self.get_paginated_data(key=key, - # count=my_state.get_counter_by_name(self.name)) - # my_state.update_counter_by_name(self.name, len(t), subtract=True) - # t.extend(key_value[key]) - # data[key] = t - # - # for key in data: - # full_hashes = data[key] - # start = 0 - # hashes = full_hashes[start:start + config.dev.data_per_page] - # while hashes: - # my_state = states_with_counter[key] - # self.put(key, - # my_state.get_counter_by_name(self.name), - # hashes, - # batch) - # my_state.update_counter_by_name(self.name, len(hashes)) - # start += config.dev.data_per_page - # hashes = full_hashes[start:start + config.dev.data_per_page] - # - # return True - def put_paginated_data(self, batch) -> bool: key_value = self.key_value self.key_value = dict() @@ -123,32 +92,3 @@ def delete(self, storage_key, batch): return self.db.delete(storage_key, batch) - - # def revert_paginated_data(self, states_with_counter: dict, batch) -> bool: - # key_value = self.key_value - # self.key_value = dict() - # for key in key_value: - # v = states_with_counter[key] - # data = self.get_paginated_data(key, v.get_counter_by_name(self.name)) - # - # for value in key_value[key]: - # if data[-1] != value: - # logger.warning("Mismatch Paginated data", data[-5:], value) - # return False - # del data[-1] - # v.update_counter_by_name(self.name, subtract=True) - # if len(data) == 0: - # self.delete(key, - # v.get_counter_by_name(self.name), - # batch) - # if v.get_counter_by_name(self.name) > 0: - # data = self.get_paginated_data(key, - # v.get_counter_by_name(self.name) - 1) - # - # if data: - # self.put(key, - # v.get_counter_by_name(self.name), - # data, - # batch) - # - # return True diff --git a/src/qrl/core/State.py b/src/qrl/core/State.py index 7f43dd901..9b2aed311 100644 --- a/src/qrl/core/State.py +++ b/src/qrl/core/State.py @@ -279,7 +279,7 @@ def revert_slaves_hash(self, slaves: dict, addresses_state: dict, batch): def put_slaves_hash(self, slaves: dict, addresses_state: dict, batch=None): slave_hashes = dict() for address_slave_pk in slaves: - address, slave_pk = address_slave_pk + address, _ = address_slave_pk # There could be case where same address associated with multiple # slave_pk so full_hashes needs to be loaded only once if address not in slave_hashes: diff --git a/src/qrl/core/TransactionInfo.py b/src/qrl/core/TransactionInfo.py index 784a21986..d0dd61ba6 100644 --- a/src/qrl/core/TransactionInfo.py +++ b/src/qrl/core/TransactionInfo.py @@ -4,7 +4,6 @@ from qrl.core import config from qrl.core.misc import ntp -from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.Transaction import Transaction diff --git a/src/qrl/core/TransactionMetadata.py b/src/qrl/core/TransactionMetadata.py index 793b63589..a5036c57e 100644 --- a/src/qrl/core/TransactionMetadata.py +++ b/src/qrl/core/TransactionMetadata.py @@ -73,13 +73,6 @@ def rollback_tx_metadata(state: State, block, batch): txn = Transaction.from_pbdata(protobuf_txn) fee_reward += txn.fee TransactionMetadata.remove_tx_metadata(state, txn, batch) - # FIXME: Being updated without batch, need to fix, - # if isinstance(txn, TransferTokenTransaction): - # self.remove_transfer_token_metadata(txn) - # elif isinstance(txn, TokenTransaction): - # self.remove_token_metadata(txn) - # self._decrease_txn_count(self.get_txn_count(txn.addr_from), - # txn.addr_from) txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction state._update_total_coin_supply(fee_reward - txn.amount, batch) @@ -97,13 +90,6 @@ def update_tx_metadata(state: State, block, batch): block.block_number, block.timestamp, batch) - # FIXME: Being updated without batch, need to fix, - # if isinstance(txn, TransferTokenTransaction): - # self.update_token_metadata(txn) - # elif isinstance(txn, TokenTransaction): - # self.create_token_metadata(txn) - # self._increase_txn_count(self.get_txn_count(txn.addr_from), - # txn.addr_from) txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction state._update_total_coin_supply(txn.amount - fee_reward, batch) @@ -113,5 +99,5 @@ def update_tx_metadata(state: State, block, batch): def remove_tx_metadata(state: State, txn, batch): try: state._db.delete(txn.txhash, batch) - except Exception: + except KeyError: pass diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index 2a82fe1ad..8fe45f796 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -521,13 +521,10 @@ def create(prev_state_key, foundation_multi_sig=foundation_multi_sig, proposal=proposal) - pow = qrl_pb2.DevConfig.POW(N_measurement=30, - kp=5) - dev_config = qrl_pb2.DevConfig(chain=chain, block=block, transaction=transaction, - pow=pow) + pow=qrl_pb2.DevConfig.POW(N_measurement=30, kp=5)) if prev_state_key is not None: dev_config.prev_state_key = prev_state_key diff --git a/src/qrl/core/misc/db.py b/src/qrl/core/misc/db.py index 2ef62ef5d..aa8376479 100644 --- a/src/qrl/core/misc/db.py +++ b/src/qrl/core/misc/db.py @@ -74,85 +74,6 @@ def get_raw(self, key): def get_batch(self): return self.db.write_batch() - def write_batch(self, batch, sync=True): + @staticmethod + def write_batch(batch, sync=True): batch.write() - - - - - -# -# -# -# -# -# # coding=utf-8 -# # Distributed under the MIT software license, see the accompanying -# # file LICENSE or http://www.opensource.org/licenses/mit-license.php. -# -# # leveldb code for maintaining account state data -# #import leveldb -# import plyvel -# import os -# -# from qrl.core import config -# from qrl.core.misc import logger -# -# __author__ = 'pete' -# -# -# class DB: -# def __init__(self, db_dir=None): -# self.db_dir = os.path.join(config.user.data_dir, config.dev.db_name) -# if db_dir: -# self.db_dir = db_dir -# logger.info('DB path: %s', self.db_dir) -# -# os.makedirs(self.db_dir, exist_ok=True) -# -# # TODO: leveldb python module is not very active. Decouple and replace -# #self.db = leveldb.LevelDB(self.db_dir) -# self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5*1024) -# -# def close(self): -# del self.db -# -# def open(self, db_dir=None): -# if db_dir: -# self.db_dir = db_dir -# self.db = leveldb.LevelDB(self.db_dir) -# -# def RangeIter(self, key_obj_start, key_obj_end): -# if not isinstance(key_obj_start, bytes): -# key_obj_start = key_obj_start.encode() -# -# if not isinstance(key_obj_end, bytes): -# key_obj_end = key_obj_end.encode() -# -# return self.db.RangeIter(key_obj_start, key_obj_end) -# -# def get_db_keys(self, include_value: bool): -# return self.db.RangeIter(include_value=include_value) -# -# def delete(self, key_obj: bytes, batch=None): -# if batch: -# batch.Delete(key_obj) -# else: -# self.db.Delete(key_obj) -# -# def put_raw(self, key, value, batch=None): -# if batch: -# batch.Put(key, value) -# else: -# self.db.Put(key, value) -# -# def get_raw(self, key): -# if isinstance(key, str): -# key = bytes(key, 'utf-8') -# return self.db.Get(key) -# -# def get_batch(self): -# return leveldb.WriteBatch() -# -# def write_batch(self, batch, sync=True): -# self.db.Write(batch, sync=sync) diff --git a/src/qrl/core/misc/set_logger.py b/src/qrl/core/misc/set_logger.py index a60de08b9..549551e58 100644 --- a/src/qrl/core/misc/set_logger.py +++ b/src/qrl/core/misc/set_logger.py @@ -1,5 +1,4 @@ import logging -import sys import threading from qrl.core.misc import logger, logger_twisted diff --git a/src/qrl/core/processors/TxnProcessor.py b/src/qrl/core/processors/TxnProcessor.py index 2da0b1eab..18861a3ad 100644 --- a/src/qrl/core/processors/TxnProcessor.py +++ b/src/qrl/core/processors/TxnProcessor.py @@ -7,9 +7,6 @@ from qrl.core import ChainManager from qrl.core.TransactionPool import TransactionPool from qrl.core.misc import logger -from qrl.core.txs.Transaction import Transaction -from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction -from qrl.core.txs.SlaveTransaction import SlaveTransaction class TxnProcessor: diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index f31eb448c..5204549d8 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -326,8 +326,8 @@ def create_send_tx(self, xmss_pk=xmss_pk, master_addr=master_addr) - def create_slave_tx(self, - slave_pks: list, + @staticmethod + def create_slave_tx(slave_pks: list, access_types: list, fee: int, xmss_pk: bytes, @@ -338,8 +338,8 @@ def create_slave_tx(self, xmss_pk=xmss_pk, master_addr=master_addr) - def create_lattice_tx(self, - pk1: bytes, + @staticmethod + def create_lattice_tx(pk1: bytes, pk2: bytes, pk3: bytes, pk4: bytes, diff --git a/src/qrl/daemon/walletd.py b/src/qrl/daemon/walletd.py index efaa34795..f45ce5caa 100644 --- a/src/qrl/daemon/walletd.py +++ b/src/qrl/daemon/walletd.py @@ -389,9 +389,7 @@ def get_slave(self, master_qaddress): # Relay slave txn using master address using ots index 0 return index, -1, -1, None - for slave_index in range(len(slave_group)): - slave = slave_group[slave_index] - + for slave_index, slave in enumerate(slave_group): if slave.index > 2 ** slave.height - 1: continue diff --git a/tests/core/test_Miner.py b/tests/core/test_Miner.py index 6fd6cadc6..4e610dcfd 100644 --- a/tests/core/test_Miner.py +++ b/tests/core/test_Miner.py @@ -36,13 +36,11 @@ def setUp(self): self.chain_manager = Mock(spec=ChainManager) self.chain_manager.get_block_size_limit.return_value = 500 - # self.chain_manager.get_address_state.return_value = self.alice_address_state self.chain_manager.get_config_by_block_number.return_value = config.dev self.parent_block = Block() self.parent_difficulty = StringToUInt256('0') # tuple (0,0,0,0,0...) length 32 self.m_pre_block_logic = Mock(spec=POW.pre_block_logic, name='hello') - m_add_unprocessed_txn_fn = create_autospec(P2PFactory.add_unprocessed_txn) mining_thread_count = 1 self.miner = Miner(self.chain_manager, diff --git a/tests/core/test_MultiSigAddressState.py b/tests/core/test_MultiSigAddressState.py index 0e12d0045..0dcc396b1 100644 --- a/tests/core/test_MultiSigAddressState.py +++ b/tests/core/test_MultiSigAddressState.py @@ -1,7 +1,7 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. -from pyqrllib.pyqrllib import hstr2bin, bin2hstr +from pyqrllib.pyqrllib import hstr2bin from unittest import TestCase from qrl.core.misc import logger diff --git a/tests/core/test_block.py b/tests/core/test_block.py index e6e05b5c6..e1c29c292 100644 --- a/tests/core/test_block.py +++ b/tests/core/test_block.py @@ -2,7 +2,7 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from unittest import TestCase -from mock import patch, Mock, PropertyMock, MagicMock +from mock import patch, Mock, PropertyMock from pyqrllib.pyqrllib import sha2_256 from collections import OrderedDict diff --git a/tests/core/test_qrlnode.py b/tests/core/test_qrlnode.py index 69b934bfd..57d94a0a9 100644 --- a/tests/core/test_qrlnode.py +++ b/tests/core/test_qrlnode.py @@ -1,5 +1,5 @@ from unittest import TestCase -from mock import Mock, patch, PropertyMock, mock, MagicMock +from mock import Mock, patch, PropertyMock, mock from qrl.core import config from qrl.core.misc import logger diff --git a/tests/core/txs/test_SlaveTransaction.py b/tests/core/txs/test_SlaveTransaction.py index 7abb48899..997a3208a 100644 --- a/tests/core/txs/test_SlaveTransaction.py +++ b/tests/core/txs/test_SlaveTransaction.py @@ -1,6 +1,6 @@ from unittest import TestCase -from mock import patch, Mock, PropertyMock +from mock import patch, PropertyMock from qrl.core import config from qrl.core.Indexer import Indexer diff --git a/tests/core/txs/test_TokenTransaction.py b/tests/core/txs/test_TokenTransaction.py index 1a6c8007d..c17b95498 100644 --- a/tests/core/txs/test_TokenTransaction.py +++ b/tests/core/txs/test_TokenTransaction.py @@ -1,7 +1,7 @@ from unittest import TestCase import simplejson as json -from mock import patch, PropertyMock, Mock +from mock import patch, PropertyMock from pyqrllib.pyqrllib import bin2hstr from qrl.core import config diff --git a/tests/core/txs/test_TransferTokenTransaction.py b/tests/core/txs/test_TransferTokenTransaction.py index 424700ff2..356a457c8 100644 --- a/tests/core/txs/test_TransferTokenTransaction.py +++ b/tests/core/txs/test_TransferTokenTransaction.py @@ -1,7 +1,7 @@ from unittest import TestCase import simplejson as json -from mock import patch, PropertyMock, Mock +from mock import patch, PropertyMock from pyqrllib.pyqrllib import bin2hstr from qrl.core import config diff --git a/tests/misc/helper.py b/tests/misc/helper.py index ac8b00b70..acb042eb3 100644 --- a/tests/misc/helper.py +++ b/tests/misc/helper.py @@ -249,9 +249,9 @@ def gen_blocks(block_count, state, miner_address): coin_base_tx.apply(state, state_container) for tx_idx in range(1, len(block.transactions)): + tx = Transaction.from_pbdata(block.transactions[tx_idx]) if not chain_manager.update_state_container(tx, state_container): return False - tx = Transaction.from_pbdata(block.transactions[tx_idx]) tx.apply(state, state_container) block.set_nonces(dev_config=config.dev, mining_nonce=10, extra_nonce=0) From e6a93bd06e26f6053cf5c134a75314fbb7a55dbc Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 5 Feb 2020 20:50:50 +0530 Subject: [PATCH 03/67] Simplified State processing, Removed commented codes & updated unit tests --- src/qrl/core/Block.py | 7 ++- src/qrl/core/ChainManager.py | 40 +++++---------- src/qrl/core/txs/CoinBase.py | 8 +-- src/qrl/core/txs/Transaction.py | 5 ++ tests/core/test_block.py | 7 ++- tests/core/txs/test_CoinBase.py | 25 ++++++++-- tests/core/txs/test_MessageTransaction.py | 7 +-- tests/core/txs/test_SlaveTransaction.py | 2 +- tests/core/txs/test_TokenTransaction.py | 50 +------------------ .../core/txs/test_TransferTokenTransaction.py | 2 +- 10 files changed, 59 insertions(+), 94 deletions(-) diff --git a/src/qrl/core/Block.py b/src/qrl/core/Block.py index 10931b6e1..f578df7ad 100644 --- a/src/qrl/core/Block.py +++ b/src/qrl/core/Block.py @@ -204,10 +204,15 @@ def validate(self, chain_manager, future_blocks: OrderedDict) -> bool: return False try: + state_container = chain_manager.new_state_container(set(), + self.block_number, + False, + None) + coinbase_txn = Transaction.from_pbdata(self.transactions[0]) coinbase_amount = coinbase_txn.amount - if not coinbase_txn.validate_extended(self.block_number, dev_config): + if not coinbase_txn.validate_all(state_container): return False except Exception as e: diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index e1215bdf8..cad3c95d3 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -398,14 +398,12 @@ def load(self, genesis_block): for addr in tx.addrs_to: state_container.addresses_state[addr] = OptimizedAddressState.get_default(addr) - - if not isinstance(coinbase_tx, CoinBase): return False state_container.addresses_state[coinbase_tx.addr_to] = OptimizedAddressState.get_default(coinbase_tx.addr_to) - if not coinbase_tx.validate_extended(genesis_block.block_number, config.dev): + if not coinbase_tx.validate_all(state_container): return False coinbase_tx.apply(self._state, state_container) @@ -783,14 +781,13 @@ def update_state_container(self, multi_sig_spend_txs = dict() votes_stats = dict() - if isinstance(tx, CoinBase): - logger.warning("Coinbase txn found in new_state_container txn list") - return False - slave_addr = Transaction.get_slave(tx) - if slave_addr is not None: - key = (tx.addr_from, tx.PK) - if key not in state_container.slaves.data: - slaves.load(key) + if not isinstance(tx, CoinBase): + slave_addr = Transaction.get_slave(tx) + if slave_addr is not None: + key = (tx.addr_from, tx.PK) + if key not in state_container.slaves.data: + slaves.load(key) + if isinstance(tx, TransferTokenTransaction): key = (tx.addr_from, tx.token_txhash) if key not in state_container.tokens.data: @@ -801,7 +798,7 @@ def update_state_container(self, if key in state_container.tokens.data: continue tokens.load(key) - if isinstance(tx, SlaveTransaction): + elif isinstance(tx, SlaveTransaction): for slave_pk in tx.slave_pks: key = (tx.addr_from, slave_pk) if key not in state_container.slaves.data: @@ -835,7 +832,7 @@ def update_state_container(self, if address not in state_container.addresses_state: address_set.add(address) elif isinstance(tx, LatticeTransaction): - # Load lattice_pk and lattice_pk_tx_hashes + # TODO: Load lattice_pk and lattice_pk_tx_hashes pass addresses_state, success = self.get_state_mainchain(address_set, @@ -852,28 +849,17 @@ def update_state_container(self, votes_stats) def apply_state_changes(self, block, dev_config: DevConfig, batch) -> bool: - address_set = set() - - coinbase_tx = Transaction.from_pbdata(block.transactions[0]) - coinbase_tx.set_affected_address(address_set) - state_container = self.new_state_container(address_set, + state_container = self.new_state_container(set(), block.block_number, True, batch) if state_container is None: return False - if not coinbase_tx.validate_extended(block.block_number, dev_config): - logger.warning('Coinbase transaction failed') - return False - - # Processing CoinBase Txn - coinbase_tx.apply(self._state, state_container) - # Processing Rest of the Transaction len_transactions = len(block.transactions) - for tx_idx in range(1, len_transactions): - tx = Transaction.from_pbdata(block.transactions[tx_idx]) + for proto_tx in block.transactions: + tx = Transaction.from_pbdata(proto_tx) if not self.update_state_container(tx, state_container): return False diff --git a/src/qrl/core/txs/CoinBase.py b/src/qrl/core/txs/CoinBase.py index 08ed821da..19c587c7c 100644 --- a/src/qrl/core/txs/CoinBase.py +++ b/src/qrl/core/txs/CoinBase.py @@ -69,7 +69,10 @@ def _validate_custom(self): # noinspection PyBroadException # Never change this function name to _validate_extended, to keep difference between other txns & # Coinbase txn, will hit unimplemented error in case called for an coinbase txn. - def validate_extended(self, block_number, dev_config: DevConfig): + def _validate_extended(self, state_container: StateContainer): + dev_config = state_container.current_dev_config + block_number = state_container.block_number + if self.master_addr != dev_config.coinbase_address: logger.warning('Master address doesnt match with coinbase_address') logger.warning('%s %s', bin2hstr(self.master_addr), bin2hstr(dev_config.coinbase_address)) @@ -87,9 +90,6 @@ def validate_extended(self, block_number, dev_config: DevConfig): return self._validate_custom() - def _validate_extended(self, state_container: StateContainer): - raise Exception("Should not be called for a Coinbase Transaction") - def set_affected_address(self, addresses_set: set): addresses_set.add(self.master_addr) addresses_set.add(self.addr_to) diff --git a/src/qrl/core/txs/Transaction.py b/src/qrl/core/txs/Transaction.py index 5b2d4445e..919cb8782 100644 --- a/src/qrl/core/txs/Transaction.py +++ b/src/qrl/core/txs/Transaction.py @@ -229,6 +229,11 @@ def validate(self, verify_signature=True) -> bool: return True def validate_all(self, state_container: StateContainer, check_nonce=True) -> bool: + if self.pbdata.WhichOneof('transactionType') == 'coinbase': + if not self._validate_extended(state_container): + return False + return True + if not self.validate(True): # It also calls _validate_custom return False if not self.validate_slave(state_container): diff --git a/tests/core/test_block.py b/tests/core/test_block.py index e1c29c292..67fd541f1 100644 --- a/tests/core/test_block.py +++ b/tests/core/test_block.py @@ -10,6 +10,7 @@ from qrl.core import config from qrl.generated import qrl_pb2 from qrl.core.State import State +from qrl.core.StateContainer import StateContainer from qrl.core.ChainManager import ChainManager from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.Block import Block @@ -110,6 +111,8 @@ def test_validate(self): 'get_block_is_duplicate.return_value': False, 'validate_mining_nonce.return_value': True, 'get_config_by_block_number.return_value': config.dev, + 'new_state_container.return_value': StateContainer(None, None, None, None, None, None, 5, + None, config.dev, False, None, None) } m_chain_manager.configure_mock(**attrs_all_pass) self.block._validate_parent_child_relation = Mock(return_value=True) @@ -149,7 +152,7 @@ def test_validate(self): self.assertFalse(result) # There was a problem with the CoinBase TX - with patch('qrl.core.txs.CoinBase.CoinBase.validate_extended') as m_validate_extended: + with patch('qrl.core.txs.CoinBase.CoinBase._validate_extended') as m_validate_extended: m_validate_extended.return_value = False result = self.block.validate(m_chain_manager, OrderedDict()) self.assertFalse(result) @@ -329,7 +332,7 @@ def test_tx_validation_fails(self, m_TransferTransaction_validate, self.assertFalse(result) m_TransferTransaction_validate_extended.return_value = True - with patch('qrl.core.txs.CoinBase.CoinBase.validate_extended') as m_validate_extended: + with patch('qrl.core.txs.CoinBase.CoinBase._validate_extended') as m_validate_extended: m_validate_extended.return_value = False result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) diff --git a/tests/core/txs/test_CoinBase.py b/tests/core/txs/test_CoinBase.py index 6f54b8069..26e314a2a 100644 --- a/tests/core/txs/test_CoinBase.py +++ b/tests/core/txs/test_CoinBase.py @@ -86,16 +86,35 @@ def test_validate_extended(self, m_logger): tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number) tx._data.master_addr = self.alice.address - result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) + addresses_state = { + config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address), + self.alice.address: OptimizedAddressState.get_default(self.alice.address), + } + addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000 + + state_container = StateContainer(addresses_state=addresses_state, + tokens=Indexer(b'token', None), + slaves=Indexer(b'slave', None), + lattice_pk=Indexer(b'lattice_pk', None), + multi_sig_spend_txs=dict(), + votes_stats=dict(), + block_number=self.mock_blockheader.block_number, + total_coin_supply=100, + current_dev_config=config.dev, + write_access=True, + my_db=self.state._db, + batch=None) + + result = tx._validate_extended(state_container) self.assertFalse(result) tx._data.master_addr = config.dev.coinbase_address with patch('qrl.core.txs.CoinBase.CoinBase.addr_to', new_callable=PropertyMock) as m_addr_to: m_addr_to.return_value = b'Fake Address' - result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) + result = tx._validate_extended(state_container) self.assertFalse(result) - result = tx.validate_extended(self.mock_blockheader.block_number, config.dev) + result = tx._validate_extended(state_container) self.assertTrue(result) def test_apply_coinbase_txn(self, m_logger): diff --git a/tests/core/txs/test_MessageTransaction.py b/tests/core/txs/test_MessageTransaction.py index d55d19622..a82dd1207 100644 --- a/tests/core/txs/test_MessageTransaction.py +++ b/tests/core/txs/test_MessageTransaction.py @@ -99,7 +99,7 @@ def test_validate_message_length_zero(self, m_logger): @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) def test_validate_extended(self, m_validate_slave, m_logger): """ - Message.validate_extended checks for: + Message._validate_extended checks for: 1. valid master/slave 2. negative fee, negative total token amounts transferred 3. addr_from has enough funds for the fee @@ -144,11 +144,6 @@ def test_validate_extended(self, m_validate_slave, m_logger): self.assertFalse(result) m_addr_from_state.balance = 100 - # addr_from_pk has used this OTS key before - # m_addr_from_pk_state.ots_key_reuse.return_value = True - # result = tx.validate_extended(m_addr_from_state, 0) - # self.assertFalse(result) - self.params["message_hash"] = b'T' * 81 # Validation should fail, as we have entered a message of more than 80 lengths diff --git a/tests/core/txs/test_SlaveTransaction.py b/tests/core/txs/test_SlaveTransaction.py index 997a3208a..e8a789745 100644 --- a/tests/core/txs/test_SlaveTransaction.py +++ b/tests/core/txs/test_SlaveTransaction.py @@ -58,7 +58,7 @@ def test_validate_custom(self, m_logger): @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) def test_validate_extended(self, m_validate_slave, m_logger): """ - SlaveTransaction.validate_extended checks for: + SlaveTransaction._validate_extended checks for: 1. valid master/slave 2. negative fee, 3. addr_from has enough funds for the fee diff --git a/tests/core/txs/test_TokenTransaction.py b/tests/core/txs/test_TokenTransaction.py index c17b95498..978261bdf 100644 --- a/tests/core/txs/test_TokenTransaction.py +++ b/tests/core/txs/test_TokenTransaction.py @@ -175,58 +175,10 @@ def test_validate_tx4(self, m_logger): with self.assertRaises(ValueError): tx.validate_or_raise() - # def test_validate_custom(self, m_logger): - # # Token symbol too long - # with self.assertRaises(ValueError): - # tx = self.make_tx(symbol=b'QRLSQRLSQRL') - # tx.sign(self.alice) - # - # # Token name too long - # with self.assertRaises(ValueError): - # tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum') - # tx.sign(self.alice) - # - # # Token symbol missing - # with self.assertRaises(ValueError): - # tx = self.make_tx(symbol=b'') - # tx.sign(self.alice) - # - # # Token name missing - # with self.assertRaises(ValueError): - # tx = self.make_tx(name=b'') - # tx.sign(self.alice) - # - # # Empty initial_balances - # with self.assertRaises(ValueError): - # tx = self.make_tx(initial_balances=[]) - # tx.sign(self.alice) - # - # # Invalid initial balances... 0! - # with self.assertRaises(ValueError): - # initial_balances_0_0 = [qrl_pb2.AddressAmount(address=self.alice.address, amount=0), - # qrl_pb2.AddressAmount(address=self.bob.address, amount=0)] - # tx = self.make_tx(initial_balances=initial_balances_0_0) - # tx.sign(self.alice) - # - # # Fee is -1 - # with patch('qrl.core.txs.TokenTransaction.TokenTransaction.fee', new_callable=PropertyMock) as m_fee: - # m_fee.return_value = -1 - # with self.assertRaises(ValueError): - # tx = self.make_tx() - # tx.sign(self.alice) - # - # # Invalid initial balances... -1! - # # tx = self.make_tx() - # # tx.sign(self.alice) - # # with patch('qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances', new_callable=PropertyMock) as m_i_balances: - # # m_i_balances.return_value = [-1, -1] - # # with self.assertRaises(ValueError): - # # tx.validate_or_raise() - @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) def test_validate_extended(self, m_validate_slave, m_logger): """ - TokenTransaction.validate_extended checks for: + TokenTransaction._validate_extended checks for: 1. valid master/slave 2. from address is valid 3. owner address is valid diff --git a/tests/core/txs/test_TransferTokenTransaction.py b/tests/core/txs/test_TransferTokenTransaction.py index 356a457c8..619cb4f6c 100644 --- a/tests/core/txs/test_TransferTokenTransaction.py +++ b/tests/core/txs/test_TransferTokenTransaction.py @@ -172,7 +172,7 @@ def test_state_validate_tx_custom(self, m_logger): @patch('qrl.core.txs.Transaction.Transaction.validate_slave', return_value=True) def test_validate_extended(self, m_validate_slave, m_logger): """ - TransferTokenTransaction.validate_extended checks for: + TransferTokenTransaction._validate_extended checks for: 1. valid master/slave 2. negative fee, negative total token amounts transferred 3. addr_from has enough funds for the fee From f721e943c4aba68e3d1df6423cb8ad7d47d740d3 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 5 Feb 2020 21:05:59 +0530 Subject: [PATCH 04/67] Excluded Unit Tests from Codacy Duplication Analysis --- .codacy.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.codacy.yml b/.codacy.yml index f92bdbec5..f32604cd7 100644 --- a/.codacy.yml +++ b/.codacy.yml @@ -10,3 +10,7 @@ exclude_paths: - 'src/qrl/_version.py' - 'src/qrl/measure.py' - 'start_qrl.py' +engines: + duplication: + exclude_paths: + - 'tests/**' \ No newline at end of file From 5b4ce9d6c781e45990b41d23c32969d41e646bc6 Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 6 Feb 2020 21:03:34 +0530 Subject: [PATCH 05/67] Added plyvel into requirements.txt --- requirements.txt | 4 ++-- setup.cfg | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0fe213021..6f15dfae5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Fixing sphinx version due to https://github.com/sphinx-doc/sphinx/issues/3976 setuptools==39.0.1 -leveldb==0.20 +plyvel==1.2.0 ntplib==0.3.3 Twisted==19.2.1 colorlog==3.1.0 @@ -20,4 +20,4 @@ Flask==0.12.3 json-rpc==1.10.8 cryptography==2.3 mock==2.0.0 -daemonize==2.4.7 \ No newline at end of file +daemonize==2.4.7 diff --git a/setup.cfg b/setup.cfg index b50bdb1fb..0b97c5d75 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,7 +26,7 @@ package_dir = # install_requires = numpy; scipy install_requires = setuptools==39.0.1 - leveldb==0.20 + plyvel==1.2.0 ntplib==0.3.3 Twisted==19.2.1 colorlog==3.1.0 From b0dd3a8bfb2df6b233d856c8b1cb6c6512f09ccb Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 6 Feb 2020 21:47:48 +0530 Subject: [PATCH 06/67] Fixed Unit Tests --- src/qrl/core/formulas.py | 24 +++++++++------- tests/core/p2p/test_p2pTxManagement.py | 4 +-- tests/core/p2p/test_p2pfactory.py | 39 +++++++++++++------------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/qrl/core/formulas.py b/src/qrl/core/formulas.py index e9aebdd8a..882343e57 100644 --- a/src/qrl/core/formulas.py +++ b/src/qrl/core/formulas.py @@ -21,7 +21,9 @@ def get_total_blocks(dev_config: DevConfig): def calc_coeff(dev_config: DevConfig) -> Decimal: """ block reward calculation. Decay curve: 200 years - >>> calc_coeff() + + >>> from qrl.core import config + >>> calc_coeff(config.dev) Decimal('1.664087503734056374552843909E-7') """ return dev_config.coin_remaining_at_genesis.ln() / get_total_blocks(dev_config) @@ -35,13 +37,14 @@ def remaining_emission(block_n, dev_config: DevConfig) -> Decimal: :param block_n: :return: - >>> remaining_emission(0) + >>> from qrl.core import config + >>> remaining_emission(0, config.dev) Decimal('40000000000000000') - >>> remaining_emission(1) + >>> remaining_emission(1, config.dev) Decimal('39999993343650538') - >>> remaining_emission(2) + >>> remaining_emission(2, config.dev) Decimal('39999986687302185') - >>> remaining_emission(100) + >>> remaining_emission(100, config.dev) Decimal('39999334370536850') """ coeff = calc_coeff(dev_config) @@ -53,15 +56,16 @@ def block_reward(block_number: int, dev_config: DevConfig) -> Decimal: """ :return: Block reward in shors for block number - >>> block_reward(1) + >>> from qrl.core import config + >>> block_reward(1, config.dev) Decimal('6656349462') - >>> block_reward(2) + >>> block_reward(2, config.dev) Decimal('6656348353') - >>> block_reward(3) + >>> block_reward(3, config.dev) Decimal('6656347246') >>> N = 40 - >>> tmp_sum = sum(block_reward(b) for b in range(1, N)) - >>> tmp_est = remaining_emission(0) - remaining_emission(N-1) + >>> tmp_sum = sum(block_reward(b, config.dev) for b in range(1, N)) + >>> tmp_est = remaining_emission(0, config.dev) - remaining_emission(N-1, config.dev) >>> tmp_est - tmp_sum Decimal('0') """ diff --git a/tests/core/p2p/test_p2pTxManagement.py b/tests/core/p2p/test_p2pTxManagement.py index c6e28d729..454b8ba3b 100644 --- a/tests/core/p2p/test_p2pTxManagement.py +++ b/tests/core/p2p/test_p2pTxManagement.py @@ -39,13 +39,13 @@ def test_count_registrations(self): self.tx_manager.new_channel(channel) channel.register.assert_called() - self.assertEquals(8, channel.register.call_count) + self.assertEquals(11, channel.register.call_count) def test_observable(self): channel = Observable(None) self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) - self.assertEquals(8, channel.observers_count) + self.assertEquals(11, channel.observers_count) def test_notification_no_observer(self): source = Mock() diff --git a/tests/core/p2p/test_p2pfactory.py b/tests/core/p2p/test_p2pfactory.py index 51b616f8b..3944939c3 100644 --- a/tests/core/p2p/test_p2pfactory.py +++ b/tests/core/p2p/test_p2pfactory.py @@ -142,19 +142,19 @@ def test_is_block_present(self, m_reactor, m_logger): is_block_present() returns True if block's headerhash is in our blockchain, or if it is known and will be processed in the future (POW.future_blocks, OrderedDict()) """ - self.factory.pow.future_blocks = OrderedDict() - self.factory._chain_manager._state.get_block.return_value = False - result = self.factory.is_block_present(b'1234') - self.assertFalse(result) + with patch.object(Block, 'get_block', return_value=False): + self.factory.pow.future_blocks = OrderedDict() + result = self.factory.is_block_present(b'1234') + self.assertFalse(result) - self.factory.pow.future_blocks = OrderedDict({b'1234': 'Some data'}) - result = self.factory.is_block_present(b'1234') - self.assertTrue(result) + self.factory.pow.future_blocks = OrderedDict({b'1234': 'Some data'}) + result = self.factory.is_block_present(b'1234') + self.assertTrue(result) - self.factory.pow.future_blocks = OrderedDict() - self.factory._chain_manager._state.get_block.return_value = True - result = self.factory.is_block_present(b'1234') - self.assertTrue(result) + with patch.object(Block, 'get_block', return_value=True): + self.factory.pow.future_blocks = OrderedDict() + result = self.factory.is_block_present(b'1234') + self.assertTrue(result) def test_connect_peer_already_connected(self, m_reactor, m_logger): """ @@ -591,23 +591,22 @@ def test_peer_fetch_block_we_already_have_the_block(self, m_reactor, m_logger): 2. we've reached the end of the peer's NodeHeaderHash. Then it will ask the peer for the next block after that. """ - self.factory._chain_manager._state.get_block.return_value = Block() + with patch.object(Block, 'get_block', return_value=Block()): + self.factory.peer_fetch_block() - self.factory.peer_fetch_block() - - self.assertEqual(self.factory._chain_manager._state.get_block.call_count, 3) - self.channel_1.send_fetch_block.assert_called_once_with(3) + self.assertEqual(Block.get_block.call_count, 3) + self.channel_1.send_fetch_block.assert_called_once_with(3) def test_peer_fetch_block_we_are_synced(self, m_reactor, m_logger): """ If is_syncing_finished() is True, then let's not ask for more blocks. """ - self.factory._chain_manager._state.get_block.return_value = Block() - self.factory.is_syncing_finished.return_value = True + with patch.object(Block, 'get_block', return_value=Block()): + self.factory.is_syncing_finished.return_value = True - self.factory.peer_fetch_block() + self.factory.peer_fetch_block() - self.channel_1.send_fetch_block.assert_not_called() + self.channel_1.send_fetch_block.assert_not_called() def test_peer_fetch_block_block_not_found_and_retry(self, m_reactor, m_logger): """ From b94c46f7f12d2e87cfca058b859e02060b2888e0 Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 6 Feb 2020 22:42:18 +0530 Subject: [PATCH 07/67] Fixed Unit Test for cli --- tests/tools/test_cli.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/tools/test_cli.py b/tests/tools/test_cli.py index 4e99f6ea1..6549878b1 100644 --- a/tests/tools/test_cli.py +++ b/tests/tools/test_cli.py @@ -444,6 +444,7 @@ def test_tx_transfer(self, mock_stub): "--master=", "--dsts={}".format(qaddr_1), "--amounts=1", + "--message_data=", "--fee=0", "--ots_key_index=0" ]) @@ -458,6 +459,7 @@ def test_tx_transfer(self, mock_stub): "--master=", "--dsts={}".format(qaddr_1), "--amounts=1", + "--message_data=", "--fee=0", "--ots_key_index=0" ]) @@ -471,6 +473,7 @@ def test_tx_transfer(self, mock_stub): "--master={}".format(qaddr_2), "--dsts={}".format(qaddr_1), "--amounts=1", + "--message_data=", "--fee=0", "--ots_key_index=0" ]) @@ -486,6 +489,7 @@ def test_tx_transfer(self, mock_stub): "--master=", "--dsts={}".format(" ".join(dsts)), "--amounts={}".format(" ".join(amounts)), + "--message_data=", "--fee=0", "--ots_key_index=0" ]) @@ -516,7 +520,7 @@ def test_tx_transfer_encrypted_wallet(self, mock_stub): # Simplest use case self.runner.invoke(qrl_cli, ["wallet_encrypt"], input='password\npassword\n') result = self.runner.invoke(qrl_cli, ["tx_transfer", "--src=0", "--master=", "--dsts={}".format(qaddr_1), - "--amounts=1", "--fee=0", "--ots_key_index=0"], + "--amounts=1", "--message_data=", "--fee=0", "--ots_key_index=0"], input='password\n') self.assertEqual(result.exit_code, 0) self.assertIn('a fake pushTransactionResp', result.output.strip()) @@ -549,6 +553,7 @@ def test_tx_transfer_invalid_input(self, mock_stub): "--master=", "--dsts={}".format(qaddr_1), "--amounts=1", + "--message_data=", "--fee=0", "--ots_key_index=16"], input='16') self.assertEqual(result.exit_code, 1) @@ -563,6 +568,7 @@ def test_tx_transfer_invalid_input(self, mock_stub): "--master=", "--dsts={}".format(" ".join(dsts)), "--amounts={}".format(" ".join(amounts)), + "--message_data=", "--fee=0", "--ots_key_index=0" ]) From 449194cdc0f3a724b0c510512f3e1fcd5cf1d7b5 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 16:17:31 +0530 Subject: [PATCH 08/67] Fix: flake8 tests --- src/qrl/cli.py | 1 - src/qrl/core/ChainManager.py | 1 - src/qrl/core/OptimizedAddressState.py | 1 - src/qrl/core/State.py | 4 +- src/qrl/core/StateMigration.py | 2 +- src/qrl/core/misc/db.py | 2 +- src/qrl/core/qrlnode.py | 12 +- src/qrl/crypto/QRandomX.py | 1 - src/qrl/services/WalletAPIService.py | 4 +- tests/core/test_BlockMetadata.py | 1 - tests/core/test_ChainManager.py | 566 +++++++++--------- tests/core/test_Miner.py | 1 - tests/core/test_PaginatedData.py | 14 +- tests/core/test_block.py | 27 +- tests/core/txs/multisig/test_MultiSigVote.py | 1 - tests/core/txs/test_SimpleTransaction.py | 2 +- ...st_TransferTokenTransactionStateChanges.py | 2 +- tests/core/txs/testdata.py | 4 +- tests/misc/helper.py | 2 +- 19 files changed, 318 insertions(+), 330 deletions(-) diff --git a/src/qrl/cli.py b/src/qrl/cli.py index b1e875034..df368b568 100755 --- a/src/qrl/cli.py +++ b/src/qrl/cli.py @@ -1037,4 +1037,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index cad3c95d3..d859384db 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -857,7 +857,6 @@ def apply_state_changes(self, block, dev_config: DevConfig, batch) -> bool: return False # Processing Rest of the Transaction - len_transactions = len(block.transactions) for proto_tx in block.transactions: tx = Transaction.from_pbdata(proto_tx) if not self.update_state_container(tx, state_container): diff --git a/src/qrl/core/OptimizedAddressState.py b/src/qrl/core/OptimizedAddressState.py index 398932d90..05c102111 100644 --- a/src/qrl/core/OptimizedAddressState.py +++ b/src/qrl/core/OptimizedAddressState.py @@ -253,4 +253,3 @@ def get_optimized_address_state(state: State, address: bytes): return address_state except KeyError: return OptimizedAddressState.get_default(address) - diff --git a/src/qrl/core/State.py b/src/qrl/core/State.py index 9b2aed311..aea30e12c 100644 --- a/src/qrl/core/State.py +++ b/src/qrl/core/State.py @@ -291,7 +291,7 @@ def put_slaves_hash(self, slaves: dict, addresses_state: dict, batch=None): for address in slave_hashes: full_hashes = slave_hashes[address] start = 0 - hashes = full_hashes[start:start+config.dev.data_per_page] + hashes = full_hashes[start:start + config.dev.data_per_page] address_state = addresses_state[address] while hashes: address_state.update_slaves_count(len(hashes)) @@ -339,7 +339,7 @@ def put_tokens_hash(self, tokens: dict, addresses_state: dict, batch=None): for address in token_hashes: full_hashes = token_hashes[address] start = 0 - hashes = full_hashes[start:start+config.dev.data_per_page] + hashes = full_hashes[start:start + config.dev.data_per_page] address_state = addresses_state[address] while hashes: self.put_token_transaction_hashes(address, address_state.tokens_count, hashes, batch) diff --git a/src/qrl/core/StateMigration.py b/src/qrl/core/StateMigration.py index feaaac318..82532f4ee 100644 --- a/src/qrl/core/StateMigration.py +++ b/src/qrl/core/StateMigration.py @@ -17,7 +17,7 @@ def state_migration_step_1(self, state: State) -> bool: :return: """ if state.is_older_state_version(): - db_dir_v1 = os.path.join(config.user.data_dir, config.dev.db_name+"2") + db_dir_v1 = os.path.join(config.user.data_dir, config.dev.db_name + '2') self._tmp_state = State(state._db) state._db = db.DB(db_dir_v1) return True diff --git a/src/qrl/core/misc/db.py b/src/qrl/core/misc/db.py index aa8376479..38e260500 100644 --- a/src/qrl/core/misc/db.py +++ b/src/qrl/core/misc/db.py @@ -37,7 +37,7 @@ def close(self): def open(self, db_dir=None): if db_dir: self.db_dir = db_dir - self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5*1024) + self.db = plyvel.DB(self.db_dir, max_open_files=1000, lru_cache_size=5 * 1024) def RangeIter(self, key_obj_start, key_obj_end): if not isinstance(key_obj_start, bytes): diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 5204549d8..63cad4279 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -393,7 +393,11 @@ def get_multi_sig_address_state(self, address: bytes) -> MultiSigAddressState: return multi_sig_address_state - def get_ots(self, address: bytes, page_from: int, page_count: int, unused_ots_index_from: int) -> (list, Optional[int], bool): + def get_ots(self, + address: bytes, + page_from: int, + page_count: int, + unused_ots_index_from: int) -> (list, Optional[int], bool): bitfields = list() for page in range(page_from, page_from + page_count): bitfield = self._chain_manager.get_bitfield(address, page) @@ -418,7 +422,7 @@ def _load_transaction_hashes(self, address: bytes, item_per_page: int, page_numb transaction_hashes = self._chain_manager.get_transaction_hashes(address, start_item_index) actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page - transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + transaction_hashes = transaction_hashes[start_item_index - actual_start_item_index:] while actual_start_item_index < end_item_index: actual_start_item_index += config.dev.data_per_page transaction_hashes.extend(self._chain_manager.get_transaction_hashes(address, @@ -462,7 +466,7 @@ def _load_token_transaction_hashes(self, address: bytes, item_per_page: int, pag transaction_hashes = self._chain_manager.get_token_transaction_hashes(address, start_item_index) actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page - token_transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + token_transaction_hashes = transaction_hashes[start_item_index - actual_start_item_index:] while actual_start_item_index < end_item_index: actual_start_item_index += config.dev.data_per_page token_transaction_hashes.extend(self._chain_manager.get_token_transaction_hashes(address, @@ -480,7 +484,7 @@ def _load_slave_transaction_hashes(self, address: bytes, item_per_page: int, pag transaction_hashes = self._chain_manager.get_slave_transaction_hashes(address, start_item_index) actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page - token_transaction_hashes = transaction_hashes[start_item_index-actual_start_item_index:] + token_transaction_hashes = transaction_hashes[start_item_index - actual_start_item_index:] while actual_start_item_index < end_item_index: actual_start_item_index += config.dev.data_per_page token_transaction_hashes.extend(self._chain_manager.get_slave_transaction_hashes(address, diff --git a/src/qrl/crypto/QRandomX.py b/src/qrl/crypto/QRandomX.py index c0451ae62..0eefcd768 100644 --- a/src/qrl/crypto/QRandomX.py +++ b/src/qrl/crypto/QRandomX.py @@ -19,4 +19,3 @@ def get_seed_height(self, block_number): def hash(self, block_height, seed_height, seed_hash, blob): with self.lock: return bytes(self._qrx.hash(block_height, seed_height, seed_hash, blob, 0)) - diff --git a/src/qrl/services/WalletAPIService.py b/src/qrl/services/WalletAPIService.py index a002588f1..a036f55cc 100644 --- a/src/qrl/services/WalletAPIService.py +++ b/src/qrl/services/WalletAPIService.py @@ -383,9 +383,7 @@ def GetTotalBalance(self, request: qrlwallet_pb2.TotalBalanceReq, context) -> qr @GrpcExceptionWrapper(qrlwallet_pb2.OTSResp) def GetOTS(self, request: qrlwallet_pb2.OTSReq, context) -> qrlwallet_pb2.OTSResp: try: - ots_bitfield_by_page, \ - next_unused_ots_index, \ - unused_ots_index_found = self._walletd.get_ots(request.address) + ots_bitfield_by_page, next_unused_ots_index, unused_ots_index_found = self._walletd.get_ots(request.address) resp = qrlwallet_pb2.OTSResp(ots_bitfield_by_page=ots_bitfield_by_page, next_unused_ots_index=next_unused_ots_index, unused_ots_index_found=unused_ots_index_found) diff --git a/tests/core/test_BlockMetadata.py b/tests/core/test_BlockMetadata.py index e376d1232..71af8eb6e 100644 --- a/tests/core/test_BlockMetadata.py +++ b/tests/core/test_BlockMetadata.py @@ -47,4 +47,3 @@ def test_get_block_metadata(self): b'"cumulativeDifficulty": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n}' self.assertEqual(tmp_json, expected_json) - diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 3b4203370..15d42b858 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -10,7 +10,6 @@ from qrl.generated import qrlstateinfo_pb2 from qrl.core import config -from qrl.core.misc import logger from qrl.crypto.xmss import XMSS from qrl.crypto.QRandomX import QRandomX from qrl.core.OptimizedAddressState import OptimizedAddressState @@ -29,18 +28,15 @@ from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend from qrl.core.txs.multisig.MultiSigVote import MultiSigVote from tests.misc.helper import get_alice_xmss, get_bob_xmss, set_default_balance_size, set_hard_fork_block_number, \ - set_qrl_dir, replacement_getTime, get_some_address, gen_blocks, get_genesis_with_only_coin_base_txn + set_qrl_dir, replacement_getTime, get_some_address, gen_blocks -# logger.initialize_default() -from qrl.core.misc.set_logger import set_logger_default -#set_logger_default() alice = get_alice_xmss() bob = get_bob_xmss() def ask_difficulty_tracker(difficulty: str, dev_config: config.DevConfig): dt = DifficultyTracker() - tmp_difficulty = StringToUInt256('2') + tmp_difficulty = StringToUInt256(difficulty) tmp_target = dt.get_target(tmp_difficulty, dev_config) return tmp_difficulty, tmp_target @@ -493,13 +489,13 @@ def test_add_block2(self, time_mock): self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward - + block_2.block_reward + block_2.fee_reward - + block_3.block_reward + block_3.fee_reward - + block_4.block_reward + block_4.fee_reward - + block_5.block_reward + block_5.fee_reward - + 5) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward + + block_5.block_reward + block_5.fee_reward + + 5) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + 10) self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta) - 15) self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) @@ -701,11 +697,11 @@ def test_add_block3(self, time_mock): self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward - + block_2.block_reward + block_2.fee_reward - + block_3.block_reward + block_3.fee_reward - + block_4.block_reward + block_4.fee_reward) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta)) self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) @@ -757,8 +753,8 @@ def test_add_block4(self, time_mock): 100 * int(config.dev.shor_per_quanta) - 5) self.assertEqual(alice_addr_state.lattice_pk_count(), 1) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + 5) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + 5) lattice_pk2 = LatticeTransaction.create(pk1=b'alice_pk11', pk2=b'alice_pk12', @@ -977,9 +973,9 @@ def test_add_block6(self, time_mock): self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward - + multi_sig_spend.amounts[1]) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + multi_sig_spend.amounts[1]) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend.amounts[0]) self.assertEqual(multi_sig_address_state.balance, @@ -1193,8 +1189,8 @@ def test_add_block7(self, time_mock): self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) self.assertEqual(multi_sig_address_state.balance, @@ -1634,22 +1630,22 @@ def test_add_block10(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction.fee - - transfer_transaction.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction.fee - + transfer_transaction.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction.total_amount - + multi_sig_spend1.total_amount) seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) block_2 = Block.create(dev_config=config.dev, @@ -1680,24 +1676,24 @@ def test_add_block10(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction.fee - - transfer_transaction.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction.fee - + transfer_transaction.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction.total_amount - + multi_sig_spend1.total_amount) # Check Txns in State vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) @@ -1969,22 +1965,22 @@ def test_add_block11(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount - + multi_sig_spend1.total_amount) seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) block_2 = Block.create(dev_config=config.dev, @@ -2015,24 +2011,24 @@ def test_add_block11(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount - + multi_sig_spend1.total_amount) transfer_transaction2 = TransferTransaction.create(addrs_to=[multi_sig_address], amounts=[40], @@ -2072,29 +2068,29 @@ def test_add_block11(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount) multi_sig_vote5 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, unvote=True, @@ -2132,32 +2128,32 @@ def test_add_block11(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount - - multi_sig_vote5.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount - + multi_sig_vote5.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward - + block_4.fee_reward - + block_4.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount) multi_sig_vote6 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, unvote=False, @@ -2195,38 +2191,38 @@ def test_add_block11(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount - - multi_sig_vote5.fee - - multi_sig_vote6.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount - + multi_sig_vote5.fee - + multi_sig_vote6.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + multi_sig_spend2.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward - + block_4.fee_reward - + block_4.block_reward - + block_5.fee_reward - + block_5.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + multi_sig_spend2.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward + + block_5.fee_reward + + block_5.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0] - + multi_sig_spend2.amounts[1]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0] + + multi_sig_spend2.amounts[1]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount - - multi_sig_spend2.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount - + multi_sig_spend2.total_amount) # Check Txns in State vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) @@ -2639,14 +2635,14 @@ def test_add_block13(self, time_mock): self.assertEqual(bob_addr_state.balance, 100 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward - - slave_txn1.fee - - transfer_txn.fee - - transfer_txn.total_amount) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward - + slave_txn1.fee - + transfer_txn.fee - + transfer_txn.total_amount) self.assertEqual(random_addr_state1.balance, - 100 * int(config.dev.shor_per_quanta) - + transfer_txn.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + transfer_txn.amounts[0]) self.assertEqual(random_addr_state2.balance, 100 * int(config.dev.shor_per_quanta)) slave_metadata = self.chain_manager.get_slave_pk_access_type(alice_addr_state.address, random_xmss1.pk) @@ -2781,7 +2777,7 @@ def test_add_block14(self, time_mock): @set_default_balance_size() @patch('qrl.core.misc.ntp.getTime') - def test_add_block13(self, time_mock): + def test_add_block15(self, time_mock): """ Features Tested - Behavior of Slave txn when duplicate slave transaction are added into a single block @@ -2803,7 +2799,6 @@ def test_add_block13(self, time_mock): random_xmss1 = XMSS.from_extended_seed(hstr2bin(extended_seed1)) random_xmss2 = XMSS.from_extended_seed(hstr2bin(extended_seed2)) alice_xmss = get_alice_xmss(4) - bob_xmss = get_bob_xmss(4) slave_txn1 = SlaveTransaction.create(slave_pks=[random_xmss1.pk, random_xmss2.pk], access_types=[0, 0], fee=5, @@ -3023,13 +3018,13 @@ def test_rollback(self, time_mock): self.assertEqual(bob_addr_state.balance, 59 * int(config.dev.shor_per_quanta)) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + block_1.block_reward + block_1.fee_reward - + block_2.block_reward + block_2.fee_reward - + block_3.block_reward + block_3.fee_reward - + block_4.block_reward + block_4.fee_reward - + block_5.block_reward + block_5.fee_reward - + 5) + 100 * int(config.dev.shor_per_quanta) + + block_1.block_reward + block_1.fee_reward + + block_2.block_reward + block_2.fee_reward + + block_3.block_reward + block_3.fee_reward + + block_4.block_reward + block_4.fee_reward + + block_5.block_reward + block_5.fee_reward + + 5) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + 10) self.assertEqual(multi_sig_address_state.balance, 40 * int(config.dev.shor_per_quanta) - 15) self.assertEqual(multi_sig_address_state.transaction_hash_count(), 3) @@ -3177,22 +3172,22 @@ def test_rollback2(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction.fee - - transfer_transaction.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction.fee - + transfer_transaction.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction.total_amount - + multi_sig_spend1.total_amount) seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) block_2 = Block.create(dev_config=config.dev, @@ -3223,24 +3218,24 @@ def test_rollback2(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction.fee - - transfer_transaction.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction.fee - + transfer_transaction.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction.total_amount - + multi_sig_spend1.total_amount) # Check Txns in State vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) @@ -3320,25 +3315,23 @@ def test_rollback2(self, time_mock): bob_addr_state = self.chain_manager.get_optimized_address_state(bob_xmss.address) alice_addr_state = self.chain_manager.get_optimized_address_state(alice_xmss.address) random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) - multi_sig_address_state = MultiSigAddressState.get_multi_sig_address_state_by_address(self.state._db, - multi_sig_address) self.assertEqual(bob_addr_state.nonce, 2) self.assertEqual(alice_addr_state.nonce, 4) self.assertEqual(random_addr_state.nonce, 0) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction.total_amount - - transfer_transaction.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction.total_amount - + transfer_transaction.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) # Check OTS key usage p = PaginatedBitfield(False, self.state._db) @@ -3504,22 +3497,22 @@ def test_roll_back3(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount - + multi_sig_spend1.total_amount) seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(2)) block_2 = Block.create(dev_config=config.dev, @@ -3550,24 +3543,24 @@ def test_roll_back3(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount - + multi_sig_spend1.total_amount) transfer_transaction2 = TransferTransaction.create(addrs_to=[multi_sig_address], amounts=[40], @@ -3607,29 +3600,29 @@ def test_roll_back3(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount) multi_sig_vote5 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, unvote=True, @@ -3667,32 +3660,32 @@ def test_roll_back3(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount - - multi_sig_vote5.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount - + multi_sig_vote5.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward - + block_4.fee_reward - + block_4.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount) multi_sig_vote6 = MultiSigVote.create(shared_key=multi_sig_spend2.txhash, unvote=False, @@ -3730,27 +3723,27 @@ def test_roll_back3(self, time_mock): multi_sig_address) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount - - multi_sig_vote5.fee - - multi_sig_vote6.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount - + multi_sig_vote5.fee - + multi_sig_vote6.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + multi_sig_spend2.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward - + block_4.fee_reward - + block_4.block_reward - + block_5.fee_reward - + block_5.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + multi_sig_spend2.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward + + block_5.fee_reward + + block_5.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0] @@ -3870,32 +3863,32 @@ def test_roll_back3(self, time_mock): self.assertEqual(random_addr_state.nonce, 0) self.assertEqual(bob_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - - transfer_transaction1.fee - - transfer_transaction1.total_amount - - transfer_transaction2.fee - - transfer_transaction2.total_amount - - multi_sig_vote5.fee) + 100 * int(config.dev.shor_per_quanta) - + transfer_transaction1.fee - + transfer_transaction1.total_amount - + transfer_transaction2.fee - + transfer_transaction2.total_amount - + multi_sig_vote5.fee) self.assertEqual(alice_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[1] - + block_1.fee_reward - + block_1.block_reward - + block_2.fee_reward - + block_2.block_reward - + block_3.fee_reward - + block_3.block_reward - + block_4.fee_reward - + block_4.block_reward) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[1] + + block_1.fee_reward + + block_1.block_reward + + block_2.fee_reward + + block_2.block_reward + + block_3.fee_reward + + block_3.block_reward + + block_4.fee_reward + + block_4.block_reward) self.assertEqual(random_addr_state.balance, 100 * int(config.dev.shor_per_quanta) + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount) # Check OTS key usage p = PaginatedBitfield(False, self.state._db) @@ -3963,11 +3956,6 @@ def test_fork_recovery(self): self.chain_manager.add_block(block_4_alt) self.assertEqual(self.chain_manager.last_block, block_4_alt) - def test_new_state_container(self): - with set_qrl_dir('no_data'): - with State() as state: - pass - @set_default_balance_size() @set_hard_fork_block_number() @patch('qrl.core.misc.ntp.getTime') diff --git a/tests/core/test_Miner.py b/tests/core/test_Miner.py index 4e610dcfd..ac1c55d89 100644 --- a/tests/core/test_Miner.py +++ b/tests/core/test_Miner.py @@ -273,7 +273,6 @@ def setUp(self): self.parent_difficulty = StringToUInt256('0') # tuple (0,0,0,0,0...) length 32 self.m_pre_block_logic = Mock(spec=POW.pre_block_logic, name='hello') - m_add_unprocessed_txn_fn = create_autospec(P2PFactory.add_unprocessed_txn) mining_thread_count = 1 self.miner = Miner(self.chain_manager, diff --git a/tests/core/test_PaginatedData.py b/tests/core/test_PaginatedData.py index f7307b19d..fff9737cc 100644 --- a/tests/core/test_PaginatedData.py +++ b/tests/core/test_PaginatedData.py @@ -57,14 +57,14 @@ def test_put_paginated_data(self, mock_dev_config): alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) for i in range(0, 10): - p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + p.insert(alice_address_state, b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) self.assertEqual(alice_address_state.get_counter_by_name(p.name), i + 1) p.put_paginated_data(None) self.assertEqual(alice_address_state.get_counter_by_name(p.name), 10) for i in range(10, 25): - p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + p.insert(alice_address_state, b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) self.assertEqual(alice_address_state.get_counter_by_name(p.name), i + 1) p.put_paginated_data(None) @@ -81,15 +81,15 @@ def test_put_paginated_data(self, mock_dev_config): self.assertEqual(len(pages_data[0]), 10) for i in range(0, 10): - self.assertEqual(pages_data[0][i], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + self.assertEqual(pages_data[0][i], b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) self.assertEqual(len(pages_data[1]), 10) for i in range(10, 20): - self.assertEqual(pages_data[1][i - 10], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + self.assertEqual(pages_data[1][i - 10], b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) self.assertEqual(len(pages_data[2]), 5) for i in range(20, 25): - self.assertEqual(pages_data[2][i - 20], b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + self.assertEqual(pages_data[2][i - 20], b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) @patch('qrl.core.config.DevConfig.data_per_page', new_callable=PropertyMock, return_value=10) def test_revert_paginated_data(self, mock_dev_config): @@ -99,7 +99,7 @@ def test_revert_paginated_data(self, mock_dev_config): alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) for i in range(0, 25): - p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + p.insert(alice_address_state, b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) p.put_paginated_data(None) full_hash = [] @@ -135,7 +135,7 @@ def test_revert_paginated_data2(self, mock_dev_config): alice_address_state = OptimizedAddressState.get_default(address=self.alice.address) for i in range(0, 25): - p.insert(alice_address_state, b'p_tx_hash_'+i.to_bytes(8, byteorder='big', signed=False)) + p.insert(alice_address_state, b'p_tx_hash_' + i.to_bytes(8, byteorder='big', signed=False)) p.put_paginated_data(None) diff --git a/tests/core/test_block.py b/tests/core/test_block.py index 67fd541f1..fe2c6bf5f 100644 --- a/tests/core/test_block.py +++ b/tests/core/test_block.py @@ -267,7 +267,8 @@ def test_all_ok(self, m_TransferTransaction_validate, m_TransferTransaction_vali result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertTrue(result) - def test_extra_coinbase_tx(self, m_TransferTransaction_validate, + def test_extra_coinbase_tx(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): @@ -284,7 +285,8 @@ def test_extra_coinbase_tx(self, m_TransferTransaction_validate, result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) - def test_bad_nonce_or_ots_reused(self, m_TransferTransaction_validate, + def test_bad_nonce_or_ots_reused(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): @@ -310,7 +312,8 @@ def test_bad_nonce_or_ots_reused(self, m_TransferTransaction_validate, result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) - def test_tx_validation_fails(self, m_TransferTransaction_validate, + def test_tx_validation_fails(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): @@ -337,7 +340,8 @@ def test_tx_validation_fails(self, m_TransferTransaction_validate, result = self.chain_manager.apply_state_changes(block, config.dev, None) self.assertFalse(result) - def test_put_block_number_mapping(self, m_TransferTransaction_validate, + def test_put_block_number_mapping(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): @@ -348,7 +352,8 @@ def test_put_block_number_mapping(self, m_TransferTransaction_validate, read_bm.SerializeToString()) self.assertIsNone(Block.get_block_by_number(self.state, 4)) - def test_get_block_number_mapping(self, m_TransferTransaction_validate, + def test_get_block_number_mapping(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): @@ -359,15 +364,17 @@ def test_get_block_number_mapping(self, m_TransferTransaction_validate, self.assertEqual(bm.SerializeToString(), read_bm.SerializeToString()) - def test_get_block_by_number(self, m_TransferTransaction_validate, - m_TransferTransaction_validate_extended, - m_TransferTransaction_apply_state_changes, - m_CoinBase_apply_state_changes): + def test_get_block_by_number(self, + m_TransferTransaction_validate, + m_TransferTransaction_validate_extended, + m_TransferTransaction_apply_state_changes, + m_CoinBase_apply_state_changes): bm = qrl_pb2.BlockNumberMapping() Block.put_block_number_mapping(self.state, 0, bm, None) self.assertIsNone(Block.get_block_by_number(self.state, 4)) - def test_last_block(self, m_TransferTransaction_validate, + def test_last_block(self, + m_TransferTransaction_validate, m_TransferTransaction_validate_extended, m_TransferTransaction_apply_state_changes, m_CoinBase_apply_state_changes): diff --git a/tests/core/txs/multisig/test_MultiSigVote.py b/tests/core/txs/multisig/test_MultiSigVote.py index 30450ba9f..960da90cf 100644 --- a/tests/core/txs/multisig/test_MultiSigVote.py +++ b/tests/core/txs/multisig/test_MultiSigVote.py @@ -62,7 +62,6 @@ def test_to_json(self): unvote=False, fee=0, xmss_pk=self.alice.pk) - tx.sign(self.alice) txjson = tx.to_json() self.assertEqual(json.loads(test_json_MultiSigVote), json.loads(txjson)) diff --git a/tests/core/txs/test_SimpleTransaction.py b/tests/core/txs/test_SimpleTransaction.py index 20c0d3ea6..b35b07d8b 100644 --- a/tests/core/txs/test_SimpleTransaction.py +++ b/tests/core/txs/test_SimpleTransaction.py @@ -529,7 +529,7 @@ def test_revert_transfer_txn(self, m_logger): state_container.paginated_bitfield.put_addresses_bitfield(None) self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, - ots_key)) + ots_key)) self.tx.apply(self.state, state_container) self.tx.revert(self.state, state_container) self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, diff --git a/tests/core/txs/test_TransferTokenTransactionStateChanges.py b/tests/core/txs/test_TransferTokenTransactionStateChanges.py index 03483ed6d..8cb7be9ea 100644 --- a/tests/core/txs/test_TransferTokenTransactionStateChanges.py +++ b/tests/core/txs/test_TransferTokenTransactionStateChanges.py @@ -291,7 +291,7 @@ def test_revert_transfer_token_txn_send_tokens_to_self(self): self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) tx.apply(self.state, state_container) tx.revert(self.state, state_container) - self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, 0)) + self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) # Unfortunately importing mock.call results in some sort of ValueError so I can't check the arguments. diff --git a/tests/core/txs/testdata.py b/tests/core/txs/testdata.py index 8e1ada452..0acd66ecc 100644 --- a/tests/core/txs/testdata.py +++ b/tests/core/txs/testdata.py @@ -92,9 +92,7 @@ "multiSigVote": { "sharedKey": "+J13jHTkcybczOMHDHqDjo97JhvUYsRx+adev5c/a4E=" }, - "publicKey": "AQMAOOpjdQafgnLMGmYBs8dsIVGUVWA9NwA2uXx3mto1ZYVOOYO9VkKYxJri5/puKNS5VNjNWTmPEiWwjWFEhUruDg==", - "signature": "AAAAAf74AYshiQcUSML+mEUhVKN1ygsXoCIkHp9B4WTgwHtUHUjy8Gw1YLz3tAGNBEixP+yNIEIQEXp7cuXbRDXaXrNFvdGlxUBQdNCdzSd24gx6/NxQHmVpnTdlhfrWwxV0h0zPkp5Ni5mb+qBH5MuTtQSD294oU9exZmEkpTuuQDND+h/5jVESUGCdf8BQMEAPorbtOrEM7whhLKwHzQ0I7mrGUgV0v4zg3XG6UfYELvLaPV2rB+tD+V0KYNA90hAIlEw7+K3fYmVzrnsvWFqeNCpvkItgwVvm79ld96FIxZxBcqVF3F0BZHpETP4/5kmw+UPbAwpdQW6dncCeTvcfKH567Cs7qZKAPiuyvR7WZhI6cNJcCL1wxJkIVmRCj3RgS65BgjOy4LJQkKniBgXLYh8/GB+Qpf2xGp3JSUQKm/3v1H9KUP8LdcymtxfwwoRsEjzhyza/PWvVMwZ02wMMAT18rfniq5zzc1JgKyAtdDOvYTCxJ96OmES5f4cqpoGrMgwrsDJEPC2NUrKEcGc7Un+rEvsXmBhBWgcbeKZTZRimW3C0OzMHnw3taaMYM6TCZMKpRi+qOj/mr1JSnab0Ju6Xez/Aq98x4kuL5WaXZ26Qpc9qI0uct5bOZk9I2tg8CJkn6BlyDGnVmPukyVZcCm1YbkaUlv2SNnS81Cx7fiwE4wbPP+CVBiKozma+dAOTyNasDBU5ABc1A8aO/WTN+OmjOiyeKSSjtrtex9INqnPcDulKQbh+QVNYGahvFMLQPrEMsn9TdyhvvV6g1sAqsq9h09ubyOYPItfWQCS0gpgXoLcv9LRFg4m5GA0xOjPmLTlc90or4EaGecoarIfsltY1DEoeUsYyssVDzME6B6N5ilF/7+ccNjVvw4Mzqg3+ZGCH3+EpxZdOhuYXXfiRzHa1Pb6/dhH0pMlbpxqNKku4/RXdqBeI0xckzmyWICbQtDa0Uo7V+W6BfcWvtaOifhzsnmDjd5sfQ7keZSPn4HYsyeSkyG+lpOJLgipajGrmE1Zzh51hftqYNQCre142+Onj7tEEwQeDqQs1eJQosgt1CIJ/yY5RQHTQeVXf9kj2j7r6LU1VpG1gkeaCfEKb+okWOFL4Dg4NEgKkC3wCaCGiPzfYUqtNcmMdbkXU3IlEyCZC3GVTcJRhBn2dG+WDSFDzha6oFxUSP/4rsUPd+SuSvVbxI/ofZLNmRg+jtF5UdO8UH0C4rAeXF7XNAWRqbQbbw3vge2rwLbJ6UGpisxcU2jkcZe3ZMTUCoiyEmwXJHwipQpKyNwD3DsJozK8uUoLYdnK6oj/pZ7J59Jj+O34o+LvEe8biYXN5wRtOjktaM9VPQB79dZOY6NI3EUxTibPVEQDpSpBb3U67UKJ6FUBEeVYnFAN2LY5hBae5BqIcZk6LgM3c9nujrTpxW6GRLJF9omFiQosHVbUojDePQ73LyVO+0I01IQBJ/TAsmO2PmR9ldGY3IDunoqyWki05zBaARB+xsfXQCP7JExNfjfNHhqO2EUNVLr+2VDPEVZ9ME9QMMFvy8n+6lpxKMx5Tu8otxsxqhDCASJbSsHwXLIPnmZe4/QJNCEWh4OE5jkRSjauQud0kP1kRDvOSLAl/GZxmUJDDFMz+wsyCcTCvN7RyXPDLsTw+MJcOgK3tP2kFjR1HRvx0gceoyOCdcNfRdA34aYkgVQF6zjd5Cup0UZgYXu/bs3zyu9enCcM5CQdRG9wIEzJjNAjg3vctrKHMHbfxRuofNK0Imto3Hb4EW67X78SKPJdil81Hu6VmTQVRi+bqWbO0q1k7JJYidNIdNVYz64hvR1izjPNTpPXGTe5F01HPYbJh/pmGMJCrXAUItl2BY7ofmuVVAPwy544hoaYS+i3+SZpXsb6eVt+FWwaKOBYcgGwElX5aMtTwxs+TOhW5MiY91rGLir+iVyJIyY7OdGX331jjaxKEJERWqFsMV40jLP6cIPjO3qQiy62VFTQ74C1vtxdaaS/4YL1E85qmC9C/8O58dxW8q2nNtpd/OL68hetNoTufWoJ/0+zwsuQow4E1nVLEWbZ05hnahUNdwtXsen/9h/+8UB6ObB70MbRKu5jP1CuVT2DtPFMfSCk2t5SjbVQ8W7ZgkSKqxAqk/gxT9OnMDi/j+jD06itIo+NR9QmLu0EGKA5o93reLHEVjrRb6jVL4cIZ5RKoJFRSVUUxsr2QOX46CjmZBLNaXszzKU6C7QPdS/iRXNn6C5XCZ3ABnYNPBD9cKjzqwn+eUSeOrLTeLJJdRcpf9GIClF0eeAzfeA+YJik4cvnShq7sNzCBeYsgEFu+WfdmJ52azT5BcB5qN42l8kGT7ZIG45XRXpJ80ksTRqyzYk2x5G8bpyh37zftJV4t4GA+3fFvGAJpkWyTUqqZajGOwZxNkenBmHjcYbGhljgecz0xAMDG6rxlqF6/2uZjgbnfNgJxf7ER0fotRNZEblth2LF7gga2sVdf2lP6oH17maL8V61MhBiQJGJLiZzE6JhKQaXmR/r9PNou1p6zvt2uJr1xqosvbH2ADd2ScpnSc4Y53wHJRZPMbIi4OA8r3dImNMmSGnp3OWG8l4n+1+7FaCpVvYf1rWewQ7qB4TH2ZfjB0gkkPSHbB1xVIRl116tC4iGC3w1clR/g24gDJCa4PzOJ48rgoXBdQfZ+ACbCMhx0VER7mo2lVzcSYljgbYnJa3ZgzSBoa8/xWY3RzsDlodzKU+hfhGLrUa0hMKuKtU5uRtuGt9ujBsZbT9LYPk5+s8uFqkoPMWVE9tuONnVuieay+SyWv/v2kKsQxea0hHJvK5ITECSTgaV3Fi6HToua6pPm9J3MlJa7nNnofYMpF55BmrxDEaK8qCkt9/5Rmr/VZ47bd2pvaKPLezTL/yFC3IRrqrFyp4NbIdSbqtpz028Gdti52myxLUgWMdMITiFw6v46402sZIbgO44rqhYWtY5yzjimUnTbSIJG7WinCylJKNon75sk7lkscj2RoC0j7pYAcsxfwSILx494Z+MoZyL+9u3vPwzgkEUAQds8ratzbyVLaL961jxwhXicK2UalH8Jhw404VXvPCxUK//0EsfWtvb8kLCpWmNe7Q+lChJqXSS3jJFcIQ2/XpJjP4PygtC55OCkf0nz0ySYKJhnXu0=", - "transactionHash": "6BCuJYD5HpCZBY9JeUo1LNJlb7IzLZEDRNwD6KDd3D4=" + "publicKey": "AQMAOOpjdQafgnLMGmYBs8dsIVGUVWA9NwA2uXx3mto1ZYVOOYO9VkKYxJri5/puKNS5VNjNWTmPEiWwjWFEhUruDg==" }""" test_signature_Simple = "0000000a899e73cfbf8c57027f5a0f853b9906701ee378ad169d34ce45153f13" \ diff --git a/tests/misc/helper.py b/tests/misc/helper.py index acb042eb3..ee76a94f1 100644 --- a/tests/misc/helper.py +++ b/tests/misc/helper.py @@ -269,4 +269,4 @@ def gen_blocks(block_count, state, miner_address): state.update_mainchain_height(block.block_number, None) OptimizedAddressState.put_optimized_addresses_state(state, addresses_state) - return blocks \ No newline at end of file + return blocks From 72e5f856bf3fa7f18c906baaaa97c898cdd15b69 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 16:36:58 +0530 Subject: [PATCH 09/67] Fix: More fix for flake8 --- tests/core/test_ChainManager.py | 35 ++++++++++++++++----------------- tests/core/test_Miner.py | 3 +-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 15d42b858..0d35df8e3 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -173,7 +173,6 @@ def test_multi_output_transaction_add_block(self, time_mock): block_1.set_nonces(config.dev, 129, 0) # Uncomment only to determine the correct mining_nonce of above blocks - from qrl.core.PoWValidator import PoWValidator # while not PoWValidator().validate_mining_nonce(self.state, block_1.blockheader, False): # block_1.set_nonces(block_1.mining_nonce + 1) # print(block_1.mining_nonce) @@ -3506,8 +3505,8 @@ def test_roll_back3(self, time_mock): block_1.fee_reward + block_1.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, @@ -3554,8 +3553,8 @@ def test_roll_back3(self, time_mock): block_2.fee_reward + block_2.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, @@ -3615,8 +3614,8 @@ def test_roll_back3(self, time_mock): block_3.fee_reward + block_3.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, @@ -3678,8 +3677,8 @@ def test_roll_back3(self, time_mock): block_4.fee_reward + block_4.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, @@ -3745,16 +3744,16 @@ def test_roll_back3(self, time_mock): block_5.fee_reward + block_5.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0] - + multi_sig_spend2.amounts[1]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0] + + multi_sig_spend2.amounts[1]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, - transfer_transaction1.total_amount - + transfer_transaction2.total_amount - - multi_sig_spend1.total_amount - - multi_sig_spend2.total_amount) + transfer_transaction1.total_amount + + transfer_transaction2.total_amount - + multi_sig_spend1.total_amount - + multi_sig_spend2.total_amount) # Check Txns in State vote_stats = self.chain_manager.get_vote_stats(multi_sig_spend1.txhash) @@ -3881,8 +3880,8 @@ def test_roll_back3(self, time_mock): block_4.fee_reward + block_4.block_reward) self.assertEqual(random_addr_state.balance, - 100 * int(config.dev.shor_per_quanta) - + multi_sig_spend1.amounts[0]) + 100 * int(config.dev.shor_per_quanta) + + multi_sig_spend1.amounts[0]) self.assertIsNotNone(multi_sig_address_state) self.assertEqual(multi_sig_address_state.balance, diff --git a/tests/core/test_Miner.py b/tests/core/test_Miner.py index ac1c55d89..510828b51 100644 --- a/tests/core/test_Miner.py +++ b/tests/core/test_Miner.py @@ -1,6 +1,6 @@ from unittest import TestCase -from mock import Mock, patch, create_autospec, MagicMock +from mock import Mock, patch, MagicMock from pyqryptonight.pyqryptonight import StringToUInt256 from qrl.core.OptimizedAddressState import OptimizedAddressState @@ -14,7 +14,6 @@ from qrl.core.TransactionPool import TransactionPool from qrl.core.misc.helper import parse_qaddress from qrl.core.node import POW -from qrl.core.p2p.p2pfactory import P2PFactory from qrl.core.txs.CoinBase import CoinBase from qrl.core.txs.TransferTransaction import TransferTransaction from tests.misc.helper import get_alice_xmss, get_bob_xmss, replacement_getTime From 349af2ba35462b2c00b88fe24bb4e32bba502783 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:27:31 +0530 Subject: [PATCH 10/67] Removed unnecessary functions from State --- src/qrl/core/State.py | 200 ------------------------------------------ 1 file changed, 200 deletions(-) diff --git a/src/qrl/core/State.py b/src/qrl/core/State.py index aea30e12c..0817e0e88 100644 --- a/src/qrl/core/State.py +++ b/src/qrl/core/State.py @@ -9,10 +9,6 @@ class State: - # FIXME: Rename to PersistentState - # FIXME: Move blockchain caching/storage over here - # FIXME: Improve key generation - def __init__(self, my_db=None): self._db = my_db if not my_db: @@ -193,42 +189,6 @@ def generate_token_key(address, token_txhash) -> bytes: def generate_slave_key(address, slave_pk) -> bytes: return b'slave_' + address + b'_' + slave_pk - def get_token(self, address: bytes, token_txhash: bytes) -> qrl_pb2.TokenBalance: - try: - token_balance = qrl_pb2.TokenBalance() - token_balance.ParseFromString(self._db.get_raw(self.generate_token_key(address, token_txhash))) - return token_balance - except KeyError: - pass - except Exception as e: - logger.error('[get_token] %s', e) - - return None - - def put_tokens(self, tokens: dict, batch=None): - for address_txhash, value in tokens.items(): - token_key = self.generate_token_key(address_txhash[0], address_txhash[1]) - self._db.put_raw(token_key, str(value).encode(), batch) - return True - - def revert_tokens(self, tokens: dict, batch): - for address_txhash in tokens: - token_key = self.generate_token_key(address_txhash[0], address_txhash[1]) - self._db.delete(token_key, batch) - return True - - def revert_slaves(self, slaves: dict, batch): - for address, slave_pk in slaves: - slave_key = self.generate_slave_key(address, slave_pk) - self._db.delete(slave_key, batch) - return True - - def put_slaves(self, slaves: dict, batch=None): - for address_slave_pk in slaves: - address, slave_pk = address_slave_pk - slave_key = self.generate_slave_key(address, slave_pk) - self._db.put_raw(slave_key, str(slaves[address_slave_pk][0]).encode(), batch) - def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.SlaveMetadata: slave_key = self.generate_slave_key(address, slave_pk) try: @@ -241,163 +201,3 @@ def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.S logger.error('[get_slave_pk_access_type] %s', e) return None - - def revert_slaves_hash(self, slaves: dict, addresses_state: dict, batch): - addresses_slave_hashes = dict() - for address, slave_pk in slaves: - if address not in addresses_slave_hashes: - addresses_slave_hashes[address] = self.get_slave_transaction_hashes(address, - addresses_state[address].slaves_count) - - if addresses_slave_hashes[address][-1] != slaves[(address, slave_pk)].tx_hash: - logger.warning("UnExpected Addresses Slave hashes") - logger.warning("Expected %s", slaves[(address, slave_pk)][1]) - logger.warning("Found %s", addresses_slave_hashes[address][-1]) - return False - - del addresses_slave_hashes[address][-1] - address_state = addresses_state[address] - address_state.update_slaves_count(subtract=True) - - if len(addresses_slave_hashes[address]) == 0: - self.remove_slave_transaction_hashes(address, - address_state.slaves_count, - batch) - if address_state.slaves_count > 0: - addresses_slave_hashes[address] = self.get_slave_transaction_hashes( - address, address_state.slaves_count - 1) - - for address in addresses_slave_hashes: - if addresses_slave_hashes[address]: - self.put_slave_transaction_hashes(address, - addresses_state[address].slaves_count, - addresses_slave_hashes[address], - batch) - - return True - - def put_slaves_hash(self, slaves: dict, addresses_state: dict, batch=None): - slave_hashes = dict() - for address_slave_pk in slaves: - address, _ = address_slave_pk - # There could be case where same address associated with multiple - # slave_pk so full_hashes needs to be loaded only once - if address not in slave_hashes: - full_hashes = self.get_slave_transaction_hashes(address, addresses_state[address].slaves_count) - addresses_state[address].update_slaves_count(len(full_hashes), subtract=True) - slave_hashes[address] = full_hashes - slave_hashes[address].append(slaves[address_slave_pk].tx_hash) - - for address in slave_hashes: - full_hashes = slave_hashes[address] - start = 0 - hashes = full_hashes[start:start + config.dev.data_per_page] - address_state = addresses_state[address] - while hashes: - address_state.update_slaves_count(len(hashes)) - self.put_slave_transaction_hashes(address, address_state.slaves_count, hashes, batch) - start += config.dev.data_per_page - hashes = full_hashes[start:start + config.dev.data_per_page] - - def remove_slave_transaction_hashes(self, address: bytes, page: int, batch=None): - self._db.delete(b'slave_transaction_hash_' + address + b'_' + str(page).encode(), - batch) - - def put_slave_transaction_hashes(self, address: bytes, count: int, hashes: list, batch=None): - page = count // config.dev.data_per_page - transaction_hash_list = qrl_pb2.TransactionHashList(hashes=hashes) - self._db.put_raw(b'slave_transaction_hash_' + address + b'_' + str(page).encode(), - transaction_hash_list.SerializeToString(), - batch) - - def get_slave_transaction_hashes(self, address: bytes, count: int) -> list: - page = count // config.dev.data_per_page - try: - data = self._db.get_raw(b'slave_transaction_hash_' + address + b'_' + str(page).encode()) - transaction_hash_list = qrl_pb2.TransactionHashList() - transaction_hash_list.ParseFromString(bytes(data)) - return list(transaction_hash_list.hashes) - except KeyError: - return [] - except Exception as e: - logger.error('Exception in get_slave_transaction_hashes') - logger.exception(e) - raise - - def put_tokens_hash(self, tokens: dict, addresses_state: dict, batch=None): - token_hashes = dict() - for address_token_tx_hash in tokens: - address, token_tx_hash = address_token_tx_hash - # There could be case where same address associated with multiple - # token_tx_hash so full_hashes needs to be loaded only once - if address not in token_hashes: - full_hashes = self.get_token_transaction_hashes(address, addresses_state[address].tokens_count) - addresses_state[address].update_tokens_count(len(full_hashes), subtract=True) - token_hashes[address] = full_hashes - token_hashes[address].append(token_tx_hash) - - for address in token_hashes: - full_hashes = token_hashes[address] - start = 0 - hashes = full_hashes[start:start + config.dev.data_per_page] - address_state = addresses_state[address] - while hashes: - self.put_token_transaction_hashes(address, address_state.tokens_count, hashes, batch) - address_state.update_tokens_count(len(hashes)) - start += config.dev.data_per_page - hashes = full_hashes[start:start + config.dev.data_per_page] - - def revert_tokens_hash(self, tokens: dict, addresses_state: dict, batch): - addresses_token_tx_hashes = dict() - for address_token_tx_hash in tokens: - address, token_tx_hash = address_token_tx_hash - if address not in addresses_token_tx_hashes: - addresses_token_tx_hashes[address] = self.get_token_transaction_hashes(address, - addresses_state[address].tokens_count) - - if addresses_token_tx_hashes[address][-1] != token_tx_hash: - return False - del addresses_token_tx_hashes[address][-1] - address_state = addresses_state[address] - address_state.update_tokens_count(subtract=True) - if len(addresses_token_tx_hashes[address]) == 0: - self.remove_token_transaction_hash(address, - address_state.tokens_count, - batch) - if address_state.tokens_count > 0: - addresses_token_tx_hashes[address] = self.get_token_transaction_hashes( - address, address_state.tokens_count - 1) - - for address in addresses_token_tx_hashes: - if addresses_token_tx_hashes[address]: - self.put_token_transaction_hashes(address, - addresses_state[address].tokens_count, - addresses_token_tx_hashes[address], - batch) - - return True - - def remove_token_transaction_hash(self, address, count, batch): - page = count // config.dev.data_per_page - self._db.delete(b'token_transaction_hash_' + address + b'_' + str(page).encode(), batch) - - def put_token_transaction_hashes(self, address: bytes, count: int, hashes: list, batch=None): - page = count // config.dev.data_per_page - transaction_hash_list = qrl_pb2.TransactionHashList(hashes=hashes) - self._db.put_raw(b'token_transaction_hash_' + address + b'_' + str(page).encode(), - transaction_hash_list.SerializeToString(), - batch) - - def get_token_transaction_hashes(self, address: bytes, count: int) -> list: - page = count // config.dev.data_per_page - try: - data = self._db.get_raw(b'token_transaction_hash_' + address + b'_' + str(page).encode()) - transaction_hash_list = qrl_pb2.TransactionHashList() - transaction_hash_list.ParseFromString(bytes(data)) - return list(transaction_hash_list.hashes) - except KeyError: - return [] - except Exception as e: - logger.error('Exception in get_token_transaction_hashes') - logger.exception(e) - raise From 7f3dc0ae17d0933af4c9bd211ad91276692bda45 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:27:57 +0530 Subject: [PATCH 11/67] Simplified function calls --- src/qrl/core/ChainManager.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index d859384db..1406aa1af 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -117,7 +117,10 @@ def get_bitfield(self, address: bytes, page: int): def is_slave(self, master_address: bytes, slave_pk: bytes) -> bool: with self.lock: - return self._state.get_slave_pk_access_type(master_address, slave_pk) == 0 + slave_meta_data = self._state.get_slave_pk_access_type(master_address, slave_pk) + if slave_meta_data: + return slave_meta_data.access_type == 0 + return False def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.SlaveMetadata: with self.lock: @@ -413,11 +416,6 @@ def load(self, genesis_block): tx.apply(self._state, state_container) state_container.paginated_tx_hash.put_paginated_data(None) - state_container.tokens.put() - self._state.put_tokens_hash(state_container.tokens.data, state_container.addresses_state) - - state_container.slaves.put() - self._state.put_slaves_hash(state_container.slaves.data, state_container.addresses_state) AddressState.put_addresses_state(self._state, state_container.addresses_state) state_container.paginated_bitfield.put_addresses_bitfield(None) @@ -448,16 +446,6 @@ def load(self, genesis_block): logger.warning("Migrated Block %s/%s", self.height, height) state_migration.state_migration_step_2(self._state) - def _apply_block(self, block: Block, dev_config: DevConfig, batch) -> bool: - # address_set = self._state.prepare_address_list(block) # Prepare list for current block - # addresses_state = self._state.get_state_mainchain(address_set) - # if not block.apply_state_changes(addresses_state): - # return False - if not self.apply_state_changes(block, dev_config, batch): - return False - # self._state.put_addresses_state(addresses_state, batch) - return True - # TODO: Update re-org limit when dev_config is updated def _update_chainstate(self, block: Block, batch): self._last_block = block @@ -480,7 +468,7 @@ def _try_branch_add_block(self, block, dev_config: DevConfig, check_stale=True) batch = self._state.batch if self._last_block.headerhash == block.prev_headerhash: - if not self._apply_block(block, dev_config, batch): + if not self._apply_state_changes(block, batch): return False Block.put_block(self._state, block, batch) @@ -609,7 +597,7 @@ def add_chain(self, hash_path: list, fork_state: qrlstateinfo_pb2.ForkState) -> batch = self._state.batch - if not self._apply_block(block, config.dev, batch): + if not self._apply_state_changes(block, batch): return False self._update_chainstate(block, batch) @@ -848,7 +836,7 @@ def update_state_container(self, multi_sig_spend_txs, votes_stats) - def apply_state_changes(self, block, dev_config: DevConfig, batch) -> bool: + def _apply_state_changes(self, block, batch) -> bool: state_container = self.new_state_container(set(), block.block_number, True, From e10eb95fdb19b46d270beea2dc6d0f7a148ba19a Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:28:31 +0530 Subject: [PATCH 12/67] Fixed Unit Test for Wallet Daemon --- tests/daemon/test_walletd.py | 173 ++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 76 deletions(-) diff --git a/tests/daemon/test_walletd.py b/tests/daemon/test_walletd.py index 01aee68fe..3c962443a 100644 --- a/tests/daemon/test_walletd.py +++ b/tests/daemon/test_walletd.py @@ -16,6 +16,7 @@ from qrl.generated.qrl_pb2_grpc import add_PublicAPIServicer_to_server from qrl.services.PublicAPIService import PublicAPIService from qrl.core.ChainManager import ChainManager +from qrl.core.AddressState import AddressState from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.txs.MessageTransaction import MessageTransaction @@ -105,147 +106,167 @@ def test_get_slave(self): with set_qrl_dir("wallet_ver1") and set_qrl_dir('no_data'): state = State() chain_manager = ChainManager(state) - qrlnode = QRLNode(mining_address=b'') - qrlnode.set_chain_manager(chain_manager) + qrl_node = QRLNode(mining_address=b'') + qrl_node.set_chain_manager(chain_manager) public_api_server = grpc.server(ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=1) - add_PublicAPIServicer_to_server(PublicAPIService(qrlnode), public_api_server) + add_PublicAPIServicer_to_server(PublicAPIService(qrl_node), public_api_server) public_api_server.add_insecure_port("{0}:{1}".format(config.user.public_api_host, config.user.public_api_port)) public_api_server.start() walletd = WalletD() - m = MockFunction() - - walletd.get_address_state = m.get walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address_with_slaves(height=10) + master_address = walletd.qaddress_to_address(qaddress) walletd.encrypt_wallet(self.passphrase) walletd.unlock_wallet(self.passphrase) - master_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) - m.put(qaddress, master_addr_state) - slaves = walletd.get_slave_list(qaddress) - slaves_state = { - (master_addr_state.address, bytes(hstr2bin(slaves[0][0].pk))): (0, b'txhash0'), - (master_addr_state.address, bytes(hstr2bin(slaves[0][1].pk))): (0, b'txhash0'), - (master_addr_state.address, bytes(hstr2bin(slaves[0][2].pk))): (0, b'txhash0'), - } - state.put_slaves(slaves_state) + state_container = chain_manager.new_state_container({master_address, + walletd.qaddress_to_address(slaves[0][0].qaddress), + walletd.qaddress_to_address(slaves[0][1].qaddress), + walletd.qaddress_to_address(slaves[0][2].qaddress)}, + 5, + True, + None) + + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[0][0].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash0') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[0][1].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash0') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[0][2].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash0') + state_container.slaves.put(None) self.assertEqual(len(slaves), 1) self.assertEqual(len(slaves[0]), 3) - slave00_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][0].qaddress)) - slave01_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][1].qaddress)) - slave02_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[0][2].qaddress)) - addresses_bitfield = dict() - addresses_state = { - slave00_addr_state.address: slave00_addr_state, - slave01_addr_state.address: slave01_addr_state, - slave02_addr_state.address: slave02_addr_state, - } - self.assertEqual(slaves[0][0].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave00_addr_state.address, i) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[0][0].qaddress), + i) walletd._wallet.set_slave_ots_index(0, 0, 0, 1020) - m.put(slaves[0][0].qaddress, slave00_addr_state) self.assertEqual(slaves[0][1].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave01_addr_state.address, i) - m.put(slaves[0][1].qaddress, slave01_addr_state) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[0][1].qaddress), + i) + walletd._wallet.set_slave_ots_index(0, 0, 1, 1020) self.assertEqual(slaves[0][2].index, 5) for i in range(5, 1000): - state.set_ots_key(addresses_bitfield, addresses_state, slave02_addr_state.address, i) - state.put_addresses_bitfield(addresses_bitfield) - m.put(slaves[0][2].qaddress, slave02_addr_state) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[0][2].qaddress), + i) + walletd._wallet.set_slave_ots_index(0, 0, 2, 1018) + + state_container.paginated_bitfield.put_addresses_bitfield(None) + AddressState.put_addresses_state(state, state_container.addresses_state) walletd.get_slave(qaddress) slaves = walletd.get_slave_list(qaddress) self.assertEqual(len(slaves), 2) walletd._wallet.set_slave_ots_index(0, 0, 2, 1019) - slave10_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][0].qaddress)) - slave11_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][1].qaddress)) - slave12_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[1][2].qaddress)) - slaves_state = { - (master_addr_state.address, bytes(hstr2bin(slaves[1][0].pk))): (0, b'txhash1'), - (master_addr_state.address, bytes(hstr2bin(slaves[1][1].pk))): (0, b'txhash1'), - (master_addr_state.address, bytes(hstr2bin(slaves[1][2].pk))): (0, b'txhash1'), - } - state.put_slaves(slaves_state) - addresses_bitfield = dict() - addresses_state = { - slave10_addr_state.address: slave10_addr_state, - slave11_addr_state.address: slave11_addr_state, - slave12_addr_state.address: slave12_addr_state, - } + state_container = chain_manager.new_state_container({master_address, + walletd.qaddress_to_address(slaves[1][0].qaddress), + walletd.qaddress_to_address(slaves[1][1].qaddress), + walletd.qaddress_to_address(slaves[1][2].qaddress)}, + 5, + True, + None) + + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[1][0].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash1') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[1][1].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash1') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[1][2].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash1') + state_container.slaves.put(None) self.assertEqual(slaves[1][0].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave10_addr_state.address, i) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[1][0].qaddress), + i) walletd._wallet.set_slave_ots_index(0, 1, 0, 1020) - m.put(slaves[1][0].qaddress, slave10_addr_state) self.assertEqual(slaves[1][1].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave11_addr_state.address, i) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[1][1].qaddress), + i) walletd._wallet.set_slave_ots_index(0, 1, 1, 1020) - m.put(slaves[1][1].qaddress, slave11_addr_state) self.assertEqual(slaves[1][2].index, 5) for i in range(5, 1000): - state.set_ots_key(addresses_bitfield, addresses_state, slave12_addr_state.address, i) - state.put_addresses_bitfield(addresses_bitfield) - m.put(slaves[1][2].qaddress, slave12_addr_state) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[1][2].qaddress), + i) + walletd._wallet.set_slave_ots_index(0, 1, 2, 1018) + state_container.paginated_bitfield.put_addresses_bitfield(None) + AddressState.put_addresses_state(state, state_container.addresses_state) walletd.get_slave(qaddress) slaves = walletd.get_slave_list(qaddress) self.assertEqual(len(slaves), 3) walletd._wallet.set_slave_ots_index(0, 1, 2, 1019) - slave20_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][0].qaddress)) - slave21_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][1].qaddress)) - slave22_addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(slaves[2][2].qaddress)) - slaves_state = { - (master_addr_state.address, bytes(hstr2bin(slaves[2][0].pk))): (0, b'txhash2'), - (master_addr_state.address, bytes(hstr2bin(slaves[2][1].pk))): (0, b'txhash2'), - (master_addr_state.address, bytes(hstr2bin(slaves[2][2].pk))): (0, b'txhash2'), - } - state.put_slaves(slaves_state) - addresses_bitfield = dict() - addresses_state = { - slave20_addr_state.address: slave20_addr_state, - slave21_addr_state.address: slave21_addr_state, - slave22_addr_state.address: slave22_addr_state, - } + state_container = chain_manager.new_state_container({master_address, + walletd.qaddress_to_address(slaves[2][0].qaddress), + walletd.qaddress_to_address(slaves[2][1].qaddress), + walletd.qaddress_to_address(slaves[2][2].qaddress)}, + 5, + True, + None) + + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[2][0].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash2') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[2][1].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash2') + state_container.slaves.data[(master_address, + bytes(hstr2bin(slaves[2][2].pk)))] = qrl_pb2.SlaveMetadata(access_type=0, + tx_hash=b'txhash2') + state_container.slaves.put(None) self.assertEqual(slaves[2][0].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave20_addr_state.address, i) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[2][0].qaddress), + i) walletd._wallet.set_slave_ots_index(0, 2, 0, 1020) - m.put(slaves[2][0].qaddress, slave20_addr_state) self.assertEqual(slaves[2][1].index, 0) for i in range(0, 1024): - state.set_ots_key(addresses_bitfield, addresses_state, slave21_addr_state.address, i) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[2][1].qaddress), + i) walletd._wallet.set_slave_ots_index(0, 2, 1, 1020) - m.put(slaves[2][1].qaddress, slave20_addr_state) self.assertEqual(slaves[2][2].index, 5) for i in range(5, 1000): - state.set_ots_key(addresses_bitfield, addresses_state, slave22_addr_state.address, i) - state.put_addresses_bitfield(addresses_bitfield) - m.put(slaves[2][2].qaddress, slave22_addr_state) + state_container.paginated_bitfield.set_ots_key(state_container.addresses_state, + walletd.qaddress_to_address(slaves[2][2].qaddress), + i) + walletd._wallet.set_slave_ots_index(0, 2, 2, 1018) + state_container.paginated_bitfield.put_addresses_bitfield(None) + AddressState.put_addresses_state(state, state_container.addresses_state) walletd.get_slave(qaddress) slaves = walletd.get_slave_list(qaddress) From 9e7be2545ce1900727d8908488b9b2c62c41c82d Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:28:48 +0530 Subject: [PATCH 13/67] Updated Unit Test for the changes made on ChainManager --- tests/core/test_ChainManager.py | 10 +++++----- tests/core/test_block.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 0d35df8e3..2f2065f85 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -4365,9 +4365,9 @@ def test_get_fork_point_failure_modes(self, mock_block): with self.assertRaises(Exception): self.chain_manager._get_fork_point(block_2) - def test_try_branch_add_block_fails_if_apply_block_fails(self): - # ChainManager._try_branch_add_block() should fail if ChainManager._apply_block() fails - self.chain_manager._apply_block = Mock(return_value=False) + def test_try_branch_add_block_fails_if_apply_state_changes_fails(self): + # ChainManager._try_branch_add_block() should fail if ChainManager._apply_state_changes() fails + self.chain_manager._apply_state_changes = Mock(return_value=False) block = create_m_block(50, self.genesis_block, alice.address) @@ -4394,7 +4394,7 @@ def test_add_chain_fails_if_fork_recovery_didnt_complete_successfully(self): self.assertFalse(ans) @patch('qrl.core.Block.Block', autospec=True) - def test_add_chain_fails_if_apply_block_fails(self, mock_block_deserialize): + def test_add_chain_fails_if_apply_state_changes_fails(self, mock_block_deserialize): block_1 = create_m_block(1, self.genesis_block, alice.address) block_2 = create_m_block(2, block_1, alice.address) @@ -4410,7 +4410,7 @@ def test_add_chain_fails_if_apply_block_fails(self, mock_block_deserialize): ) # we want to add_chain(block_*_alt chain), but for some reason applying a Block to the State didn't work. - self.chain_manager._apply_block = Mock(return_value=False) + self.chain_manager._apply_state_changes = Mock(return_value=False) ans = self.chain_manager.add_chain([block_1_alt.headerhash, block_2_alt.headerhash], fork_state) self.assertFalse(ans) diff --git a/tests/core/test_block.py b/tests/core/test_block.py index fe2c6bf5f..3841c0b0c 100644 --- a/tests/core/test_block.py +++ b/tests/core/test_block.py @@ -264,7 +264,7 @@ def test_all_ok(self, m_TransferTransaction_validate, m_TransferTransaction_vali self.chain_manager.get_optimized_address_state = get_optimized_address_state.get block = Block.create(**self.block_attrs) - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertTrue(result) def test_extra_coinbase_tx(self, @@ -282,7 +282,7 @@ def test_extra_coinbase_tx(self, self.block_attrs["transactions"] = [self.tx1, coinbase_extra, self.tx2] block = Block.create(**self.block_attrs) - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) def test_bad_nonce_or_ots_reused(self, @@ -300,16 +300,16 @@ def test_bad_nonce_or_ots_reused(self, get_optimized_address_state.put(self.slave_addrstate_attrs.address, self.slave_addrstate_attrs) block = Block.create(**self.block_attrs) - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) self.slave_addrstate_attrs.pbdata.nonce = 5 # Now we pretend that Alice's OTS key has been reused. - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) # Now we pretend that Slave's OTS key has been reused. - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) def test_tx_validation_fails(self, @@ -326,18 +326,18 @@ def test_tx_validation_fails(self, block = Block.create(**self.block_attrs) m_TransferTransaction_validate.return_value = False - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) m_TransferTransaction_validate.return_value = True m_TransferTransaction_validate_extended.return_value = False - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) m_TransferTransaction_validate_extended.return_value = True with patch('qrl.core.txs.CoinBase.CoinBase._validate_extended') as m_validate_extended: m_validate_extended.return_value = False - result = self.chain_manager.apply_state_changes(block, config.dev, None) + result = self.chain_manager._apply_state_changes(block, None) self.assertFalse(result) def test_put_block_number_mapping(self, From 3217f9214fc5c7f3b0dd5138e8967153f23087a4 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:31:37 +0530 Subject: [PATCH 14/67] Removed unused import --- tests/daemon/test_walletd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/daemon/test_walletd.py b/tests/daemon/test_walletd.py index 3c962443a..36cec613d 100644 --- a/tests/daemon/test_walletd.py +++ b/tests/daemon/test_walletd.py @@ -23,7 +23,6 @@ from qrl.daemon.helper.DaemonHelper import WalletDecryptionError from qrl.core.misc import logger from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_bob_xmss -from tests.misc.MockHelper.mock_function import MockFunction logger.initialize_default() From 45bc9db4d6779179970def128d16e1dd23090a69 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:54:44 +0530 Subject: [PATCH 15/67] Updated txn validations --- src/qrl/core/txs/LatticeTransaction.py | 8 ++++---- src/qrl/core/txs/MessageTransaction.py | 8 ++++---- src/qrl/core/txs/SlaveTransaction.py | 8 +++----- src/qrl/core/txs/TransferTokenTransaction.py | 3 ++- src/qrl/core/txs/TransferTransaction.py | 3 ++- src/qrl/core/txs/multisig/MultiSigCreate.py | 3 ++- src/qrl/core/txs/multisig/MultiSigSpend.py | 3 ++- src/qrl/core/txs/multisig/MultiSigVote.py | 3 ++- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/qrl/core/txs/LatticeTransaction.py b/src/qrl/core/txs/LatticeTransaction.py index a1bf77ca2..987b9c002 100644 --- a/src/qrl/core/txs/LatticeTransaction.py +++ b/src/qrl/core/txs/LatticeTransaction.py @@ -56,6 +56,10 @@ def create(pk1: bytes, pk2: bytes, pk3: bytes, pk4: bytes, fee: int, xmss_pk: by return transaction def _validate_custom(self) -> bool: + if self.fee < 0: + logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) + return False + return True def _validate_extended(self, state_container: StateContainer) -> bool: @@ -86,10 +90,6 @@ def _validate_extended(self, state_container: StateContainer) -> bool: tx_balance = state_container.addresses_state[self.addr_from].balance - if self.fee < 0: - logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) - return False - if tx_balance < self.fee: logger.info('State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, amount: %s', tx_balance, self.fee) diff --git a/src/qrl/core/txs/MessageTransaction.py b/src/qrl/core/txs/MessageTransaction.py index 50533b813..3190a3b22 100644 --- a/src/qrl/core/txs/MessageTransaction.py +++ b/src/qrl/core/txs/MessageTransaction.py @@ -55,6 +55,10 @@ def _validate_custom(self) -> bool: logger.warning('[MessageTransaction] Invalid address addr_to: %s', bin2hstr(self.addr_to)) return False + if self.fee < 0: + logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) + return False + return True def _validate_extended(self, state_container: StateContainer) -> bool: @@ -70,10 +74,6 @@ def _validate_extended(self, state_container: StateContainer) -> bool: tx_balance = state_container.addresses_state[self.addr_from].balance - if self.fee < 0: - logger.info('State validation failed for %s because: Negative send', bin2hstr(self.txhash)) - return False - if tx_balance < self.fee: logger.info('State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, amount: %s', tx_balance, self.fee) diff --git a/src/qrl/core/txs/SlaveTransaction.py b/src/qrl/core/txs/SlaveTransaction.py index 43f9426a8..3ea15ec48 100644 --- a/src/qrl/core/txs/SlaveTransaction.py +++ b/src/qrl/core/txs/SlaveTransaction.py @@ -68,7 +68,9 @@ def _validate_custom(self) -> bool: logger.warning('Invalid Access type %s', access_type) return False - # TODO: Add Maximum PK size limit + if self.fee < 0: + logger.info('Slave: State validation failed for %s because: Negative send', bin2hstr(self.txhash)) + return False return True @@ -83,10 +85,6 @@ def _validate_extended(self, state_container: StateContainer) -> bool: tx_balance = state_container.addresses_state[self.addr_from].balance - if self.fee < 0: - logger.info('Slave: State validation failed for %s because: Negative send', bin2hstr(self.txhash)) - return False - if tx_balance < self.fee: logger.info('Slave: State validation failed for %s because: Insufficient funds', bin2hstr(self.txhash)) logger.info('balance: %s, amount: %s', tx_balance, self.fee) diff --git a/src/qrl/core/txs/TransferTokenTransaction.py b/src/qrl/core/txs/TransferTokenTransaction.py index 8436f08fe..7393c690d 100644 --- a/src/qrl/core/txs/TransferTokenTransaction.py +++ b/src/qrl/core/txs/TransferTokenTransaction.py @@ -83,7 +83,8 @@ def _validate_custom(self): return False if self.fee < 0: - raise ValueError('TransferTokenTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + logger.info('TransferTokenTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + return False if len(self.addrs_to) != len(self.amounts): logger.warning('[TransferTokenTransaction] Mismatch number of addresses to & amounts') diff --git a/src/qrl/core/txs/TransferTransaction.py b/src/qrl/core/txs/TransferTransaction.py index b1cdb6e3d..d07771d71 100644 --- a/src/qrl/core/txs/TransferTransaction.py +++ b/src/qrl/core/txs/TransferTransaction.py @@ -80,7 +80,8 @@ def _validate_custom(self): return False if self.fee < 0: - raise ValueError('TransferTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + logger.info('TransferTransaction [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + return False if len(self.addrs_to) == 0: logger.warning("[TransferTransaction] No Addrs To found") diff --git a/src/qrl/core/txs/multisig/MultiSigCreate.py b/src/qrl/core/txs/multisig/MultiSigCreate.py index d12922dc0..6a3dbb60b 100644 --- a/src/qrl/core/txs/multisig/MultiSigCreate.py +++ b/src/qrl/core/txs/multisig/MultiSigCreate.py @@ -82,7 +82,8 @@ def _validate_custom(self): return False if self.fee < 0: - raise ValueError('MultiSigCreate [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + logger.warning('MultiSigCreate [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + return False if self.total_weight < self.threshold: logger.warning('[MultiSigCreate] Validation failed for %s because: Insufficient weight', diff --git a/src/qrl/core/txs/multisig/MultiSigSpend.py b/src/qrl/core/txs/multisig/MultiSigSpend.py index 8775b74c8..08a3bf672 100644 --- a/src/qrl/core/txs/multisig/MultiSigSpend.py +++ b/src/qrl/core/txs/multisig/MultiSigSpend.py @@ -93,7 +93,8 @@ def _validate_custom(self): return False if self.fee < 0: - raise ValueError('MultiSigSpend [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + logger.warning('MultiSigSpend [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + return False if len(self.addrs_to) == 0: logger.warning('[MultiSigSpend] No addrs_to found') diff --git a/src/qrl/core/txs/multisig/MultiSigVote.py b/src/qrl/core/txs/multisig/MultiSigVote.py index 535ba8e06..61aa1dcf9 100644 --- a/src/qrl/core/txs/multisig/MultiSigVote.py +++ b/src/qrl/core/txs/multisig/MultiSigVote.py @@ -62,7 +62,8 @@ def create(shared_key: bytes, def _validate_custom(self): if self.fee < 0: - raise ValueError('MultiSigVote [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + logger.warning('MultiSigVote [%s] Invalid Fee = %d', bin2hstr(self.txhash), self.fee) + return False return True From 3052120b3961f84278b6536446c5a527b49b260c Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 21:55:19 +0530 Subject: [PATCH 16/67] Updated Unit Tests based on validation changes --- tests/core/txs/test_MessageTransaction.py | 2 +- tests/core/txs/test_SlaveTransaction.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/txs/test_MessageTransaction.py b/tests/core/txs/test_MessageTransaction.py index a82dd1207..e04beedd7 100644 --- a/tests/core/txs/test_MessageTransaction.py +++ b/tests/core/txs/test_MessageTransaction.py @@ -135,7 +135,7 @@ def test_validate_extended(self, m_validate_slave, m_logger): # fee = -1 with patch('qrl.core.txs.MessageTransaction.MessageTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 - result = tx._validate_extended(state_container) + result = tx._validate_custom() self.assertFalse(result) # balance = 0, cannot pay the Transaction fee diff --git a/tests/core/txs/test_SlaveTransaction.py b/tests/core/txs/test_SlaveTransaction.py index e8a789745..0a630e4c7 100644 --- a/tests/core/txs/test_SlaveTransaction.py +++ b/tests/core/txs/test_SlaveTransaction.py @@ -97,7 +97,7 @@ def test_validate_extended(self, m_validate_slave, m_logger): # fee = -1 with patch('qrl.core.txs.SlaveTransaction.SlaveTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 - result = tx._validate_extended(state_container) + result = tx._validate_custom() self.assertFalse(result) # balance = 0, cannot pay the Transaction fee From a66ba86ebd923d8ba20dcdb6417f310bf66a2075 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 7 Feb 2020 22:21:56 +0530 Subject: [PATCH 17/67] Updated Transaction Meta Data logging & return false in case of failure --- src/qrl/core/TransactionMetadata.py | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/qrl/core/TransactionMetadata.py b/src/qrl/core/TransactionMetadata.py index a5036c57e..bade85928 100644 --- a/src/qrl/core/TransactionMetadata.py +++ b/src/qrl/core/TransactionMetadata.py @@ -2,6 +2,7 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +from qrl.core.misc import logger from qrl.core.State import State from qrl.core.LastTransactions import LastTransactions from qrl.core.txs.Transaction import Transaction @@ -46,7 +47,7 @@ def deserialize(data): return TransactionMetadata(pbdata) @staticmethod - def put_tx_metadata(state: State, txn: Transaction, block_number: int, timestamp: int, batch): + def put_tx_metadata(state: State, txn: Transaction, block_number: int, timestamp: int, batch) -> bool: try: tm = TransactionMetadata.create(tx=txn, block_number=block_number, @@ -55,7 +56,10 @@ def put_tx_metadata(state: State, txn: Transaction, block_number: int, timestamp tm.serialize(), batch) except Exception: - pass + logger.warning("Error writing tx metadata") + return False + + return True @staticmethod def get_tx_metadata(state: State, txhash: bytes): @@ -79,25 +83,31 @@ def rollback_tx_metadata(state: State, block, batch): LastTransactions._remove_last_tx(state, block, batch) @staticmethod - def update_tx_metadata(state: State, block, batch): + def update_tx_metadata(state: State, block, batch) -> bool: fee_reward = 0 - # TODO (cyyber): Move To State Cache, instead of writing directly + for protobuf_txn in block.transactions: txn = Transaction.from_pbdata(protobuf_txn) fee_reward += txn.fee - TransactionMetadata.put_tx_metadata(state, - txn, - block.block_number, - block.timestamp, - batch) + if not TransactionMetadata.put_tx_metadata(state, + txn, + block.block_number, + block.timestamp, + batch): + return False txn = Transaction.from_pbdata(block.transactions[0]) # Coinbase Transaction state._update_total_coin_supply(txn.amount - fee_reward, batch) LastTransactions._update_last_tx(state, block, batch) + return True + @staticmethod - def remove_tx_metadata(state: State, txn, batch): + def remove_tx_metadata(state: State, txn, batch) -> bool: try: state._db.delete(txn.txhash, batch) except KeyError: - pass + logger.warning("Error removing tx metadata") + return False + + return True From a69f31eab04a83cde29dfe7f74fbd4877fcc8d22 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 8 Feb 2020 18:22:30 +0530 Subject: [PATCH 18/67] Removed unused variable --- src/qrl/core/ChainManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 1406aa1af..073abdc7c 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -437,7 +437,6 @@ def load(self, genesis_block): logger.warning("Start blockheight %s", start_blocknumber) for block_number in range(start_blocknumber, height): block = state_migration.block_from_state_version_0(block_number) - dev_config = self.get_config_by_block_number(block_number) self.add_block(block, check_stale=False) if block_number % 1000 == 0: logger.warning("Migrated Block %s/%s", block_number, height) From bed3e7c1da6e29b9db37f13f52eb12a95eb5fa05 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 8 Feb 2020 18:22:44 +0530 Subject: [PATCH 19/67] Updated tests_integration --- tests_integration | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests_integration b/tests_integration index fc9793e07..e40df2e82 160000 --- a/tests_integration +++ b/tests_integration @@ -1 +1 @@ -Subproject commit fc9793e07aebb6480a294960537bcfbf130dee1d +Subproject commit e40df2e825dc87579c8d481e320f1a8088dd76c0 From effda9bc43e95e2219b70987a2f97b7bcf078e29 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sun, 9 Feb 2020 14:10:38 +0530 Subject: [PATCH 20/67] Updated re-org limit --- src/qrl/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index 8fe45f796..d8d9b32d8 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -478,7 +478,7 @@ def create(prev_state_key, current_block_number: int, ignore_check=False, ignore_singleton=False): - chain = qrl_pb2.DevConfig.Chain(reorg_limit=10, + chain = qrl_pb2.DevConfig.Chain(reorg_limit=300, max_coin_supply=105000000, complete_emission_time_span_in_years=200) block_size_controller = qrl_pb2.DevConfig.Block.BlockSizeController(number_of_blocks_analyze=10, From a7edd5280f33e7cae8b538f63d412483009cb045 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sun, 9 Feb 2020 16:45:49 +0530 Subject: [PATCH 21/67] Added Comment for StateMigration --- src/qrl/core/StateMigration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qrl/core/StateMigration.py b/src/qrl/core/StateMigration.py index 82532f4ee..727c5fc37 100644 --- a/src/qrl/core/StateMigration.py +++ b/src/qrl/core/StateMigration.py @@ -18,8 +18,8 @@ def state_migration_step_1(self, state: State) -> bool: """ if state.is_older_state_version(): db_dir_v1 = os.path.join(config.user.data_dir, config.dev.db_name + '2') - self._tmp_state = State(state._db) - state._db = db.DB(db_dir_v1) + self._tmp_state = State(state._db) # DB Pointing to Older State + state._db = db.DB(db_dir_v1) # DB Pointing to Newer State return True return False From a424d843e7f5ab1a302a0c9e7e62b92fb227a502 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sun, 9 Feb 2020 16:46:02 +0530 Subject: [PATCH 22/67] Fix for State migration --- src/qrl/core/ChainManager.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 073abdc7c..4bc0205b1 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -1,6 +1,7 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import sys import threading from typing import Optional, Tuple from math import ceil @@ -433,11 +434,13 @@ def load(self, genesis_block): if is_state_migration_needed: logger.warning("Please Wait... Starting State Migration From Version 0 to %s", self._state.state_version) height = state_migration.height_from_state_version_0() - start_blocknumber = self._state.get_mainchain_height() + 1 - logger.warning("Start blockheight %s", start_blocknumber) - for block_number in range(start_blocknumber, height): + start_block_number = self._state.get_mainchain_height() + 1 + logger.warning("Start blockheight %s", start_block_number) + for block_number in range(start_block_number, height + 1): block = state_migration.block_from_state_version_0(block_number) - self.add_block(block, check_stale=False) + if not self.add_block(block, check_stale=False): + print("System Exitting, due to migration failure") + sys.exit(1) if block_number % 1000 == 0: logger.warning("Migrated Block %s/%s", block_number, height) @@ -445,7 +448,6 @@ def load(self, genesis_block): logger.warning("Migrated Block %s/%s", self.height, height) state_migration.state_migration_step_2(self._state) - # TODO: Update re-org limit when dev_config is updated def _update_chainstate(self, block: Block, batch): self._last_block = block self._update_block_number_mapping(block, batch) @@ -664,10 +666,12 @@ def add_block(self, block: Block, check_stale=True) -> bool: return False if self.get_block_is_duplicate(block): + logger.warning("Duplicate Block found #%s", block.block_number) return False block_flag = self._add_block(block, check_stale=check_stale) if not block_flag: + logger.warning("[ChainManager] Failed to Add Block #%s", block.block_number) return False logger.info('Added Block #%s %s', block.block_number, bin2hstr(block.headerhash)) From 4a14adfd1bc2b78778fc0e87b877399e3fcf416a Mon Sep 17 00:00:00 2001 From: cyyber Date: Sun, 9 Feb 2020 16:46:13 +0530 Subject: [PATCH 23/67] Fix: mock get_measurement in ChainManager when measurement is passed as argument --- src/qrl/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qrl/main.py b/src/qrl/main.py index 3e5f3886a..027ffc1c9 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -102,10 +102,10 @@ def main(): logger.warning('%s', args.mining_address) return False + chain_manager = ChainManager(state=persistent_state) if args.measurement > -1: - persistent_state.get_measurement = MagicMock(return_value=args.measurement) + chain_manager.get_measurement = MagicMock(return_value=args.measurement) - chain_manager = ChainManager(state=persistent_state) chain_manager.load(Block.deserialize(GenesisBlock().serialize())) qrlnode = QRLNode(mining_address=mining_address) From 200efde3699679ba10b2ed894e6114d153c43a68 Mon Sep 17 00:00:00 2001 From: cyyber Date: Tue, 11 Feb 2020 14:45:05 +0530 Subject: [PATCH 24/67] Updated docker container for CI to qrl-docker-ci --- .circleci/config.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fde903a36..c81fe0372 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial steps: - checkout - run: pip install -U setuptools @@ -14,7 +14,7 @@ jobs: test_leaks_CLI: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial steps: - checkout - run: pip install -U setuptools @@ -25,7 +25,7 @@ jobs: flake8: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial steps: - checkout - run: pip install -U setuptools @@ -33,7 +33,7 @@ jobs: test_leaks_other: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial steps: - checkout - run: pip install -U setuptools @@ -44,7 +44,7 @@ jobs: build_trusty: docker: - - image: qrledger/qrl-docker:trusty + - image: qrledger/qrl-docker-ci:trusty steps: - checkout - run: pip install -U setuptools @@ -55,7 +55,7 @@ jobs: build_bionic: docker: - - image: qrledger/qrl-docker:bionic + - image: qrledger/qrl-docker-ci:bionic steps: - checkout - run: pip install -U setuptools @@ -65,7 +65,7 @@ jobs: integration_fast: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial environment: PYTHONPATH: /root/project:/root/project/tests_integration TESTINPLACE: 1 @@ -79,7 +79,7 @@ jobs: integration_smoke: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial environment: PYTHONPATH: /root/project:/root/project/tests_integration TESTINPLACE: 1 @@ -95,7 +95,7 @@ jobs: integration_fuzzing: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial environment: PYTHONPATH: /root/project:/root/project/tests_integration TESTINPLACE: 1 @@ -109,7 +109,7 @@ jobs: deploy-pypi: docker: - - image: qrledger/qrl-docker:xenial + - image: qrledger/qrl-docker-ci:xenial steps: - checkout - run: git submodule update --init --recursive From a61c0f25687b711e0316e23939422a0c5583e6cf Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 12 Feb 2020 15:21:10 +0530 Subject: [PATCH 25/67] Updated qrl.proto and added function to derive older address state format --- src/qrl/core/AddressState.py | 3 + src/qrl/core/ChainManager.py | 45 +- src/qrl/core/State.py | 12 + src/qrl/core/qrlnode.py | 11 +- src/qrl/generated/qrl_pb2.py | 655 ++++++++++++++------------- src/qrl/generated/qrl_pb2_grpc.py | 16 + src/qrl/protos/qrl.proto | 6 + src/qrl/services/PublicAPIService.py | 13 +- 8 files changed, 451 insertions(+), 310 deletions(-) diff --git a/src/qrl/core/AddressState.py b/src/qrl/core/AddressState.py index dad7e3c76..d51d81afc 100644 --- a/src/qrl/core/AddressState.py +++ b/src/qrl/core/AddressState.py @@ -231,6 +231,9 @@ def address_is_valid(address: bytes) -> bool: if not QRLHelper.addressIsValid(address): return False + if address[0:1] == b'\x11': + return False + return True def serialize(self): diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 4bc0205b1..e1a385c63 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -100,8 +100,47 @@ def get_address_is_used(self, address: bytes) -> bool: return self._state.get_address_is_used(address) def get_address_state(self, address: bytes) -> AddressState: - with self.lock: - return AddressState.get_address_state(self._state, address) + """ + Transform Optimized Address State into Older Address State format + """ + optimized_address_state = self.get_optimized_address_state(address) + ots_bitfield = [b'\x00'] * int(ceil((2 ** optimized_address_state.height) / 8)) + tokens = dict() + slave_pks_access_type = dict() + + max_bitfield_page = (2 ** optimized_address_state.height) // config.dev.ots_tracking_per_page + + offset = 0 + for page in range(1, max_bitfield_page + 1): + page_data = self.get_bitfield(address, page) + for data in page_data: + ots_bitfield[offset] = data + offset += 1 + offset = (page - 1) * config.dev.ots_tracking_per_page + + for page in range(1, optimized_address_state.tokens_count() + 1): + page_data = self.get_token_transaction_hashes(address, page) + for token_txn_hash in page_data: + token_balance = self.get_token(address, token_txn_hash) + tokens[token_txn_hash] = token_balance.balance + + for page in range(1, optimized_address_state.slaves_count() + 1): + page_data = self.get_slave_transaction_hashes(address, page) + for slave_txn_hash in page_data: + tx, _ = self.get_tx_metadata(slave_txn_hash) + for slave_pk in tx.slave_pks: + slave_meta_data = self.get_slave_pk_access_type(address, slave_pk) + slave_pks_access_type[slave_pk] = slave_meta_data.access_type + + addr_state = AddressState.create(address=optimized_address_state.address, + nonce=optimized_address_state.nonce, + balance=optimized_address_state.balance, + ots_bitfield=ots_bitfield, + tokens=tokens, + slave_pks_access_type=slave_pks_access_type, + ots_counter=0) + + return addr_state def get_optimized_address_state(self, address: bytes) -> OptimizedAddressState: with self.lock: @@ -161,7 +200,7 @@ def get_vote_stats(self, multi_sig_spend_txn_hash: bytes): with self.lock: return VoteStats.get_state(state=self._state, shared_key=multi_sig_spend_txn_hash) - def get_token(self, address: bytes, token_txhash: bytes) -> list: + def get_token(self, address: bytes, token_txhash: bytes) -> qrl_pb2.TokenBalance: with self.lock: return self._state.get_token(address, token_txhash) diff --git a/src/qrl/core/State.py b/src/qrl/core/State.py index 0817e0e88..c9cf10c7a 100644 --- a/src/qrl/core/State.py +++ b/src/qrl/core/State.py @@ -201,3 +201,15 @@ def get_slave_pk_access_type(self, address: bytes, slave_pk: bytes) -> qrl_pb2.S logger.error('[get_slave_pk_access_type] %s', e) return None + + def get_token(self, address: bytes, token_txhash: bytes) -> qrl_pb2.TokenBalance: + try: + token_balance = qrl_pb2.TokenBalance() + token_balance.ParseFromString(self._db.get_raw(self.generate_token_key(address, token_txhash))) + return token_balance + except KeyError: + pass + except Exception as e: + logger.error('[get_token] %s', e) + + return None diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 63cad4279..289bddd58 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -8,6 +8,7 @@ from twisted.internet import reactor from qrl.core import config +from qrl.core.AddressState import AddressState from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.MultiSigAddressState import MultiSigAddressState from qrl.core.Block import Block @@ -377,7 +378,15 @@ def get_address_is_used(self, address: bytes) -> bool: return self._chain_manager.get_address_is_used(address) - def get_address_state(self, address: bytes) -> OptimizedAddressState: + def get_address_state(self, address: bytes) -> AddressState: + if address != config.dev.coinbase_address and not AddressState.address_is_valid(address): + raise ValueError("Invalid Address") + + address_state = self._chain_manager.get_address_state(address) + + return address_state + + def get_optimized_address_state(self, address: bytes) -> OptimizedAddressState: if address != config.dev.coinbase_address and not OptimizedAddressState.address_is_valid(address): raise ValueError("Invalid Address") diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index 6f3aa15c8..38368bc88 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"@\n\x13GetAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"F\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\x9b\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"F\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -49,8 +49,8 @@ ], containing_type=None, options=None, - serialized_start=1759, - serialized_end=1842, + serialized_start=1825, + serialized_end=1908, ) _sym_db.RegisterEnumDescriptor(_GETLATESTDATAREQ_FILTER) @@ -79,8 +79,8 @@ ], containing_type=None, options=None, - serialized_start=2436, - serialized_end=2512, + serialized_start=2502, + serialized_end=2578, ) _sym_db.RegisterEnumDescriptor(_PUSHTRANSACTIONRESP_RESPONSECODE) @@ -121,8 +121,8 @@ ], containing_type=None, options=None, - serialized_start=4382, - serialized_end=4527, + serialized_start=4448, + serialized_end=4593, ) _sym_db.RegisterEnumDescriptor(_GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE) @@ -155,8 +155,8 @@ ], containing_type=None, options=None, - serialized_start=6230, - serialized_end=6301, + serialized_start=6296, + serialized_end=6367, ) _sym_db.RegisterEnumDescriptor(_NODEINFO_STATE) @@ -758,7 +758,38 @@ oneofs=[ ], serialized_start=1051, - serialized_end=1115, + serialized_end=1106, +) + + +_GETOPTIMIZEDADDRESSSTATERESP = _descriptor.Descriptor( + name='GetOptimizedAddressStateResp', + full_name='qrl.GetOptimizedAddressStateResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='state', full_name='qrl.GetOptimizedAddressStateResp.state', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1108, + serialized_end=1181, ) @@ -788,8 +819,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1117, - serialized_end=1162, + serialized_start=1183, + serialized_end=1228, ) @@ -819,8 +850,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1164, - serialized_end=1235, + serialized_start=1230, + serialized_end=1301, ) @@ -857,8 +888,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1237, - serialized_end=1291, + serialized_start=1303, + serialized_end=1357, ) @@ -888,8 +919,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1293, - serialized_end=1322, + serialized_start=1359, + serialized_end=1388, ) @@ -919,8 +950,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1324, - serialized_end=1358, + serialized_start=1390, + serialized_end=1424, ) @@ -957,8 +988,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1360, - serialized_end=1434, + serialized_start=1426, + serialized_end=1500, ) @@ -988,8 +1019,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1436, - serialized_end=1465, + serialized_start=1502, + serialized_end=1531, ) @@ -1043,8 +1074,8 @@ name='result', full_name='qrl.GetObjectResp.result', index=0, containing_type=None, fields=[]), ], - serialized_start=1468, - serialized_end=1656, + serialized_start=1534, + serialized_end=1722, ) @@ -1089,8 +1120,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1659, - serialized_end=1842, + serialized_start=1725, + serialized_end=1908, ) @@ -1134,8 +1165,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1845, - serialized_end=2020, + serialized_start=1911, + serialized_end=2086, ) @@ -1200,8 +1231,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2023, - serialized_end=2153, + serialized_start=2089, + serialized_end=2219, ) @@ -1231,8 +1262,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2155, - serialized_end=2239, + serialized_start=2221, + serialized_end=2305, ) @@ -1262,8 +1293,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2241, - serialized_end=2307, + serialized_start=2307, + serialized_end=2373, ) @@ -1308,8 +1339,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2310, - serialized_end=2512, + serialized_start=2376, + serialized_end=2578, ) @@ -1374,8 +1405,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2515, - serialized_end=2645, + serialized_start=2581, + serialized_end=2711, ) @@ -1447,8 +1478,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2648, - serialized_end=2811, + serialized_start=2714, + serialized_end=2877, ) @@ -1506,8 +1537,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2813, - serialized_end=2920, + serialized_start=2879, + serialized_end=2986, ) @@ -1565,8 +1596,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2922, - serialized_end=3022, + serialized_start=2988, + serialized_end=3088, ) @@ -1645,8 +1676,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3025, - serialized_end=3198, + serialized_start=3091, + serialized_end=3264, ) @@ -1711,8 +1742,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3201, - serialized_end=3334, + serialized_start=3267, + serialized_end=3400, ) @@ -1770,8 +1801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3336, - serialized_end=3441, + serialized_start=3402, + serialized_end=3507, ) @@ -1843,8 +1874,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3443, - serialized_end=3561, + serialized_start=3509, + serialized_end=3627, ) @@ -1888,8 +1919,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3563, - serialized_end=3635, + serialized_start=3629, + serialized_end=3701, ) @@ -1919,8 +1950,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3637, - serialized_end=3673, + serialized_start=3703, + serialized_end=3739, ) @@ -1985,8 +2016,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3676, - serialized_end=3836, + serialized_start=3742, + serialized_end=3902, ) @@ -2030,8 +2061,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3838, - serialized_end=3932, + serialized_start=3904, + serialized_end=3998, ) @@ -2068,8 +2099,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3934, - serialized_end=4034, + serialized_start=4000, + serialized_end=4100, ) @@ -2113,8 +2144,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4036, - serialized_end=4126, + serialized_start=4102, + serialized_end=4192, ) @@ -2144,8 +2175,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4128, - serialized_end=4212, + serialized_start=4194, + serialized_end=4278, ) @@ -2197,8 +2228,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4215, - serialized_end=4527, + serialized_start=4281, + serialized_end=4593, ) @@ -2228,8 +2259,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4529, - serialized_end=4617, + serialized_start=4595, + serialized_end=4683, ) @@ -2259,8 +2290,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4619, - serialized_end=4669, + serialized_start=4685, + serialized_end=4735, ) @@ -2290,8 +2321,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4671, - serialized_end=4725, + serialized_start=4737, + serialized_end=4791, ) @@ -2342,8 +2373,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4727, - serialized_end=4809, + serialized_start=4793, + serialized_end=4875, ) @@ -2373,8 +2404,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4811, - serialized_end=4876, + serialized_start=4877, + serialized_end=4942, ) @@ -2411,8 +2442,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4878, - serialized_end=4935, + serialized_start=4944, + serialized_end=5001, ) @@ -2442,8 +2473,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4937, - serialized_end=5002, + serialized_start=5003, + serialized_end=5068, ) @@ -2494,8 +2525,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5004, - serialized_end=5074, + serialized_start=5070, + serialized_end=5140, ) @@ -2525,8 +2556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5076, - serialized_end=5155, + serialized_start=5142, + serialized_end=5221, ) @@ -2563,8 +2594,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5157, - serialized_end=5207, + serialized_start=5223, + serialized_end=5273, ) @@ -2594,8 +2625,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5209, - serialized_end=5291, + serialized_start=5275, + serialized_end=5357, ) @@ -2625,8 +2656,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5293, - serialized_end=5325, + serialized_start=5359, + serialized_end=5391, ) @@ -2656,8 +2687,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5327, - serialized_end=5360, + serialized_start=5393, + serialized_end=5426, ) @@ -2687,8 +2718,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5362, - serialized_end=5401, + serialized_start=5428, + serialized_end=5467, ) @@ -2718,8 +2749,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5403, - serialized_end=5441, + serialized_start=5469, + serialized_end=5507, ) @@ -2770,8 +2801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5443, - serialized_end=5541, + serialized_start=5509, + serialized_end=5607, ) @@ -2808,8 +2839,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5543, - serialized_end=5605, + serialized_start=5609, + serialized_end=5671, ) @@ -2853,8 +2884,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5608, - serialized_end=5737, + serialized_start=5674, + serialized_end=5803, ) @@ -2877,8 +2908,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5739, - serialized_end=5753, + serialized_start=5805, + serialized_end=5819, ) @@ -2908,8 +2939,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5755, - serialized_end=5786, + serialized_start=5821, + serialized_end=5852, ) @@ -2939,8 +2970,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5788, - serialized_end=5822, + serialized_start=5854, + serialized_end=5888, ) @@ -2970,8 +3001,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5824, - serialized_end=5865, + serialized_start=5890, + serialized_end=5931, ) @@ -3001,8 +3032,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5867, - serialized_end=5910, + serialized_start=5933, + serialized_end=5976, ) @@ -3032,8 +3063,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5912, - serialized_end=5961, + serialized_start=5978, + serialized_end=6027, ) @@ -3056,8 +3087,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5963, - serialized_end=5985, + serialized_start=6029, + serialized_end=6051, ) @@ -3087,8 +3118,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5987, - serialized_end=6029, + serialized_start=6053, + serialized_end=6095, ) @@ -3168,8 +3199,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6032, - serialized_end=6301, + serialized_start=6098, + serialized_end=6367, ) @@ -3227,8 +3258,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6304, - serialized_end=6437, + serialized_start=6370, + serialized_end=6503, ) @@ -3258,8 +3289,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6439, - serialized_end=6478, + serialized_start=6505, + serialized_end=6544, ) @@ -3289,8 +3320,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6480, - serialized_end=6498, + serialized_start=6546, + serialized_end=6564, ) @@ -3327,8 +3358,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6798, - serialized_end=6843, + serialized_start=6864, + serialized_end=6909, ) _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( @@ -3364,8 +3395,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6845, - serialized_end=6902, + serialized_start=6911, + serialized_end=6968, ) _ADDRESSSTATE = _descriptor.Descriptor( @@ -3450,8 +3481,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6501, - serialized_end=6902, + serialized_start=6567, + serialized_end=6968, ) @@ -3579,8 +3610,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6905, - serialized_end=7356, + serialized_start=6971, + serialized_end=7422, ) @@ -3701,8 +3732,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7359, - serialized_end=7762, + serialized_start=7425, + serialized_end=7828, ) @@ -3732,8 +3763,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7764, - serialized_end=7803, + serialized_start=7830, + serialized_end=7869, ) @@ -3763,8 +3794,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7805, - serialized_end=7831, + serialized_start=7871, + serialized_end=7897, ) @@ -3794,8 +3825,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7833, - serialized_end=7862, + serialized_start=7899, + serialized_end=7928, ) @@ -3825,8 +3856,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7864, - serialized_end=7901, + serialized_start=7930, + serialized_end=7967, ) @@ -3863,8 +3894,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7903, - serialized_end=7954, + serialized_start=7969, + serialized_end=8020, ) @@ -3901,8 +3932,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7956, - serialized_end=8004, + serialized_start=8022, + serialized_end=8070, ) @@ -3988,8 +4019,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8007, - serialized_end=8222, + serialized_start=8073, + serialized_end=8288, ) @@ -4026,8 +4057,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8224, - serialized_end=8329, + serialized_start=8290, + serialized_end=8395, ) @@ -4064,8 +4095,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8400, - serialized_end=8444, + serialized_start=8466, + serialized_end=8510, ) _TRANSACTIONCOUNT = _descriptor.Descriptor( @@ -4094,8 +4125,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8331, - serialized_end=8444, + serialized_start=8397, + serialized_end=8510, ) @@ -4153,8 +4184,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8447, - serialized_end=8592, + serialized_start=8513, + serialized_end=8658, ) @@ -4205,8 +4236,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8595, - serialized_end=8761, + serialized_start=8661, + serialized_end=8827, ) @@ -4250,8 +4281,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8763, - serialized_end=8890, + serialized_start=8829, + serialized_end=8956, ) @@ -4288,8 +4319,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8892, - serialized_end=8942, + serialized_start=8958, + serialized_end=9008, ) @@ -4319,8 +4350,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8944, - serialized_end=9012, + serialized_start=9010, + serialized_end=9078, ) @@ -4364,8 +4395,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9772, - serialized_end=9839, + serialized_start=9838, + serialized_end=9905, ) _TRANSACTION_COINBASE = _descriptor.Descriptor( @@ -4401,8 +4432,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9841, - serialized_end=9884, + serialized_start=9907, + serialized_end=9950, ) _TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -4452,8 +4483,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9886, - serialized_end=9956, + serialized_start=9952, + serialized_end=10022, ) _TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -4489,8 +4520,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9958, - serialized_end=10006, + serialized_start=10024, + serialized_end=10072, ) _TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -4547,8 +4578,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10008, - serialized_end=10124, + serialized_start=10074, + serialized_end=10190, ) _TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -4591,8 +4622,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10126, - serialized_end=10198, + serialized_start=10192, + serialized_end=10264, ) _TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -4628,8 +4659,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10200, - serialized_end=10248, + serialized_start=10266, + serialized_end=10314, ) _TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( @@ -4672,8 +4703,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10250, - serialized_end=10323, + serialized_start=10316, + serialized_end=10389, ) _TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( @@ -4723,8 +4754,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10325, - serialized_end=10431, + serialized_start=10391, + serialized_end=10497, ) _TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( @@ -4767,8 +4798,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10433, - serialized_end=10505, + serialized_start=10499, + serialized_end=10571, ) _TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( @@ -4797,8 +4828,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10742, - serialized_end=10765, + serialized_start=10808, + serialized_end=10831, ) _TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( @@ -5016,8 +5047,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10768, - serialized_end=11677, + serialized_start=10834, + serialized_end=11743, ) _TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( @@ -5046,8 +5077,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11679, - serialized_end=11703, + serialized_start=11745, + serialized_end=11769, ) _TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( @@ -5107,8 +5138,8 @@ name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', index=0, containing_type=None, fields=[]), ], - serialized_start=10508, - serialized_end=11719, + serialized_start=10574, + serialized_end=11785, ) _TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( @@ -5144,8 +5175,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11721, - serialized_end=11771, + serialized_start=11787, + serialized_end=11837, ) _TRANSACTION = _descriptor.Descriptor( @@ -5296,8 +5327,8 @@ name='transactionType', full_name='qrl.Transaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=9015, - serialized_end=11790, + serialized_start=9081, + serialized_end=11856, ) @@ -5376,8 +5407,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11793, - serialized_end=11977, + serialized_start=11859, + serialized_end=12043, ) @@ -5449,8 +5480,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11980, - serialized_end=12163, + serialized_start=12046, + serialized_end=12229, ) @@ -5480,8 +5511,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12165, - serialized_end=12210, + serialized_start=12231, + serialized_end=12276, ) @@ -5511,8 +5542,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12212, - serialized_end=12245, + serialized_start=12278, + serialized_end=12311, ) @@ -5556,8 +5587,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12247, - serialized_end=12312, + serialized_start=12313, + serialized_end=12378, ) @@ -5601,8 +5632,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12314, - serialized_end=12383, + serialized_start=12380, + serialized_end=12449, ) @@ -5646,8 +5677,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12385, - serialized_end=12454, + serialized_start=12451, + serialized_end=12520, ) @@ -5684,8 +5715,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12456, - serialized_end=12527, + serialized_start=12522, + serialized_end=12593, ) @@ -5715,8 +5746,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12690, - serialized_end=12726, + serialized_start=12756, + serialized_end=12792, ) _ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( @@ -5780,8 +5811,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12530, - serialized_end=12726, + serialized_start=12596, + serialized_end=12792, ) @@ -5811,8 +5842,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12728, - serialized_end=12760, + serialized_start=12794, + serialized_end=12826, ) @@ -5856,8 +5887,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12762, - serialized_end=12858, + serialized_start=12828, + serialized_end=12924, ) @@ -5908,8 +5939,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12861, - serialized_end=12990, + serialized_start=12927, + serialized_end=13056, ) @@ -5946,8 +5977,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12992, - serialized_end=13057, + serialized_start=13058, + serialized_end=13123, ) @@ -5991,8 +6022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13059, - serialized_end=13147, + serialized_start=13125, + serialized_end=13213, ) @@ -6050,8 +6081,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13149, - serialized_end=13275, + serialized_start=13215, + serialized_end=13341, ) @@ -6088,8 +6119,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13277, - serialized_end=13337, + serialized_start=13343, + serialized_end=13403, ) @@ -6119,8 +6150,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13339, - serialized_end=13384, + serialized_start=13405, + serialized_end=13450, ) @@ -6178,8 +6209,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13386, - serialized_end=13510, + serialized_start=13452, + serialized_end=13576, ) @@ -6209,8 +6240,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13512, - serialized_end=13558, + serialized_start=13578, + serialized_end=13624, ) @@ -6254,8 +6285,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13846, - serialized_end=13945, + serialized_start=13912, + serialized_end=14011, ) _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( @@ -6298,8 +6329,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14155, - serialized_end=14274, + serialized_start=14221, + serialized_end=14340, ) _DEVCONFIG_BLOCK = _descriptor.Descriptor( @@ -6356,8 +6387,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13948, - serialized_end=14274, + serialized_start=14014, + serialized_end=14340, ) _DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -6386,8 +6417,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14656, - serialized_end=14685, + serialized_start=14722, + serialized_end=14751, ) _DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -6416,8 +6447,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14687, - serialized_end=14723, + serialized_start=14753, + serialized_end=14789, ) _DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -6453,8 +6484,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14725, - serialized_end=14784, + serialized_start=14791, + serialized_end=14850, ) _DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( @@ -6504,8 +6535,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14786, - serialized_end=14891, + serialized_start=14852, + serialized_end=14957, ) _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( @@ -6534,8 +6565,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14893, - serialized_end=14943, + serialized_start=14959, + serialized_end=15009, ) _DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( @@ -6599,8 +6630,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14946, - serialized_end=15138, + serialized_start=15012, + serialized_end=15204, ) _DEVCONFIG_TRANSACTION = _descriptor.Descriptor( @@ -6671,8 +6702,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14277, - serialized_end=15138, + serialized_start=14343, + serialized_end=15204, ) _DEVCONFIG_POW = _descriptor.Descriptor( @@ -6708,8 +6739,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15140, - serialized_end=15180, + serialized_start=15206, + serialized_end=15246, ) _DEVCONFIG = _descriptor.Descriptor( @@ -6787,8 +6818,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13561, - serialized_end=15180, + serialized_start=13627, + serialized_end=15246, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -6797,7 +6828,8 @@ _GETPEERSSTATRESP.fields_by_name['peers_stat'].message_type = _PEERSTAT _GETSTATSRESP.fields_by_name['node_info'].message_type = _NODEINFO _GETSTATSRESP.fields_by_name['block_timeseries'].message_type = _BLOCKDATAPOINT -_GETADDRESSSTATERESP.fields_by_name['state'].message_type = _OPTIMIZEDADDRESSSTATE +_GETADDRESSSTATERESP.fields_by_name['state'].message_type = _ADDRESSSTATE +_GETOPTIMIZEDADDRESSSTATERESP.fields_by_name['state'].message_type = _OPTIMIZEDADDRESSSTATE _GETMULTISIGADDRESSSTATERESP.fields_by_name['state'].message_type = _MULTISIGADDRESSSTATE _PARSEADDRESSRESP.fields_by_name['desc'].message_type = _ADDRESSDESCRIPTOR _GETOBJECTRESP.fields_by_name['address_state'].message_type = _OPTIMIZEDADDRESSSTATE @@ -6977,6 +7009,7 @@ DESCRIPTOR.message_types_by_name['BlockDataPoint'] = _BLOCKDATAPOINT DESCRIPTOR.message_types_by_name['GetAddressStateReq'] = _GETADDRESSSTATEREQ DESCRIPTOR.message_types_by_name['GetAddressStateResp'] = _GETADDRESSSTATERESP +DESCRIPTOR.message_types_by_name['GetOptimizedAddressStateResp'] = _GETOPTIMIZEDADDRESSSTATERESP DESCRIPTOR.message_types_by_name['GetMultiSigAddressStateReq'] = _GETMULTISIGADDRESSSTATEREQ DESCRIPTOR.message_types_by_name['GetMultiSigAddressStateResp'] = _GETMULTISIGADDRESSSTATERESP DESCRIPTOR.message_types_by_name['IsSlaveReq'] = _ISSLAVEREQ @@ -7189,6 +7222,13 @@ )) _sym_db.RegisterMessage(GetAddressStateResp) +GetOptimizedAddressStateResp = _reflection.GeneratedProtocolMessageType('GetOptimizedAddressStateResp', (_message.Message,), dict( + DESCRIPTOR = _GETOPTIMIZEDADDRESSSTATERESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetOptimizedAddressStateResp) + )) +_sym_db.RegisterMessage(GetOptimizedAddressStateResp) + GetMultiSigAddressStateReq = _reflection.GeneratedProtocolMessageType('GetMultiSigAddressStateReq', (_message.Message,), dict( DESCRIPTOR = _GETMULTISIGADDRESSSTATEREQ, __module__ = 'qrl_pb2' @@ -8129,8 +8169,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=15183, - serialized_end=17770, + serialized_start=15249, + serialized_end=17924, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -8177,10 +8217,19 @@ output_type=_GETADDRESSSTATERESP, options=None, ), + _descriptor.MethodDescriptor( + name='GetOptimizedAddressState', + full_name='qrl.PublicAPI.GetOptimizedAddressState', + index=5, + containing_service=None, + input_type=_GETADDRESSSTATEREQ, + output_type=_GETOPTIMIZEDADDRESSSTATERESP, + options=None, + ), _descriptor.MethodDescriptor( name='GetMultiSigAddressState', full_name='qrl.PublicAPI.GetMultiSigAddressState', - index=5, + index=6, containing_service=None, input_type=_GETMULTISIGADDRESSSTATEREQ, output_type=_GETMULTISIGADDRESSSTATERESP, @@ -8189,7 +8238,7 @@ _descriptor.MethodDescriptor( name='IsSlave', full_name='qrl.PublicAPI.IsSlave', - index=6, + index=7, containing_service=None, input_type=_ISSLAVEREQ, output_type=_ISSLAVERESP, @@ -8198,7 +8247,7 @@ _descriptor.MethodDescriptor( name='GetObject', full_name='qrl.PublicAPI.GetObject', - index=7, + index=8, containing_service=None, input_type=_GETOBJECTREQ, output_type=_GETOBJECTRESP, @@ -8207,7 +8256,7 @@ _descriptor.MethodDescriptor( name='GetLatestData', full_name='qrl.PublicAPI.GetLatestData', - index=8, + index=9, containing_service=None, input_type=_GETLATESTDATAREQ, output_type=_GETLATESTDATARESP, @@ -8216,7 +8265,7 @@ _descriptor.MethodDescriptor( name='PushTransaction', full_name='qrl.PublicAPI.PushTransaction', - index=9, + index=10, containing_service=None, input_type=_PUSHTRANSACTIONREQ, output_type=_PUSHTRANSACTIONRESP, @@ -8225,7 +8274,7 @@ _descriptor.MethodDescriptor( name='TransferCoins', full_name='qrl.PublicAPI.TransferCoins', - index=10, + index=11, containing_service=None, input_type=_TRANSFERCOINSREQ, output_type=_TRANSFERCOINSRESP, @@ -8234,7 +8283,7 @@ _descriptor.MethodDescriptor( name='ParseAddress', full_name='qrl.PublicAPI.ParseAddress', - index=11, + index=12, containing_service=None, input_type=_PARSEADDRESSREQ, output_type=_PARSEADDRESSRESP, @@ -8243,7 +8292,7 @@ _descriptor.MethodDescriptor( name='GetChainStats', full_name='qrl.PublicAPI.GetChainStats', - index=12, + index=13, containing_service=None, input_type=_GETCHAINSTATSREQ, output_type=_GETCHAINSTATSRESP, @@ -8252,7 +8301,7 @@ _descriptor.MethodDescriptor( name='GetAddressFromPK', full_name='qrl.PublicAPI.GetAddressFromPK', - index=13, + index=14, containing_service=None, input_type=_GETADDRESSFROMPKREQ, output_type=_GETADDRESSFROMPKRESP, @@ -8261,7 +8310,7 @@ _descriptor.MethodDescriptor( name='GetMultiSigCreateTxn', full_name='qrl.PublicAPI.GetMultiSigCreateTxn', - index=14, + index=15, containing_service=None, input_type=_MULTISIGCREATETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8270,7 +8319,7 @@ _descriptor.MethodDescriptor( name='GetMultiSigSpendTxn', full_name='qrl.PublicAPI.GetMultiSigSpendTxn', - index=15, + index=16, containing_service=None, input_type=_MULTISIGSPENDTXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8279,7 +8328,7 @@ _descriptor.MethodDescriptor( name='GetMultiSigVoteTxn', full_name='qrl.PublicAPI.GetMultiSigVoteTxn', - index=16, + index=17, containing_service=None, input_type=_MULTISIGVOTETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8288,7 +8337,7 @@ _descriptor.MethodDescriptor( name='GetMessageTxn', full_name='qrl.PublicAPI.GetMessageTxn', - index=17, + index=18, containing_service=None, input_type=_MESSAGETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8297,7 +8346,7 @@ _descriptor.MethodDescriptor( name='GetTokenTxn', full_name='qrl.PublicAPI.GetTokenTxn', - index=18, + index=19, containing_service=None, input_type=_TOKENTXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8306,7 +8355,7 @@ _descriptor.MethodDescriptor( name='GetTransferTokenTxn', full_name='qrl.PublicAPI.GetTransferTokenTxn', - index=19, + index=20, containing_service=None, input_type=_TRANSFERTOKENTXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8315,7 +8364,7 @@ _descriptor.MethodDescriptor( name='GetSlaveTxn', full_name='qrl.PublicAPI.GetSlaveTxn', - index=20, + index=21, containing_service=None, input_type=_SLAVETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8324,7 +8373,7 @@ _descriptor.MethodDescriptor( name='GetLatticeTxn', full_name='qrl.PublicAPI.GetLatticeTxn', - index=21, + index=22, containing_service=None, input_type=_LATTICETXNREQ, output_type=_TRANSFERCOINSRESP, @@ -8333,7 +8382,7 @@ _descriptor.MethodDescriptor( name='GetTransaction', full_name='qrl.PublicAPI.GetTransaction', - index=22, + index=23, containing_service=None, input_type=_GETTRANSACTIONREQ, output_type=_GETTRANSACTIONRESP, @@ -8342,7 +8391,7 @@ _descriptor.MethodDescriptor( name='GetMiniTransactionsByAddress', full_name='qrl.PublicAPI.GetMiniTransactionsByAddress', - index=23, + index=24, containing_service=None, input_type=_GETMINITRANSACTIONSBYADDRESSREQ, output_type=_GETMINITRANSACTIONSBYADDRESSRESP, @@ -8351,7 +8400,7 @@ _descriptor.MethodDescriptor( name='GetTransactionsByAddress', full_name='qrl.PublicAPI.GetTransactionsByAddress', - index=24, + index=25, containing_service=None, input_type=_GETTRANSACTIONSBYADDRESSREQ, output_type=_GETTRANSACTIONSBYADDRESSRESP, @@ -8360,7 +8409,7 @@ _descriptor.MethodDescriptor( name='GetTokensByAddress', full_name='qrl.PublicAPI.GetTokensByAddress', - index=25, + index=26, containing_service=None, input_type=_GETTRANSACTIONSBYADDRESSREQ, output_type=_GETTOKENSBYADDRESSRESP, @@ -8369,7 +8418,7 @@ _descriptor.MethodDescriptor( name='GetSlavesByAddress', full_name='qrl.PublicAPI.GetSlavesByAddress', - index=26, + index=27, containing_service=None, input_type=_GETTRANSACTIONSBYADDRESSREQ, output_type=_GETSLAVESBYADDRESSRESP, @@ -8378,7 +8427,7 @@ _descriptor.MethodDescriptor( name='GetLatticePKsByAddress', full_name='qrl.PublicAPI.GetLatticePKsByAddress', - index=27, + index=28, containing_service=None, input_type=_GETTRANSACTIONSBYADDRESSREQ, output_type=_GETLATTICEPKSBYADDRESSRESP, @@ -8387,7 +8436,7 @@ _descriptor.MethodDescriptor( name='GetMultiSigAddressesByAddress', full_name='qrl.PublicAPI.GetMultiSigAddressesByAddress', - index=28, + index=29, containing_service=None, input_type=_GETTRANSACTIONSBYADDRESSREQ, output_type=_GETMULTISIGADDRESSESBYADDRESSRESP, @@ -8396,7 +8445,7 @@ _descriptor.MethodDescriptor( name='GetMultiSigSpendTxsByAddress', full_name='qrl.PublicAPI.GetMultiSigSpendTxsByAddress', - index=29, + index=30, containing_service=None, input_type=_GETMULTISIGSPENDTXSBYADDRESSREQ, output_type=_GETMULTISIGSPENDTXSBYADDRESSRESP, @@ -8405,7 +8454,7 @@ _descriptor.MethodDescriptor( name='GetVoteStats', full_name='qrl.PublicAPI.GetVoteStats', - index=30, + index=31, containing_service=None, input_type=_GETVOTESTATSREQ, output_type=_GETVOTESTATSRESP, @@ -8414,7 +8463,7 @@ _descriptor.MethodDescriptor( name='GetBalance', full_name='qrl.PublicAPI.GetBalance', - index=31, + index=32, containing_service=None, input_type=_GETBALANCEREQ, output_type=_GETBALANCERESP, @@ -8423,7 +8472,7 @@ _descriptor.MethodDescriptor( name='GetTotalBalance', full_name='qrl.PublicAPI.GetTotalBalance', - index=32, + index=33, containing_service=None, input_type=_GETTOTALBALANCEREQ, output_type=_GETTOTALBALANCERESP, @@ -8432,7 +8481,7 @@ _descriptor.MethodDescriptor( name='GetOTS', full_name='qrl.PublicAPI.GetOTS', - index=33, + index=34, containing_service=None, input_type=_GETOTSREQ, output_type=_GETOTSRESP, @@ -8441,7 +8490,7 @@ _descriptor.MethodDescriptor( name='GetHeight', full_name='qrl.PublicAPI.GetHeight', - index=34, + index=35, containing_service=None, input_type=_GETHEIGHTREQ, output_type=_GETHEIGHTRESP, @@ -8450,7 +8499,7 @@ _descriptor.MethodDescriptor( name='GetBlock', full_name='qrl.PublicAPI.GetBlock', - index=35, + index=36, containing_service=None, input_type=_GETBLOCKREQ, output_type=_GETBLOCKRESP, @@ -8459,7 +8508,7 @@ _descriptor.MethodDescriptor( name='GetBlockByNumber', full_name='qrl.PublicAPI.GetBlockByNumber', - index=36, + index=37, containing_service=None, input_type=_GETBLOCKBYNUMBERREQ, output_type=_GETBLOCKBYNUMBERRESP, @@ -8477,8 +8526,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=17772, - serialized_end=17782, + serialized_start=17926, + serialized_end=17936, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/generated/qrl_pb2_grpc.py b/src/qrl/generated/qrl_pb2_grpc.py index 0337bc44f..016e8925d 100644 --- a/src/qrl/generated/qrl_pb2_grpc.py +++ b/src/qrl/generated/qrl_pb2_grpc.py @@ -47,6 +47,11 @@ def __init__(self, channel): request_serializer=qrl__pb2.GetAddressStateReq.SerializeToString, response_deserializer=qrl__pb2.GetAddressStateResp.FromString, ) + self.GetOptimizedAddressState = channel.unary_unary( + '/qrl.PublicAPI/GetOptimizedAddressState', + request_serializer=qrl__pb2.GetAddressStateReq.SerializeToString, + response_deserializer=qrl__pb2.GetOptimizedAddressStateResp.FromString, + ) self.GetMultiSigAddressState = channel.unary_unary( '/qrl.PublicAPI/GetMultiSigAddressState', request_serializer=qrl__pb2.GetMultiSigAddressStateReq.SerializeToString, @@ -251,6 +256,12 @@ def GetAddressState(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def GetOptimizedAddressState(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def GetMultiSigAddressState(self, request, context): # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -471,6 +482,11 @@ def add_PublicAPIServicer_to_server(servicer, server): request_deserializer=qrl__pb2.GetAddressStateReq.FromString, response_serializer=qrl__pb2.GetAddressStateResp.SerializeToString, ), + 'GetOptimizedAddressState': grpc.unary_unary_rpc_method_handler( + servicer.GetOptimizedAddressState, + request_deserializer=qrl__pb2.GetAddressStateReq.FromString, + response_serializer=qrl__pb2.GetOptimizedAddressStateResp.SerializeToString, + ), 'GetMultiSigAddressState': grpc.unary_unary_rpc_method_handler( servicer.GetMultiSigAddressState, request_deserializer=qrl__pb2.GetMultiSigAddressStateReq.FromString, diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index e1d628704..d24aa5630 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -26,6 +26,8 @@ service PublicAPI rpc GetAddressState (GetAddressStateReq) returns (GetAddressStateResp); + rpc GetOptimizedAddressState (GetAddressStateReq) returns (GetOptimizedAddressStateResp); + rpc GetMultiSigAddressState (GetMultiSigAddressStateReq) returns (GetMultiSigAddressStateResp); rpc IsSlave (IsSlaveReq) returns (IsSlaveResp); @@ -218,6 +220,10 @@ message GetAddressStateReq { } message GetAddressStateResp { + AddressState state = 1; +} + +message GetOptimizedAddressStateResp { OptimizedAddressState state = 1; } diff --git a/src/qrl/services/PublicAPIService.py b/src/qrl/services/PublicAPIService.py index 401666e72..8e9b1aa00 100644 --- a/src/qrl/services/PublicAPIService.py +++ b/src/qrl/services/PublicAPIService.py @@ -109,6 +109,13 @@ def GetAddressState(self, request: qrl_pb2.GetAddressStateReq, context) -> qrl_p address_state = self.qrlnode.get_address_state(request.address) return qrl_pb2.GetAddressStateResp(state=address_state.pbdata) + @GrpcExceptionWrapper(qrl_pb2.GetOptimizedAddressStateResp) + def GetOptimizedAddressState(self, + request: qrl_pb2.GetAddressStateReq, + context) -> qrl_pb2.GetOptimizedAddressStateResp: + address_state = self.qrlnode.get_optimized_address_state(request.address) + return qrl_pb2.GetOptimizedAddressStateResp(state=address_state.pbdata) + @GrpcExceptionWrapper(qrl_pb2.GetMultiSigAddressStateResp) def GetMultiSigAddressState(self, request: qrl_pb2.GetMultiSigAddressStateReq, @@ -293,7 +300,7 @@ def GetObject(self, request: qrl_pb2.GetObjectReq, context) -> qrl_pb2.GetObject try: if AddressState.address_is_valid(query): if self.qrlnode.get_address_is_used(query): - address_state = self.qrlnode.get_address_state(query) + address_state = self.qrlnode.get_optimized_address_state(query) if address_state is not None: answer.found = True answer.address_state.CopyFrom(address_state.pbdata) @@ -507,7 +514,7 @@ def GetTransaction(self, request: qrl_pb2.GetTransactionReq, context) -> qrl_pb2 @GrpcExceptionWrapper(qrl_pb2.GetBalanceResp) def GetBalance(self, request: qrl_pb2.GetBalanceReq, context) -> qrl_pb2.GetBalanceResp: logger.debug("[PublicAPI] GetBalance") - address_state = self.qrlnode.get_address_state(request.address) + address_state = self.qrlnode.get_optimized_address_state(request.address) response = qrl_pb2.GetBalanceResp(balance=address_state.balance) return response @@ -517,7 +524,7 @@ def GetTotalBalance(self, request: qrl_pb2.GetTotalBalanceReq, context) -> qrl_p response = qrl_pb2.GetBalanceResp(balance=0) for address in request.addresses: - address_state = self.qrlnode.get_address_state(address) + address_state = self.qrlnode.get_optimized_address_state(address) response.balance += address_state.balance return response From d223b0c8b0a41e2c3de2d57416c95f5b53c33cf4 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 12 Feb 2020 15:21:32 +0530 Subject: [PATCH 26/67] Updated Unit Tests --- tests/core/test_ChainManager.py | 10 +++++----- tests/core/test_qrlnode.py | 8 ++++---- tests/services/test_PublicAPIService.py | 6 ++++-- tests/services/test_WalletAPIService.py | 24 ++++++++++++------------ 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 2f2065f85..a8fc4bd1a 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -182,9 +182,9 @@ def test_multi_output_transaction_add_block(self, time_mock): self.assertTrue(result) self.assertEqual(self.chain_manager.last_block, block_1) - bob_addr_state = self.chain_manager.get_address_state(bob.address) - alice_addr_state = self.chain_manager.get_address_state(alice.address) - random_addr_state = self.chain_manager.get_address_state(random_xmss.address) + bob_addr_state = self.chain_manager.get_optimized_address_state(bob.address) + alice_addr_state = self.chain_manager.get_optimized_address_state(alice.address) + random_addr_state = self.chain_manager.get_optimized_address_state(random_xmss.address) self.assertEqual(bob_addr_state.balance, 0) self.assertEqual(alice_addr_state.balance, @@ -292,8 +292,8 @@ def test_add_block(self, mock_difficulty_tracker_get): self.assertEqual(self.chain_manager.last_block.serialize(), block_2.serialize()) # Now we are on the forked chain, Bob is no longer Alice's slave. - alice_state = self.chain_manager.get_address_state(alice.address) - self.assertFalse(str(bob.pk) in alice_state.slave_pks_access_type) + bob_access_type = self.chain_manager.get_slave_pk_access_type(alice.address, bob.pk) + self.assertIsNone(bob_access_type) @set_default_balance_size() @set_hard_fork_block_number() diff --git a/tests/core/test_qrlnode.py b/tests/core/test_qrlnode.py index 57d94a0a9..f15f3ab1c 100644 --- a/tests/core/test_qrlnode.py +++ b/tests/core/test_qrlnode.py @@ -222,24 +222,24 @@ def test_get_mini_transactions_by_address(self, self.assertEqual(balance, 100) @patch('qrl.core.OptimizedAddressState.OptimizedAddressState.get_optimized_address_state') - def test_get_address_state(self, mock_get_optimized_address_state): + def test_get_optimized_address_state(self, mock_get_optimized_address_state): """ QRLNode.get_address_state() asks the DB (State) for an Address's AddressState, like its nonce, ots index... It also validates the address before sending it to the State. """ m_addr_state = Mock(autospec=OptimizedAddressState) mock_get_optimized_address_state.return_value = m_addr_state - result = self.qrlnode.get_address_state(alice.address) + result = self.qrlnode.get_optimized_address_state(alice.address) self.assertEqual(m_addr_state, result) # Fetching AddressState for Coinbase Address m_addr_state = Mock(autospec=OptimizedAddressState) mock_get_optimized_address_state.return_value = m_addr_state - result = self.qrlnode.get_address_state(config.dev.coinbase_address) + result = self.qrlnode.get_optimized_address_state(config.dev.coinbase_address) self.assertEqual(m_addr_state, result) with self.assertRaises(ValueError): - self.qrlnode.get_address_state(b'fdsa') + self.qrlnode.get_optimized_address_state(b'fdsa') def test_get_addr_from(self): """ diff --git a/tests/services/test_PublicAPIService.py b/tests/services/test_PublicAPIService.py index 94aacc68d..d1453ecba 100644 --- a/tests/services/test_PublicAPIService.py +++ b/tests/services/test_PublicAPIService.py @@ -2,6 +2,7 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import heapq +from math import ceil from unittest import TestCase from grpc import ServicerContext, StatusCode @@ -177,8 +178,9 @@ def test_getAddressState(self): self.assertEqual(alice_xmss.address, response.state.address) self.assertEqual(25, response.state.nonce) self.assertEqual(10, response.state.balance) - self.assertEqual(0, response.state.ots_bitfield_used_page) - self.assertEqual(0, response.state.transaction_hash_count) + count = int(ceil((2 ** optimized_address_state.height) / 8)) + self.assertEqual([b'\x00'] * count, response.state.ots_bitfield) + self.assertEqual([], response.state.transaction_hashes) def test_getObject(self): SOME_ODD_HASH = sha256(b'this should not be found') diff --git a/tests/services/test_WalletAPIService.py b/tests/services/test_WalletAPIService.py index 1a38651a3..15140aebf 100644 --- a/tests/services/test_WalletAPIService.py +++ b/tests/services/test_WalletAPIService.py @@ -7,7 +7,7 @@ from pyqrllib.pyqrllib import bin2hstr, hstr2bin from qrl.core.misc import logger -from qrl.core.OptimizedAddressState import OptimizedAddressState +from qrl.core.AddressState import AddressState from qrl.daemon.walletd import WalletD from qrl.generated import qrlwallet_pb2, qrl_pb2 from qrl.services.WalletAPIService import WalletAPIService @@ -137,7 +137,7 @@ def test_relayTransferTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -174,7 +174,7 @@ def test_relayTransferTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -207,7 +207,7 @@ def test_relayMessageTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.GetOTS = Mock( @@ -220,7 +220,7 @@ def test_relayMessageTxn(self): signer_address=qaddress, ots_index=0), context=None) - self.assertEqual(resp.code, 0) + self.assertEqual(0, resp.code) self.assertIsNotNone(resp.tx) def test_relayMessageTxnBySlave(self): @@ -233,7 +233,7 @@ def test_relayMessageTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -257,7 +257,7 @@ def test_relayTokenTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -298,7 +298,7 @@ def test_relayTokenTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -332,7 +332,7 @@ def test_relayTransferTokenTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -370,7 +370,7 @@ def test_relayTransferTokenTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -401,7 +401,7 @@ def test_relaySlaveTxn(self): resp = service.AddNewAddress(qrlwallet_pb2.AddNewAddressReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( @@ -437,7 +437,7 @@ def test_relaySlaveTxnBySlave(self): resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None) qaddress = resp.address - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.IsSlave = Mock( From 78cb12f770426b3fcd578d90ffc632064c81221b Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 12 Feb 2020 15:33:52 +0530 Subject: [PATCH 27/67] Fix block_timing_in_seconds mocking for Mocknet --- src/qrl/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qrl/main.py b/src/qrl/main.py index 027ffc1c9..226297663 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -81,7 +81,7 @@ def main(): config.user.mining_enabled = True config.user.mining_thread_count = 1 config.user.mining_pause = 500 - config.dev.block_timing_in_seconds = 1 + config.dev.pbdata.block.block_timing_in_seconds = 1 config.user.genesis_difficulty = 2 # Mocknet mining address From cfaedda07a113cf5ece3829710e5cb4b167edb2c Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 12 Feb 2020 15:59:57 +0530 Subject: [PATCH 28/67] Fixed Wallet Daemon Unit Test --- tests/daemon/test_walletd.py | 39 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/tests/daemon/test_walletd.py b/tests/daemon/test_walletd.py index 36cec613d..b9e45ab56 100644 --- a/tests/daemon/test_walletd.py +++ b/tests/daemon/test_walletd.py @@ -17,7 +17,6 @@ from qrl.services.PublicAPIService import PublicAPIService from qrl.core.ChainManager import ChainManager from qrl.core.AddressState import AddressState -from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.txs.MessageTransaction import MessageTransaction from qrl.daemon.helper.DaemonHelper import WalletDecryptionError @@ -474,7 +473,7 @@ def test_relay_transfer_txn(self): return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -503,7 +502,7 @@ def test_relay_transfer_txn2(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -538,7 +537,7 @@ def test_relay_transfer_txn3(self): return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -568,7 +567,7 @@ def test_relay_transfer_txn_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -596,7 +595,7 @@ def test_relay_transfer_txn2_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -633,7 +632,7 @@ def test_relay_transfer_txn3_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -665,7 +664,7 @@ def test_relay_message_txn(self): return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) walletd._public_stub.GetOTS = Mock( @@ -691,7 +690,7 @@ def test_relay_message_txn_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) # addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0) walletd._public_stub.GetAddressState = Mock( @@ -713,7 +712,7 @@ def test_relay_message_txn2(self): return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -747,7 +746,7 @@ def test_relay_message_txn2_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -777,7 +776,7 @@ def test_relay_token_txn(self): return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -804,7 +803,7 @@ def test_relay_token_txn_by_slave(self): walletd._public_stub.PushTransaction = Mock( return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.IsSlave = Mock( return_value=qrl_pb2.IsSlaveResp(result=True)) walletd._public_stub.GetOTS = Mock( @@ -840,7 +839,7 @@ def test_relay_token_txn2(self): return_value=qrl_pb2.GetOTSResp(next_unused_ots_index=0, unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -889,7 +888,7 @@ def test_relay_token_txn2_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -935,7 +934,7 @@ def test_relay_transfer_token_txn(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -984,7 +983,7 @@ def test_relay_transfer_token_txn2(self): walletd.add_new_address(height=8) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -1028,7 +1027,7 @@ def test_relay_transfer_token_txn_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -1069,7 +1068,7 @@ def test_relay_slave_txn(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) @@ -1109,7 +1108,7 @@ def test_relay_slave_txn_by_slave(self): unused_ots_index_found=True)) qaddress = walletd.add_new_address_with_slaves(height=8) - addr_state = OptimizedAddressState.get_default(walletd.qaddress_to_address(qaddress)) + addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress)) walletd._public_stub.GetAddressState = Mock( return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata)) From 72f1c3f187205bf813b337723a5dae8bf1746b0d Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 12 Feb 2020 16:00:16 +0530 Subject: [PATCH 29/67] Fix: Updated arguments to call new_state_container in Miner.py --- src/qrl/core/Miner.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qrl/core/Miner.py b/src/qrl/core/Miner.py index fe2634079..653b411c7 100644 --- a/src/qrl/core/Miner.py +++ b/src/qrl/core/Miner.py @@ -136,8 +136,7 @@ def create_block(self, block_size_limit = self._chain_manager.get_block_size_limit(last_block, dev_config) transactions = [] - state_container = self._chain_manager.new_state_container([], - set(), + state_container = self._chain_manager.new_state_container(set(), last_block.block_number, True, None) From 46b81b8ee0cb0676b64d5c99a0f0ce811144fd84 Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 13 Feb 2020 00:36:02 +0530 Subject: [PATCH 30/67] Single lock for all miners --- src/qrl/core/Miner.py | 9 ++++++--- src/qrl/core/miners/qrandomx/QRXMiner.py | 5 +++-- src/qrl/core/miners/qryptonight7/CNv1Miner.py | 5 +++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/qrl/core/Miner.py b/src/qrl/core/Miner.py index 653b411c7..d12ada503 100644 --- a/src/qrl/core/Miner.py +++ b/src/qrl/core/Miner.py @@ -26,14 +26,18 @@ def __init__(self, pre_block_logic, mining_address: bytes, mining_thread_count): + self.lock = threading.RLock() + self.qryptonight_7_miner = CNv1Miner(pre_block_logic, mining_address, - mining_thread_count) + mining_thread_count, + self.lock) self.qrandomx_miner = QRandomXMiner(chain_manager, pre_block_logic, mining_address, - mining_thread_count) + mining_thread_count, + self.lock) self._qn = Qryptonight() self._chain_manager = chain_manager self._pre_block_logic = pre_block_logic @@ -43,7 +47,6 @@ def __init__(self, self._measurement = None self._current_miner = self.qrandomx_miner - self.lock = threading.RLock() def isRunning(self): return self._current_miner.isRunning diff --git a/src/qrl/core/miners/qrandomx/QRXMiner.py b/src/qrl/core/miners/qrandomx/QRXMiner.py index d6b2e6507..00bb79e6e 100644 --- a/src/qrl/core/miners/qrandomx/QRXMiner.py +++ b/src/qrl/core/miners/qrandomx/QRXMiner.py @@ -17,7 +17,8 @@ def __init__(self, chain_manager, pre_block_logic, mining_address: bytes, - mining_thread_count): + mining_thread_count, + lock): super().__init__() self._qn = QRandomX() self._chain_manager = chain_manager @@ -30,7 +31,7 @@ def __init__(self, self._seed_block = None self.setForcedSleep(user_config.mining_pause) self._dev_config = None - self.lock = threading.RLock() + self.lock = lock def get_seed_block(self, block_number): # TODO: Verify when seed height is changed also add unit test for edge case diff --git a/src/qrl/core/miners/qryptonight7/CNv1Miner.py b/src/qrl/core/miners/qryptonight7/CNv1Miner.py index cbecf76d8..4ee417cf2 100644 --- a/src/qrl/core/miners/qryptonight7/CNv1Miner.py +++ b/src/qrl/core/miners/qryptonight7/CNv1Miner.py @@ -15,7 +15,8 @@ class CNv1Miner(Qryptominer): def __init__(self, pre_block_logic, mining_address: bytes, - mining_thread_count): + mining_thread_count, + lock): super().__init__() self.pre_block_logic = pre_block_logic # FIXME: Circular dependency with node.py @@ -26,7 +27,7 @@ def __init__(self, self._mining_block = None self.setForcedSleep(user_config.mining_pause) self._dev_config = None - self.lock = threading.RLock() + self.lock = lock def start_mining(self, mining_block: Block, From a0c20059bf5df26e36fb5e7e2013b0b909bcaed7 Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 13 Feb 2020 00:41:44 +0530 Subject: [PATCH 31/67] Removed unused import --- src/qrl/core/miners/qrandomx/QRXMiner.py | 1 - src/qrl/core/miners/qryptonight7/CNv1Miner.py | 1 - 2 files changed, 2 deletions(-) diff --git a/src/qrl/core/miners/qrandomx/QRXMiner.py b/src/qrl/core/miners/qrandomx/QRXMiner.py index 00bb79e6e..24db06d9f 100644 --- a/src/qrl/core/miners/qrandomx/QRXMiner.py +++ b/src/qrl/core/miners/qrandomx/QRXMiner.py @@ -2,7 +2,6 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import copy -import threading from pyqrandomx.pyqrandomx import QRXMiner, SOLUTION diff --git a/src/qrl/core/miners/qryptonight7/CNv1Miner.py b/src/qrl/core/miners/qryptonight7/CNv1Miner.py index 4ee417cf2..7823db956 100644 --- a/src/qrl/core/miners/qryptonight7/CNv1Miner.py +++ b/src/qrl/core/miners/qryptonight7/CNv1Miner.py @@ -2,7 +2,6 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import copy -import threading from pyqryptonight.pyqryptonight import Qryptominer, SOLUTION From 581ee568ff538714807157f40324674e056f3edd Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 13 Feb 2020 21:03:19 +0530 Subject: [PATCH 32/67] Updated CircleCI config --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c81fe0372..610c83033 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -102,7 +102,6 @@ jobs: steps: - checkout - run: git submodule update --init --recursive --remote - - run: apt install -y python3-venv - run: pip install -U -r tests_integration/requirements.txt - run: pip install git+https://github.com/CurataEng/hypothesis-protobuf.git - run: pytest tests_integration/tests/python/fuzzing From bf7e45a50766dbe5796d761960d71f52ccbb48a7 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 14 Feb 2020 23:17:56 +0530 Subject: [PATCH 33/67] Fix: Logger file now stored to specified qrl directory instead of hard coded .qrl directory --- src/qrl/core/misc/logger.py | 3 +-- src/qrl/core/misc/set_logger.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qrl/core/misc/logger.py b/src/qrl/core/misc/logger.py index 50962d0a0..7497e2ce1 100644 --- a/src/qrl/core/misc/logger.py +++ b/src/qrl/core/misc/logger.py @@ -14,7 +14,6 @@ LOG_NAME = 'qrl' -LOG_FILENAME_DEFAULT = config.user.log_path LOG_MAXBYTES = 100 * 1024 * 1024 LOG_FORMAT_FULL = '%(asctime)s - %(levelname)s - %(message)s' LOG_FORMAT_SMALL = '%(asctime)s - %(message)s' @@ -37,7 +36,7 @@ def initialize_default(force_console_output=False, log_level=logging.DEBUG): return handler -def log_to_file(filename=LOG_FILENAME_DEFAULT): +def log_to_file(filename): dir_path = os.path.dirname(os.path.realpath(filename)) os.makedirs(dir_path, exist_ok=True) handler = RotatingFileHandler(filename, diff --git a/src/qrl/core/misc/set_logger.py b/src/qrl/core/misc/set_logger.py index 549551e58..b29fbc4f3 100644 --- a/src/qrl/core/misc/set_logger.py +++ b/src/qrl/core/misc/set_logger.py @@ -31,7 +31,7 @@ def set_logger(args, sync_state): logger.initialize_default(force_console_output=not args.quiet).setLevel(log_level) custom_filter = ContextFilter(sync_state, config.dev.version) logger.logger.addFilter(custom_filter) - file_handler = logger.log_to_file() + file_handler = logger.log_to_file(config.user.log_path) file_handler.addFilter(custom_filter) file_handler.setLevel(logging.DEBUG) logger.set_colors(not args.no_colors, LOG_FORMAT_CUSTOM) From 690dcf3ea54c1b02287a80b749df8872c6fc39ce Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 14 Feb 2020 23:19:50 +0530 Subject: [PATCH 34/67] Support for --network-type argument to switch between mainnet and testnet --- src/qrl/core/config.py | 13 +++++++---- src/qrl/main.py | 17 +++++++++++--- src/qrl/network/testnet/config.yml | 4 ++++ src/qrl/network/testnet/genesis.yml | 35 +++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 src/qrl/network/testnet/config.yml create mode 100644 src/qrl/network/testnet/genesis.yml diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index d8d9b32d8..0cb286c4b 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -1,6 +1,7 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import shutil import decimal from os.path import expanduser from pyqrllib.pyqrllib import hstr2bin @@ -187,11 +188,15 @@ def load_yaml(self, file_path): self.__dict__.update(**dataMap) -def create_path(path): - # FIXME: Obsolete. Refactor/remove. Use makedirs from python3 +def create_path(path, copy_files=None): tmp_path = os.path.join(path) - if not os.path.isdir(tmp_path): - os.makedirs(tmp_path) + if os.path.isdir(tmp_path): + return + os.makedirs(tmp_path) + if not copy_files: + return + for file in copy_files: + shutil.copy(file, tmp_path) class DevConfig(object): diff --git a/src/qrl/main.py b/src/qrl/main.py index 226297663..6359a90a7 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -3,7 +3,7 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import argparse import faulthandler -from os.path import expanduser +import os from mock import MagicMock from twisted.internet import reactor @@ -32,6 +32,8 @@ def parse_arguments(): help="Disables color output") parser.add_argument("-l", "--loglevel", dest="logLevel", choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help="Set the logging level") + parser.add_argument('--network-type', dest='network_type', choices=['mainnet', 'testnet'], + default='mainnet', required=False, help="Runs QRL Testnet Node") parser.add_argument('--miningAddress', dest='mining_address', required=False, help="QRL Wallet address on which mining reward has to be credited.") parser.add_argument('--mockGetMeasurement', dest='measurement', required=False, type=int, default=-1, @@ -63,10 +65,19 @@ def get_mining_address(mining_address: str): def main(): args = parse_arguments() + qrl_dir_post_fix = '' + copy_files = [] + if args.network_type == 'testnet': + qrl_dir_post_fix = '-testnet' + package_directory = os.path.dirname(os.path.abspath(__file__)) + print(package_directory) + copy_files.append(os.path.join(package_directory, 'network/testnet/genesis.yml')) + copy_files.append(os.path.join(package_directory, 'network/testnet/config.yml')) + logger.debug("=====================================================================================") logger.info("QRL Path: %s", args.qrl_dir) - config.user.qrl_dir = expanduser(args.qrl_dir) - config.create_path(config.user.qrl_dir) + config.user.qrl_dir = os.path.expanduser(os.path.normpath(args.qrl_dir) + qrl_dir_post_fix) + config.create_path(config.user.qrl_dir, copy_files) logger.debug("=====================================================================================") config.create_path(config.user.wallet_dir) diff --git a/src/qrl/network/testnet/config.yml b/src/qrl/network/testnet/config.yml new file mode 100644 index 000000000..0134802b3 --- /dev/null +++ b/src/qrl/network/testnet/config.yml @@ -0,0 +1,4 @@ +peer_list: [ "18.130.83.207", "35.176.41.49", "18.130.187.220", "35.176.33.242" ] +genesis_prev_headerhash: 'The Testnet Genesis' +genesis_timestamp: 1530004179 +genesis_difficulty: 5000 diff --git a/src/qrl/network/testnet/genesis.yml b/src/qrl/network/testnet/genesis.yml new file mode 100644 index 000000000..cc18318a7 --- /dev/null +++ b/src/qrl/network/testnet/genesis.yml @@ -0,0 +1,35 @@ +genesisBalance: +- {address: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, balance: '105000000000000000'} +header: {hashHeader: zTnPTGwZrMT+T1dxN/8mr2jArzsYatEQFFkboJJvfGg=, hashHeaderPrev: VGhlIFRlc3RuZXQgR2VuZXNpcw==, + merkleRoot: WI9TSXvP+6mAjffoX05uprLk/ace20rIN2iyLnYYyeU=, rewardBlock: '65000000000000000', + timestampSeconds: '1530004179'} +transactions: +- coinbase: {addrTo: AQUAP581PQiqk/bKCLX92e0qtLZSJSTIq41N4yZpPA8qK3T0VC2l, amount: '65000000000000000'} + masterAddr: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + nonce: '1' + transactionHash: ySWhauTK7jCA7QT5r+kpgOIPGGavsWmTo37IuhqAAiM= +- nonce: '1' + publicKey: AQUADQjp7dOFQYDsWzaynbDdiPcs1bypV/Bfch68FOghq9iS36U210VGizuzg0PXjojTRTksDQv/Z4t1zXOrdMBt2A== + signature: AAAAALwB7YZL2an2Kc39uPAYRa2hnh1rAHQnhbExk5uRrA+7WVbG/7yK9s0OxJqeSSIlPaJxBhNi0ZbF7txTAzqZ/0VR2DFf3X1Khfz7RTh1zsjQKowBxyY5M1f+1TcmMD71S2bsTQ2TX+nyfITV+rH4kTHHhQ8k417RGBuZBju8kvJoWkLkDE5s0AfS+ocGqOBYc3+ECNYh/wktXgNu/nSiTuekiDxBLCSrg1zJtkwt+B4yTdc4lXU5Hle7zbozZuAZRUwyWUgHxM7JV3TwKP7NPAKcw4NftA3XMrCCCpDYqm3a7xs4wHrNNOW3nu9A5ZEHEl80meBXP8Woqvy6YLqcxAohjgDp3h8H+p3pZ9MkeB1FWT1cuDt0WxSKnpFyrIk+k6UqUW/X0s/leeppTKw9ugzBm9GqNPM+xm++pkn3AVm+ji5LO4WF2PPWQDhFT0vmJC7ZPaORYUXQkRlYHYkFXQ6t1RLm6KgWMx6sMZHOxCApIDKfIjT2df8qEtsIHpcd+hoWYvmUy+FCxtyxGCV+MgAKyjpshkFN9opmqUK5Tg2gFMpp8orPDDhpAsWVYgG+pNqZIRCUFRJJg20EKsijLEJYkzOABuJc5xjFt5QImWZvs4ju8WU6btgP4gd8cvlXcytfXr5lKJowlxQsufWRp6NF5+K/q2LyK5QlFfiPQhHKXVczdyWp9oFP63xh1oeSH225Cbcz04AohbostMjchXpEn2NJQDz8e4VO5rFWwuL7QD0jE9ZlHAhv+jPIaXoXmc/VUiWv6z+2Yu4BAzgFkOhA0sAFx17H9bk1uAhZQKu6DGE9hUgQLn2wfBHsfn9wN/d99g4EhZEqomzj9CQI8voUpMJ0uZO/y692QVgt8P7zxg0bH5dpC1SLDFKuf39c4+1PO68c6b34lwbWjfapSP//uyXUVNPm6jcBcyiszDsSE/N6vQFLGqtYzLLkorTGoKTMstFUnUN0zTtgdTyY9AUhVtA3+NeiVndNFxhnNztxzTAZTGwL/ijQ1rP0OYH0/X6mBg0S7usjLSOAMbSKDogKZsHAccyM9KPQX8InaJFeY+F67g06G8b4kOunGrExT3pkN3+SYJ1gSQ2TxA/bZtC1JWj1G4wIyvmCpvsziFYrYmP8Sb4dzPep5RHNIHM9w6NiKxpdxe8wAeB/kDmaQPPMnEugDm5zSW6M0QuEwahAJuOdDgL+EpAA0Kh+yn7cPVDPvVxLOK+APtcB+ObpOwEDe05W+RBGixs4QgdbVHTI//dSwImmyXC6Ird575jPnxkZLzz/UReVfiMaDrIuPG2hLykfbi8ZpE/St4epBB0/bIkks95NC7WNO5CzdHeS0Jst8Fj9fhwTKChJ3rbizHL2UCf05FaKpoiojrabY+glGwuGw/Ij1k5OSfBVTlzcLkPg96qSkUNv3l2lxMDs5YKMEbZCv3OGKplcP/9A380l9DeeL2q7eugfZ97ml8CJto6awQcQLGfkyJOznrDKORP8j3qlG+pfcmEG1h1+2YIp89i3ujSIbvs1cbbuv9MdHrJ54+hgA/hhQh40dmzQe529nKFbnkSbWqW4BsmuYrAMzR7UO/VhwE5ZFI97k3So0xOmZJ6FMD03ktUfJHWtTa/ydIzfnkTUSPZYpJsgFpyLNYhHnaPwSuNuLo9ut2aEHFJtvLHA93KWpELl03wKaLs1PGhJE3IJx0PwZRS//wq2ztxNXQTK1tJsGVMSwX3D05G3wGzw8yHK+mU6edHpazdiip1F76XY3gtdeDZD2JegqidYbPT5Xt1aQV5nddUqdmEFiQnsAL31fDAgatgyMjEiYPVCCgOot83EZyvaEWhau4uPF8EhC3hOW+w23t+HylTopMAPWBWJhLHOi4OTT/jfz5zP3vHCy1HDXMBFc1TVrGiWnYCDaQ+8J3q/dnAgCQYFUC3DankIs7qvX6UeyEojfd0DSE6/LaJIpm2Vmk0F5IRDjI8NohROU0oZzC3yHrVuU1ymdY/sefYSrVQbmBc71OAfaXP622cNEupfyPtI2XUAXCURVMvHrNTVS15cNmyZAynCWEjoTLuJGjOHAfrtAxUQhYpdLpwlAuVnePVzJWHWNoHIU291R94C6M5CGtsbrD5fF4okO9T5dD72iVTEFoK1fhxFpikY1zb1Gqrm+wF6zhrI39RUUrO39oiaIxGKDPTXRkO//wV2iHbOrwrHt3bMzMjR4gmkjSNHgmk+UOn/Y3i3izaPphMqeI7C/WBCHNSVhf/IYIaKWCjT7FFxDgzzgOGJQa0IOrFLcnwXo5Oyc4G+yh1vJcwbW8o6aHXhxlkdixm3dqY255gRgmkqrW3/4g8WqCXE4UrnVadWOYfiq6j+SrC15wRKHUnT/io9IxIxdNjvOS0pk9HUDBoO/40BHnp0Pa2n6+aKjo6taAOLM5IHvVf0D9qKabn4irijB/cPTZrqtLrZnX7uMy/uw6vx7GLlEJJa4tjGVQ5gQqQKOD057Rfomgs4qXbZK5H6n0SH6ghRj7/wMte20QIoGQUZHqDARcDSIg3ekZ/KLqgudX5nCYpV3c9McHmD3FjRsXGktNwIJrkyQJxCGOdMlGz2WsmCJGdNYuT5UGVdwp0PNxgdQ4A5zF/LS1X3WZC0D0sa4MtQFdz1DSdGo8fwabLQoKASYgXKXibWv7Ziuugok/RseXSsraGph8R7USwr17ofiy0G9VUggCwcWRwmwWhmN9wOQMo/xeyYKd/fZq1LMsITybRsoeMWmBywWpxm+ttDaHAtBtFvVw4PMRZ04B3rWONT1ZaXTGeDHH9dR69+8iJOCo8UKPnQVztFH++UjbVj2Mh0C1YQ+z+ZS/9u2S3i98uisUbaCZnW1sn1iZtkI7xJJgWiUo1rZoIYVbsOAyTPXUbtgzJREo9lYwLPlCTiAHRfZ8q7azTUQ+wQIUytXpKd3HTe60LWNJ0LJzj5cNx1Oeln7Ct6MEo4SLp/sGhpPSGLbVVuVvf1mpGKfrOKVDVi2zRiUPSLm+5PfXkriuz7Y3NQrXHJmTAX6jKoJHbhEpJLiNGYE2LzJTYbpndLFGVYq8mu8cf/tecpBXSsqMxQCxURkowcWe3MCzGIWRVR+TD2qfmYF6Fkb6tFmaP3cLkUuEh6Tf81XwyRnjN40bLeVrKUA01TwG1ATBoFGZ7UyFAmr6i0IV1i8GHQUowwvv1qLmulj0wovhD16byUANqpQbDYnwI5LyvDRd2n7cPU8T55+54V1/mlvNOdNb17XjZlMo5i89FcbZfhvXd3UECG9DFEpIXbyGeTnu78q8c1amHg9vFJVAi+0/zyMkQlJHUnhL+LJqbvfKMDzQ== + transactionHash: 6IhL/ZYfWzFAnhs01yS1QfGos4kQI6LHJadNuVR6KmA= + transfer: + addrsTo: [AQMAmMXxlr05m0gMKMeyqzbGAScYYgnsHhkdos2btmV1N2YPRTAr, AQUAMXzlAhI8DeZxH9TqaDPqNg6Vy0CvcZRO6jjakL+12DdA0B5Q, + AQYA6/PGyseeabX7AQ5BnzvoH88YiCchKYh/9gHfF5RzUySiw2YQ, AQUA68H8kCdZsRrEOX2EiogYVRauKfBPAZbY0mNES8fcxw/MhQJ6, + AQUABwTFd9VXslEzMtSrzrVrouiULgw4amZLK3Wx7dTkAwGbhKo3, AQUAm7iePNiVDmIBbqElsOwidloXyYGpDL3JFLXAEojDunHZaH+r, + AQUAf03L/rELXH5iXmQh/P+PQ7xvT3pmYmi3Rx4vCGU54nAX+vCv, AQUABc41hpjQgCfRwDMKRnVVv8A2Udjmfb2dtzsv1BkfiYpISo2j, + AQQA6ZhwjU4fk/JcdK79OzmQojVo7es1SyQDLwS8DsZhZzv5t6ii, AQIAmLAUwLHjp9zry6yVbz3eIlHvDSp80Qby7N5SoOqhp+vpVyW/, + AQUAnx588JeaZ/auZUfbqfNSicAu8GUTHCGhKB51+YWKgzho42LT, AQUAC7VCLVflaTMQVdzuOhvAM0pDnSmRBdKhSax1vrqVzr0F0keP, + AQUA/oCF0pKJVfI++QoxwhVvV1vF8NUGcM4Jov87Y4HK/P/euEk+, AQUAdSDRJ+sbkEn562+2rTuRe9+oh7E40t2HTn4rM5I/HVAtDxOn, + AQUAJ/JiAyIcmLxiArWi9Wc0ioERD9SEEaTwPWCav25pnNipIshg, AQUAIpIoocpQTt8Ya7YH7gXrO3ArM/iyWt/RbD6eSTOqBdOoMMgS, + AQYAocRKrqQ8kKSrCY6qi1vsbCgwS9uebHQTKDeiQlWkampc+Ra6, AQUAs0fSxKHrpSdbYcN7LGakeXHVjdBsXnwNewjoYMl4ZYD74+/j, + AQUAfoSLiyaUrVmd5paF/z4sVW0qgXwWHtB0DedpHzzzrXV2Huur, AQUAY+xDh4hbJn2SPIHUrgeshkEtsWF+Em2jp9qo62IyT+DVcEDO, + AQUAi3RxgqQDsLccXFUPsj7NinQ8XjuX3ZcsB9fRXfibTa0tyy+W, AQUA2bjXCM0gQd406wvCbdsufuoUZ2QPG/N18IN95E2t6sXKRJ42, + AQUAjbzLqQvcLnkRXmRxzIzfTHEwsT7vRVW1jAAPkX6kArRBv45Q, AQUAWIZsC+m0CoqS1gbF3JCb/WyABRCddDQ36t77CEiHNf4/7v+1, + AQUAWBzM+xk/ywXCNm4FD5hP2yxTc5buOsRS0sfJL0VL2PPvGcQj, AQMA5vlJm3iJ7hX1pdU2srNNaOf9kVRzwq5Z5Qd7O0jHT5/ZkV2D, + AQYAJoas3IkIdHkQO2mhCUsbltqRZ1rcpJUqoW9Rsy2T1uG2vRDA] + amounts: ['70000000000000', '2000000000000', '500000000000000', '100000000000', + '50000000000', '1000000000000', '4000000000000', '10014000000000', '1715229300000', + '1100000000', '1000000000000', '540000000000', '5000000000', '55000000000', + '1000000000', '10000000000000', '100000000000', '1234000000000', '200000000000', + '1000000000000', '14804070700000', '10000000000000', '5000000000000', '1000000000', + '1000000000000', '60000000000000', '775000000000000'] From 89d511670865e5af32f2c98998642496fe676d2e Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 14 Feb 2020 23:24:19 +0530 Subject: [PATCH 35/67] Removed print statement --- src/qrl/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qrl/main.py b/src/qrl/main.py index 6359a90a7..80380d67c 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -70,7 +70,6 @@ def main(): if args.network_type == 'testnet': qrl_dir_post_fix = '-testnet' package_directory = os.path.dirname(os.path.abspath(__file__)) - print(package_directory) copy_files.append(os.path.join(package_directory, 'network/testnet/genesis.yml')) copy_files.append(os.path.join(package_directory, 'network/testnet/config.yml')) From 1698d08df164a4b74a697d2939839a5810402fbc Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 00:39:15 +0530 Subject: [PATCH 36/67] Added mining_blob into logging for PoW Validation --- src/qrl/core/ChainManager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index e1a385c63..5e81ef1fd 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -310,6 +310,8 @@ def validate_mining_nonce(self, blockheader: BlockHeader, dev_config: config.Dev parent_difficulty=parent_metadata.block_difficulty, dev_config=dev_config) + mining_blob = blockheader.mining_blob(dev_config) + if enable_logging: logger.debug('-----------------START--------------------') logger.debug('Validate #%s', blockheader.block_number) @@ -318,15 +320,15 @@ def validate_mining_nonce(self, blockheader: BlockHeader, dev_config: config.Dev logger.debug('parent_block.difficulty %s', UInt256ToString(parent_metadata.block_difficulty)) logger.debug('diff %s', UInt256ToString(diff)) logger.debug('target %s', bin2hstr(target)) + logger.debug('mining blob %s', bin2hstr(mining_blob)) logger.debug('-------------------END--------------------') qn = Qryptonight() seed_block = self.get_block_by_number(qn.get_seed_height(blockheader.block_number)) - if not PoWValidator().verify_input(blockheader.block_number, seed_block.block_number, seed_block.headerhash, - blockheader.mining_blob(dev_config), + mining_blob, target): if enable_logging: logger.warning("PoW verification failed") From 9a661e54b5e853c037a1bea0136f413e1444ab50 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 00:39:38 +0530 Subject: [PATCH 37/67] Try to reload config when qrl_dir is changed --- src/qrl/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qrl/main.py b/src/qrl/main.py index 80380d67c..2370cc228 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -77,6 +77,7 @@ def main(): logger.info("QRL Path: %s", args.qrl_dir) config.user.qrl_dir = os.path.expanduser(os.path.normpath(args.qrl_dir) + qrl_dir_post_fix) config.create_path(config.user.qrl_dir, copy_files) + config.user.load_yaml(config.user.config_path) logger.debug("=====================================================================================") config.create_path(config.user.wallet_dir) From c7499cee04d7ab47dbf9e3fc466e7c1a0a215024 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 00:44:12 +0530 Subject: [PATCH 38/67] Flake8 Fix: Removed unused import --- src/qrl/core/misc/logger.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qrl/core/misc/logger.py b/src/qrl/core/misc/logger.py index 7497e2ce1..817d8cac6 100644 --- a/src/qrl/core/misc/logger.py +++ b/src/qrl/core/misc/logger.py @@ -10,8 +10,6 @@ from colorlog import ColoredFormatter from logging.handlers import RotatingFileHandler -from qrl.core import config - LOG_NAME = 'qrl' LOG_MAXBYTES = 100 * 1024 * 1024 From d821fc721c7a42a37b5e54324e718e2e410f7306 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 01:49:20 +0530 Subject: [PATCH 39/67] Fix: Indexer to load arbitrary Indexed data, rather than hard coded slave metadata --- src/qrl/core/ChainManager.py | 10 +++++----- src/qrl/core/Indexer.py | 16 +++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 5e81ef1fd..c791651f5 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -818,27 +818,27 @@ def update_state_container(self, if slave_addr is not None: key = (tx.addr_from, tx.PK) if key not in state_container.slaves.data: - slaves.load(key) + slaves.load(key, qrl_pb2.SlaveMetadata()) if isinstance(tx, TransferTokenTransaction): key = (tx.addr_from, tx.token_txhash) if key not in state_container.tokens.data: - tokens.load(key) + tokens.load(key, qrl_pb2.TokenBalance()) for address in tx.addrs_to: key = (address, tx.token_txhash) if key in state_container.tokens.data: continue - tokens.load(key) + tokens.load(key, qrl_pb2.TokenBalance()) elif isinstance(tx, SlaveTransaction): for slave_pk in tx.slave_pks: key = (tx.addr_from, slave_pk) if key not in state_container.slaves.data: - slaves.load(key) + slaves.load(key, qrl_pb2.SlaveMetadata()) elif isinstance(tx, LatticeTransaction): key = (tx.addr_from, tx.pk1, tx.pk2, tx.pk3, tx.pk4) if key not in state_container.lattice_pk.data: - lattice_pk.load(key) + lattice_pk.load(key, qrl_pb2.LatticePKMetadata()) # elif isinstance(tx, TokenTransaction): # for initial_balance in tx.initial_balances: # if (initial_balance.address, tx.txhash) not in tokens: diff --git a/src/qrl/core/Indexer.py b/src/qrl/core/Indexer.py index d70d114ab..65088fd73 100644 --- a/src/qrl/core/Indexer.py +++ b/src/qrl/core/Indexer.py @@ -2,14 +2,11 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. -from qrl.generated.qrl_pb2 import SlaveMetadata - class Indexer: def __init__(self, name: bytes, db): self._name = name self._db = db - # self._data = IndexerData(self._name) self._data = dict() @property @@ -18,16 +15,17 @@ def data(self): def put(self, batch=None): for key, value in self._data.items(): - if not value.delete: - self._db.put_raw(self.generate_key(key), value.SerializeToString(), batch) - else: + if value.delete: self._db.delete(self.generate_key(key), batch) + continue + + self._db.put_raw(self.generate_key(key), value.SerializeToString(), batch) - def load(self, key) -> bool: + def load(self, key, meta_data) -> bool: generated_key = self.generate_key(key) try: - slaves_meta_data = SlaveMetadata() - self._data[key] = slaves_meta_data.ParseFromString(self._db.get_raw(generated_key)) + meta_data.ParseFromString(self._db.get_raw(generated_key)) + self._data[key] = meta_data except Exception: return False From dfff91a2fb32a82cbddaa2908910979c2fdbf152 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 01:50:08 +0530 Subject: [PATCH 40/67] PEP8 Fix: Break long line --- src/qrl/core/txs/TokenTransaction.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qrl/core/txs/TokenTransaction.py b/src/qrl/core/txs/TokenTransaction.py index 6c1a36546..f1a5899dc 100644 --- a/src/qrl/core/txs/TokenTransaction.py +++ b/src/qrl/core/txs/TokenTransaction.py @@ -183,9 +183,10 @@ def apply(self, if initial_balance.address == addr_from_pk: addr_from_pk_processed = True - state_container.tokens.data[(initial_balance.address, self.txhash)] = TokenBalance(balance=initial_balance.amount, - decimals=self.decimals, - delete=False) + state_container.tokens.data[(initial_balance.address, + self.txhash)] = TokenBalance(balance=initial_balance.amount, + decimals=self.decimals, + delete=False) address_state = state_container.addresses_state[initial_balance.address] state_container.paginated_tx_hash.insert(address_state, self.txhash) state_container.paginated_tokens_hash.insert(address_state, self.txhash) From f7d5167f35a947109bb7c996f2d9e35fbd9d553e Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 01:51:24 +0530 Subject: [PATCH 41/67] Fix: Initialize TokenBalance data for the receiver for receiving a token first time --- src/qrl/core/txs/TransferTokenTransaction.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/qrl/core/txs/TransferTokenTransaction.py b/src/qrl/core/txs/TransferTokenTransaction.py index 7393c690d..8272e4018 100644 --- a/src/qrl/core/txs/TransferTokenTransaction.py +++ b/src/qrl/core/txs/TransferTokenTransaction.py @@ -5,6 +5,7 @@ from qrl.core.OptimizedAddressState import OptimizedAddressState from qrl.core.misc import logger from qrl.core.txs.Transaction import Transaction +from qrl.generated.qrl_pb2 import TokenBalance class TransferTokenTransaction(Transaction): @@ -134,10 +135,10 @@ def _validate_extended(self, state_container: StateContainer): return False token_balance = state_container.tokens.data[(self.addr_from, self.token_txhash)] - if token_balance < total_amount: + if token_balance.balance < total_amount: logger.info('Insufficient amount of token') logger.info('Token Balance: %s, Sent Token Amount: %s', - token_balance, + token_balance.balance, total_amount) return False @@ -152,6 +153,7 @@ def apply(self, state: State, state_container: StateContainer) -> bool: state_container.tokens.data[(self.addr_from, self.token_txhash)].balance -= self.total_amount + decimals = state_container.tokens.data[(self.addr_from, self.token_txhash)].decimals address_state = state_container.addresses_state[self.addr_from] address_state.update_balance(state_container, self.fee, subtract=True) state_container.paginated_tx_hash.insert(address_state, self.txhash) @@ -161,6 +163,13 @@ def apply(self, amount = self.amounts[index] address_state = state_container.addresses_state[addr_to] + # If receiver doesn't have this token before, then initialize token balance data into state + # before adding the new balance. + if (addr_to, self.token_txhash) not in state_container.tokens.data: + state_container.tokens.data[(addr_to, + self.token_txhash)] = TokenBalance(balance=0, + decimals=decimals, + delete=False) state_container.tokens.data[(addr_to, self.token_txhash)].balance += amount if self.addr_from != addr_to: From ed18c84d93cbc6e1b712a126dd8a12a2c067fe39 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 02:24:48 +0530 Subject: [PATCH 42/67] Fix: Unit Tests for TransferTokenTransaction --- .../core/txs/test_TransferTokenTransaction.py | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/core/txs/test_TransferTokenTransaction.py b/tests/core/txs/test_TransferTokenTransaction.py index 619cb4f6c..2663f8632 100644 --- a/tests/core/txs/test_TransferTokenTransaction.py +++ b/tests/core/txs/test_TransferTokenTransaction.py @@ -12,6 +12,7 @@ from qrl.core.StateContainer import StateContainer from qrl.core.txs.Transaction import Transaction from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction +from qrl.generated import qrl_pb2 from tests.core.txs.testdata import test_json_TransferToken, test_signature_TransferToken from tests.misc.helper import get_alice_xmss, get_bob_xmss, get_slave_xmss, set_qrl_dir @@ -191,7 +192,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): alice_address_state.address: alice_address_state } tokens = Indexer(b'token', None) - tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, + decimals=0, + delete=False) state_container = StateContainer(addresses_state=addresses_state, tokens=tokens, @@ -211,7 +214,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): # Invalid master XMSS/slave XMSS relationship m_validate_slave.return_value = False state_container.tokens = Indexer(b'token', None) - state_container.tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + state_container.tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, + decimals=0, + delete=False) result = tx.validate_all(state_container) self.assertFalse(result) m_validate_slave.return_value = True @@ -221,7 +226,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 tokens = Indexer(b'token', None) - tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, + decimals=0, + delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) @@ -231,7 +238,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): new_callable=PropertyMock) as m_total_amount: m_total_amount.return_value = -100 tokens = Indexer(b'token', None) - tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, + decimals=0, + delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) @@ -239,7 +248,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): # balance = 0, cannot pay the Transaction fee alice_address_state.pbdata.balance = 0 tokens = Indexer(b'token', None) - tokens.data[(self.alice.address, tx.token_txhash)] = 1000 + tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, + decimals=0, + delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) @@ -252,7 +263,9 @@ def test_validate_extended(self, m_validate_slave, m_logger): # addr_from doesn't have enough tokens tokens = Indexer(b'token', None) - tokens.data[(self.alice.address, tx.token_txhash)] = 99 + tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=99, + decimals=0, + delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) From c72f7bbcdb39764eadcf2fffa94be7998a96ef63 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 15 Feb 2020 14:18:10 +0530 Subject: [PATCH 43/67] Added tx_hash field in the response of GetLatticePKsByAddress --- src/qrl/core/qrlnode.py | 3 +- src/qrl/generated/qrl_pb2.py | 383 ++++++++++++++++++----------------- src/qrl/protos/qrl.proto | 1 + 3 files changed, 198 insertions(+), 189 deletions(-) diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 289bddd58..9e02f4409 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -687,7 +687,8 @@ def get_lattice_pks_by_address(self, address: bytes, item_per_page: int, page_nu transaction_detail = qrl_pb2.LatticePKsDetail(pk1=tx.pk1, pk2=tx.pk2, pk3=tx.pk3, - pk4=tx.pk4) + pk4=tx.pk4, + tx_hash=tx_hash) response.lattice_pks_detail.extend([transaction_detail]) return response diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index 38368bc88..1e42fc4e8 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"F\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"W\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x05 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -155,8 +155,8 @@ ], containing_type=None, options=None, - serialized_start=6296, - serialized_end=6367, + serialized_start=6313, + serialized_end=6384, ) _sym_db.RegisterEnumDescriptor(_NODEINFO_STATE) @@ -2513,6 +2513,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tx_hash', full_name='qrl.LatticePKsDetail.tx_hash', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -2526,7 +2533,7 @@ oneofs=[ ], serialized_start=5070, - serialized_end=5140, + serialized_end=5157, ) @@ -2556,8 +2563,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5142, - serialized_end=5221, + serialized_start=5159, + serialized_end=5238, ) @@ -2594,8 +2601,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5223, - serialized_end=5273, + serialized_start=5240, + serialized_end=5290, ) @@ -2625,8 +2632,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5275, - serialized_end=5357, + serialized_start=5292, + serialized_end=5374, ) @@ -2656,8 +2663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5359, - serialized_end=5391, + serialized_start=5376, + serialized_end=5408, ) @@ -2687,8 +2694,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5393, - serialized_end=5426, + serialized_start=5410, + serialized_end=5443, ) @@ -2718,8 +2725,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5428, - serialized_end=5467, + serialized_start=5445, + serialized_end=5484, ) @@ -2749,8 +2756,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5469, - serialized_end=5507, + serialized_start=5486, + serialized_end=5524, ) @@ -2801,8 +2808,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5509, - serialized_end=5607, + serialized_start=5526, + serialized_end=5624, ) @@ -2839,8 +2846,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5609, - serialized_end=5671, + serialized_start=5626, + serialized_end=5688, ) @@ -2884,8 +2891,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5674, - serialized_end=5803, + serialized_start=5691, + serialized_end=5820, ) @@ -2908,8 +2915,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5805, - serialized_end=5819, + serialized_start=5822, + serialized_end=5836, ) @@ -2939,8 +2946,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5821, - serialized_end=5852, + serialized_start=5838, + serialized_end=5869, ) @@ -2970,8 +2977,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5854, - serialized_end=5888, + serialized_start=5871, + serialized_end=5905, ) @@ -3001,8 +3008,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5890, - serialized_end=5931, + serialized_start=5907, + serialized_end=5948, ) @@ -3032,8 +3039,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5933, - serialized_end=5976, + serialized_start=5950, + serialized_end=5993, ) @@ -3063,8 +3070,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5978, - serialized_end=6027, + serialized_start=5995, + serialized_end=6044, ) @@ -3087,8 +3094,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6029, - serialized_end=6051, + serialized_start=6046, + serialized_end=6068, ) @@ -3118,8 +3125,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6053, - serialized_end=6095, + serialized_start=6070, + serialized_end=6112, ) @@ -3199,8 +3206,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6098, - serialized_end=6367, + serialized_start=6115, + serialized_end=6384, ) @@ -3258,8 +3265,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6370, - serialized_end=6503, + serialized_start=6387, + serialized_end=6520, ) @@ -3289,8 +3296,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6505, - serialized_end=6544, + serialized_start=6522, + serialized_end=6561, ) @@ -3320,8 +3327,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6546, - serialized_end=6564, + serialized_start=6563, + serialized_end=6581, ) @@ -3358,8 +3365,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6864, - serialized_end=6909, + serialized_start=6881, + serialized_end=6926, ) _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( @@ -3395,8 +3402,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6911, - serialized_end=6968, + serialized_start=6928, + serialized_end=6985, ) _ADDRESSSTATE = _descriptor.Descriptor( @@ -3481,8 +3488,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6567, - serialized_end=6968, + serialized_start=6584, + serialized_end=6985, ) @@ -3610,8 +3617,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6971, - serialized_end=7422, + serialized_start=6988, + serialized_end=7439, ) @@ -3732,8 +3739,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7425, - serialized_end=7828, + serialized_start=7442, + serialized_end=7845, ) @@ -3763,8 +3770,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7830, - serialized_end=7869, + serialized_start=7847, + serialized_end=7886, ) @@ -3794,8 +3801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7871, - serialized_end=7897, + serialized_start=7888, + serialized_end=7914, ) @@ -3825,8 +3832,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7899, - serialized_end=7928, + serialized_start=7916, + serialized_end=7945, ) @@ -3856,8 +3863,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7930, - serialized_end=7967, + serialized_start=7947, + serialized_end=7984, ) @@ -3894,8 +3901,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7969, - serialized_end=8020, + serialized_start=7986, + serialized_end=8037, ) @@ -3932,8 +3939,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8022, - serialized_end=8070, + serialized_start=8039, + serialized_end=8087, ) @@ -4019,8 +4026,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8073, - serialized_end=8288, + serialized_start=8090, + serialized_end=8305, ) @@ -4057,8 +4064,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8290, - serialized_end=8395, + serialized_start=8307, + serialized_end=8412, ) @@ -4095,8 +4102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8466, - serialized_end=8510, + serialized_start=8483, + serialized_end=8527, ) _TRANSACTIONCOUNT = _descriptor.Descriptor( @@ -4125,8 +4132,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8397, - serialized_end=8510, + serialized_start=8414, + serialized_end=8527, ) @@ -4184,8 +4191,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8513, - serialized_end=8658, + serialized_start=8530, + serialized_end=8675, ) @@ -4236,8 +4243,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8661, - serialized_end=8827, + serialized_start=8678, + serialized_end=8844, ) @@ -4281,8 +4288,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8829, - serialized_end=8956, + serialized_start=8846, + serialized_end=8973, ) @@ -4319,8 +4326,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8958, - serialized_end=9008, + serialized_start=8975, + serialized_end=9025, ) @@ -4350,8 +4357,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9010, - serialized_end=9078, + serialized_start=9027, + serialized_end=9095, ) @@ -4395,8 +4402,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9838, - serialized_end=9905, + serialized_start=9855, + serialized_end=9922, ) _TRANSACTION_COINBASE = _descriptor.Descriptor( @@ -4432,8 +4439,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9907, - serialized_end=9950, + serialized_start=9924, + serialized_end=9967, ) _TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -4483,8 +4490,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9952, - serialized_end=10022, + serialized_start=9969, + serialized_end=10039, ) _TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -4520,8 +4527,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10024, - serialized_end=10072, + serialized_start=10041, + serialized_end=10089, ) _TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -4578,8 +4585,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10074, - serialized_end=10190, + serialized_start=10091, + serialized_end=10207, ) _TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -4622,8 +4629,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10192, - serialized_end=10264, + serialized_start=10209, + serialized_end=10281, ) _TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -4659,8 +4666,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10266, - serialized_end=10314, + serialized_start=10283, + serialized_end=10331, ) _TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( @@ -4703,8 +4710,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10316, - serialized_end=10389, + serialized_start=10333, + serialized_end=10406, ) _TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( @@ -4754,8 +4761,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10391, - serialized_end=10497, + serialized_start=10408, + serialized_end=10514, ) _TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( @@ -4798,8 +4805,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10499, - serialized_end=10571, + serialized_start=10516, + serialized_end=10588, ) _TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( @@ -4828,8 +4835,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10808, - serialized_end=10831, + serialized_start=10825, + serialized_end=10848, ) _TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( @@ -5047,8 +5054,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10834, - serialized_end=11743, + serialized_start=10851, + serialized_end=11760, ) _TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( @@ -5077,8 +5084,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11745, - serialized_end=11769, + serialized_start=11762, + serialized_end=11786, ) _TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( @@ -5138,8 +5145,8 @@ name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', index=0, containing_type=None, fields=[]), ], - serialized_start=10574, - serialized_end=11785, + serialized_start=10591, + serialized_end=11802, ) _TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( @@ -5175,8 +5182,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11787, - serialized_end=11837, + serialized_start=11804, + serialized_end=11854, ) _TRANSACTION = _descriptor.Descriptor( @@ -5327,8 +5334,8 @@ name='transactionType', full_name='qrl.Transaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=9081, - serialized_end=11856, + serialized_start=9098, + serialized_end=11873, ) @@ -5407,8 +5414,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11859, - serialized_end=12043, + serialized_start=11876, + serialized_end=12060, ) @@ -5480,8 +5487,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12046, - serialized_end=12229, + serialized_start=12063, + serialized_end=12246, ) @@ -5511,8 +5518,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12231, - serialized_end=12276, + serialized_start=12248, + serialized_end=12293, ) @@ -5542,8 +5549,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12278, - serialized_end=12311, + serialized_start=12295, + serialized_end=12328, ) @@ -5587,8 +5594,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12313, - serialized_end=12378, + serialized_start=12330, + serialized_end=12395, ) @@ -5632,8 +5639,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12380, - serialized_end=12449, + serialized_start=12397, + serialized_end=12466, ) @@ -5677,8 +5684,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12451, - serialized_end=12520, + serialized_start=12468, + serialized_end=12537, ) @@ -5715,8 +5722,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12522, - serialized_end=12593, + serialized_start=12539, + serialized_end=12610, ) @@ -5746,8 +5753,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12756, - serialized_end=12792, + serialized_start=12773, + serialized_end=12809, ) _ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( @@ -5811,8 +5818,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12596, - serialized_end=12792, + serialized_start=12613, + serialized_end=12809, ) @@ -5842,8 +5849,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12794, - serialized_end=12826, + serialized_start=12811, + serialized_end=12843, ) @@ -5887,8 +5894,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12828, - serialized_end=12924, + serialized_start=12845, + serialized_end=12941, ) @@ -5939,8 +5946,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12927, - serialized_end=13056, + serialized_start=12944, + serialized_end=13073, ) @@ -5977,8 +5984,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13058, - serialized_end=13123, + serialized_start=13075, + serialized_end=13140, ) @@ -6022,8 +6029,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13125, - serialized_end=13213, + serialized_start=13142, + serialized_end=13230, ) @@ -6081,8 +6088,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13215, - serialized_end=13341, + serialized_start=13232, + serialized_end=13358, ) @@ -6119,8 +6126,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13343, - serialized_end=13403, + serialized_start=13360, + serialized_end=13420, ) @@ -6150,8 +6157,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13405, - serialized_end=13450, + serialized_start=13422, + serialized_end=13467, ) @@ -6209,8 +6216,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13452, - serialized_end=13576, + serialized_start=13469, + serialized_end=13593, ) @@ -6240,8 +6247,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13578, - serialized_end=13624, + serialized_start=13595, + serialized_end=13641, ) @@ -6285,8 +6292,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13912, - serialized_end=14011, + serialized_start=13929, + serialized_end=14028, ) _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( @@ -6329,8 +6336,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14221, - serialized_end=14340, + serialized_start=14238, + serialized_end=14357, ) _DEVCONFIG_BLOCK = _descriptor.Descriptor( @@ -6387,8 +6394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14014, - serialized_end=14340, + serialized_start=14031, + serialized_end=14357, ) _DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -6417,8 +6424,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14722, - serialized_end=14751, + serialized_start=14739, + serialized_end=14768, ) _DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -6447,8 +6454,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14753, - serialized_end=14789, + serialized_start=14770, + serialized_end=14806, ) _DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -6484,8 +6491,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14791, - serialized_end=14850, + serialized_start=14808, + serialized_end=14867, ) _DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( @@ -6535,8 +6542,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14852, - serialized_end=14957, + serialized_start=14869, + serialized_end=14974, ) _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( @@ -6565,8 +6572,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14959, - serialized_end=15009, + serialized_start=14976, + serialized_end=15026, ) _DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( @@ -6630,8 +6637,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15012, - serialized_end=15204, + serialized_start=15029, + serialized_end=15221, ) _DEVCONFIG_TRANSACTION = _descriptor.Descriptor( @@ -6702,8 +6709,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14343, - serialized_end=15204, + serialized_start=14360, + serialized_end=15221, ) _DEVCONFIG_POW = _descriptor.Descriptor( @@ -6739,8 +6746,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15206, - serialized_end=15246, + serialized_start=15223, + serialized_end=15263, ) _DEVCONFIG = _descriptor.Descriptor( @@ -6818,8 +6825,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13627, - serialized_end=15246, + serialized_start=13644, + serialized_end=15263, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -8169,8 +8176,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=15249, - serialized_end=17924, + serialized_start=15266, + serialized_end=17941, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -8526,8 +8533,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=17926, - serialized_end=17936, + serialized_start=17943, + serialized_end=17953, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index d24aa5630..a1108a186 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -481,6 +481,7 @@ message LatticePKsDetail { bytes pk2 = 2; bytes pk3 = 3; bytes pk4 = 4; + bytes tx_hash = 5; } message GetLatticePKsByAddressResp { From ddb079d6bb01ff55d4c7b2ef48c7fee4ae6b7815 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sun, 16 Feb 2020 14:02:49 +0530 Subject: [PATCH 44/67] Removed pk4 and updated public key length limit for Lattice Transaction --- src/qrl/core/ChainManager.py | 2 +- src/qrl/core/config.py | 12 +- src/qrl/core/qrlnode.py | 3 - src/qrl/core/txs/LatticeTransaction.py | 21 +- src/qrl/generated/qrl_pb2.py | 515 ++++++++++++------------- src/qrl/protos/qrl.proto | 29 +- src/qrl/services/PublicAPIService.py | 1 - tests/core/test_ChainManager.py | 2 - 8 files changed, 261 insertions(+), 324 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index c791651f5..357bf9d8a 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -836,7 +836,7 @@ def update_state_container(self, if key not in state_container.slaves.data: slaves.load(key, qrl_pb2.SlaveMetadata()) elif isinstance(tx, LatticeTransaction): - key = (tx.addr_from, tx.pk1, tx.pk2, tx.pk3, tx.pk4) + key = (tx.addr_from, tx.pk1, tx.pk2, tx.pk3) if key not in state_container.lattice_pk.data: lattice_pk.load(key, qrl_pb2.LatticePKMetadata()) # elif isinstance(tx, TokenTransaction): diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index 0cb286c4b..4cb97dc4f 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -424,10 +424,6 @@ def lattice_pk2_max_length(self): def lattice_pk3_max_length(self): return self.pbdata.transaction.lattice.pk3_max_length - @property - def lattice_pk4_max_length(self): - return self.pbdata.transaction.lattice.pk4_max_length - @property def proposal_threshold_per(self): return self.pbdata.transaction.proposal.threshold_per @@ -502,11 +498,9 @@ def create(prev_state_key, token = qrl_pb2.DevConfig.Transaction.Token(symbol_max_length=10, name_max_length=30) - # TODO: Change following values before hard fork - lattice = qrl_pb2.DevConfig.Transaction.Lattice(pk1_max_length=2000, - pk2_max_length=2000, - pk3_max_length=2000, - pk4_max_length=2000) + lattice = qrl_pb2.DevConfig.Transaction.Lattice(pk1_max_length=1088, + pk2_max_length=1472, + pk3_max_length=65) foundation_multi_sig = qrl_pb2.DevConfig.Transaction.FoundationMultiSig(threshold_percentage=10) diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 9e02f4409..29390d964 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -343,14 +343,12 @@ def create_slave_tx(slave_pks: list, def create_lattice_tx(pk1: bytes, pk2: bytes, pk3: bytes, - pk4: bytes, fee: int, xmss_pk: bytes, master_addr: bytes) -> LatticeTransaction: return LatticeTransaction.create(pk1=pk1, pk2=pk2, pk3=pk3, - pk4=pk4, fee=fee, xmss_pk=xmss_pk, master_addr=master_addr) @@ -687,7 +685,6 @@ def get_lattice_pks_by_address(self, address: bytes, item_per_page: int, page_nu transaction_detail = qrl_pb2.LatticePKsDetail(pk1=tx.pk1, pk2=tx.pk2, pk3=tx.pk3, - pk4=tx.pk4, tx_hash=tx_hash) response.lattice_pks_detail.extend([transaction_detail]) diff --git a/src/qrl/core/txs/LatticeTransaction.py b/src/qrl/core/txs/LatticeTransaction.py index 987b9c002..cd5921a41 100644 --- a/src/qrl/core/txs/LatticeTransaction.py +++ b/src/qrl/core/txs/LatticeTransaction.py @@ -24,20 +24,15 @@ def pk2(self): # dilithium_pk def pk3(self): # ecdsa_pk return self._data.latticePK.pk3 - @property - def pk4(self): # ecies_pk - return self._data.latticePK.pk4 - def get_data_bytes(self): return self.master_addr + \ self.fee.to_bytes(8, byteorder='big', signed=False) + \ self.pk1 + \ self.pk2 + \ - self.pk3 + \ - self.pk4 + self.pk3 @staticmethod - def create(pk1: bytes, pk2: bytes, pk3: bytes, pk4: bytes, fee: int, xmss_pk: bytes, master_addr: bytes = None): + def create(pk1: bytes, pk2: bytes, pk3: bytes, fee: int, xmss_pk: bytes, master_addr: bytes = None): transaction = LatticeTransaction() if master_addr: @@ -49,7 +44,6 @@ def create(pk1: bytes, pk2: bytes, pk3: bytes, pk4: bytes, fee: int, xmss_pk: by transaction._data.latticePK.pk1 = bytes(pk1) transaction._data.latticePK.pk2 = bytes(pk2) transaction._data.latticePK.pk3 = bytes(pk3) - transaction._data.latticePK.pk4 = bytes(pk4) transaction.validate_or_raise(verify_signature=False) @@ -83,11 +77,6 @@ def _validate_extended(self, state_container: StateContainer) -> bool: logger.warning('Found length %s', len(self.pk3)) return False - if len(self.pk4) > dev_config.lattice_pk4_max_length: # TODO: to fix ecies pk value - logger.warning('ECIES PK length cannot be more than %s bytes', dev_config.lattice_pk4_max_length) - logger.warning('Found length %s', len(self.pk4)) - return False - tx_balance = state_container.addresses_state[self.addr_from].balance if tx_balance < self.fee: @@ -95,7 +84,7 @@ def _validate_extended(self, state_container: StateContainer) -> bool: logger.info('balance: %s, amount: %s', tx_balance, self.fee) return False - if (self.addr_from, self.pk1, self.pk2, self.pk3, self.pk4) in state_container.lattice_pk.data: + if (self.addr_from, self.pk1, self.pk2, self.pk3) in state_container.lattice_pk.data: logger.info('State validation failed for %s because: Lattice PKs already exists for this address', bin2hstr(self.txhash)) return False @@ -114,7 +103,7 @@ def apply(self, state_container.paginated_tx_hash.insert(address_state, self.txhash) state_container.lattice_pk.data[(self.addr_from, - self.pk1, self.pk2, self.pk3, self.pk4)] = LatticePKMetadata(enabled=True) + self.pk1, self.pk2, self.pk3)] = LatticePKMetadata(enabled=True) return self._apply_state_changes_for_PK(state_container) @@ -127,6 +116,6 @@ def revert(self, state_container.paginated_tx_hash.remmove(address_state, self.txhash) state_container.lattice_pk.data[(self.addr_from, - self.pk1, self.pk2, self.pk3, self.pk4)] = LatticePKMetadata(enabled=False) + self.pk1, self.pk2, self.pk3)] = LatticePKMetadata(enabled=False) return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index 1e42fc4e8..62ccf975a 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"v\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03pk4\x18\x05 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"W\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x05 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xd7\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x46\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0b\n\x03pk4\x18\x04 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\xbb\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\x8d\x07\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x1e\n\x16lattice_pk4_max_length\x18\x13 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x14 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x15 \x01(\x04\x12 \n\x18proposal_default_options\x18\x16 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x17 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x18 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x19 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x1a \x01(\x04\x12\x15\n\rN_measurement\x18\x1b \x01(\x04\x12\n\n\x02kp\x18\x1c \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xd3\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xdd\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1ai\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x12\x16\n\x0epk4_max_length\x18\x04 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"i\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"J\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xaa\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x39\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\x9b\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\xed\x06\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x13 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x14 \x01(\x04\x12 \n\x18proposal_default_options\x18\x15 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x16 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x17 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x18 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x19 \x01(\x04\x12\x15\n\rN_measurement\x18\x1a \x01(\x04\x12\n\n\x02kp\x18\x1b \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xbb\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xc5\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1aQ\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -121,8 +121,8 @@ ], containing_type=None, options=None, - serialized_start=4448, - serialized_end=4593, + serialized_start=4435, + serialized_end=4580, ) _sym_db.RegisterEnumDescriptor(_GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE) @@ -155,8 +155,8 @@ ], containing_type=None, options=None, - serialized_start=6313, - serialized_end=6384, + serialized_start=6287, + serialized_end=6358, ) _sym_db.RegisterEnumDescriptor(_NODEINFO_STATE) @@ -1842,22 +1842,15 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='pk4', full_name='qrl.LatticeTxnReq.pk4', index=4, - number=5, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='fee', full_name='qrl.LatticeTxnReq.fee', index=5, - number=6, type=4, cpp_type=4, label=1, + name='fee', full_name='qrl.LatticeTxnReq.fee', index=4, + number=5, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='xmss_pk', full_name='qrl.LatticeTxnReq.xmss_pk', index=6, - number=7, type=12, cpp_type=9, label=1, + name='xmss_pk', full_name='qrl.LatticeTxnReq.xmss_pk', index=5, + number=6, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -1875,7 +1868,7 @@ oneofs=[ ], serialized_start=3509, - serialized_end=3627, + serialized_end=3614, ) @@ -1919,8 +1912,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3629, - serialized_end=3701, + serialized_start=3616, + serialized_end=3688, ) @@ -1950,8 +1943,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3703, - serialized_end=3739, + serialized_start=3690, + serialized_end=3726, ) @@ -2016,8 +2009,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3742, - serialized_end=3902, + serialized_start=3729, + serialized_end=3889, ) @@ -2061,8 +2054,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3904, - serialized_end=3998, + serialized_start=3891, + serialized_end=3985, ) @@ -2099,8 +2092,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4000, - serialized_end=4100, + serialized_start=3987, + serialized_end=4087, ) @@ -2144,8 +2137,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4102, - serialized_end=4192, + serialized_start=4089, + serialized_end=4179, ) @@ -2175,8 +2168,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4194, - serialized_end=4278, + serialized_start=4181, + serialized_end=4265, ) @@ -2228,8 +2221,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4281, - serialized_end=4593, + serialized_start=4268, + serialized_end=4580, ) @@ -2259,8 +2252,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4595, - serialized_end=4683, + serialized_start=4582, + serialized_end=4670, ) @@ -2290,8 +2283,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4685, - serialized_end=4735, + serialized_start=4672, + serialized_end=4722, ) @@ -2321,8 +2314,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4737, - serialized_end=4791, + serialized_start=4724, + serialized_end=4778, ) @@ -2373,8 +2366,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4793, - serialized_end=4875, + serialized_start=4780, + serialized_end=4862, ) @@ -2404,8 +2397,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4877, - serialized_end=4942, + serialized_start=4864, + serialized_end=4929, ) @@ -2442,8 +2435,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4944, - serialized_end=5001, + serialized_start=4931, + serialized_end=4988, ) @@ -2473,8 +2466,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5003, - serialized_end=5068, + serialized_start=4990, + serialized_end=5055, ) @@ -2507,19 +2500,12 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='pk4', full_name='qrl.LatticePKsDetail.pk4', index=3, + name='tx_hash', full_name='qrl.LatticePKsDetail.tx_hash', index=3, number=4, type=12, cpp_type=9, label=1, has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='tx_hash', full_name='qrl.LatticePKsDetail.tx_hash', index=4, - number=5, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -2532,8 +2518,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5070, - serialized_end=5157, + serialized_start=5057, + serialized_end=5131, ) @@ -2563,8 +2549,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5159, - serialized_end=5238, + serialized_start=5133, + serialized_end=5212, ) @@ -2601,8 +2587,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5240, - serialized_end=5290, + serialized_start=5214, + serialized_end=5264, ) @@ -2632,8 +2618,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5292, - serialized_end=5374, + serialized_start=5266, + serialized_end=5348, ) @@ -2663,8 +2649,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5376, - serialized_end=5408, + serialized_start=5350, + serialized_end=5382, ) @@ -2694,8 +2680,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5410, - serialized_end=5443, + serialized_start=5384, + serialized_end=5417, ) @@ -2725,8 +2711,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5445, - serialized_end=5484, + serialized_start=5419, + serialized_end=5458, ) @@ -2756,8 +2742,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5486, - serialized_end=5524, + serialized_start=5460, + serialized_end=5498, ) @@ -2808,8 +2794,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5526, - serialized_end=5624, + serialized_start=5500, + serialized_end=5598, ) @@ -2846,8 +2832,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5626, - serialized_end=5688, + serialized_start=5600, + serialized_end=5662, ) @@ -2891,8 +2877,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5691, - serialized_end=5820, + serialized_start=5665, + serialized_end=5794, ) @@ -2915,8 +2901,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5822, - serialized_end=5836, + serialized_start=5796, + serialized_end=5810, ) @@ -2946,8 +2932,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5838, - serialized_end=5869, + serialized_start=5812, + serialized_end=5843, ) @@ -2977,8 +2963,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5871, - serialized_end=5905, + serialized_start=5845, + serialized_end=5879, ) @@ -3008,8 +2994,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5907, - serialized_end=5948, + serialized_start=5881, + serialized_end=5922, ) @@ -3039,8 +3025,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5950, - serialized_end=5993, + serialized_start=5924, + serialized_end=5967, ) @@ -3070,8 +3056,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5995, - serialized_end=6044, + serialized_start=5969, + serialized_end=6018, ) @@ -3094,8 +3080,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6046, - serialized_end=6068, + serialized_start=6020, + serialized_end=6042, ) @@ -3125,8 +3111,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6070, - serialized_end=6112, + serialized_start=6044, + serialized_end=6086, ) @@ -3206,8 +3192,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6115, - serialized_end=6384, + serialized_start=6089, + serialized_end=6358, ) @@ -3265,8 +3251,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6387, - serialized_end=6520, + serialized_start=6361, + serialized_end=6494, ) @@ -3296,8 +3282,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6522, - serialized_end=6561, + serialized_start=6496, + serialized_end=6535, ) @@ -3327,8 +3313,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6563, - serialized_end=6581, + serialized_start=6537, + serialized_end=6555, ) @@ -3365,8 +3351,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6881, - serialized_end=6926, + serialized_start=6855, + serialized_end=6900, ) _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( @@ -3402,8 +3388,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6928, - serialized_end=6985, + serialized_start=6902, + serialized_end=6959, ) _ADDRESSSTATE = _descriptor.Descriptor( @@ -3488,8 +3474,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6584, - serialized_end=6985, + serialized_start=6558, + serialized_end=6959, ) @@ -3617,8 +3603,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6988, - serialized_end=7439, + serialized_start=6962, + serialized_end=7413, ) @@ -3739,8 +3725,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7442, - serialized_end=7845, + serialized_start=7416, + serialized_end=7819, ) @@ -3770,8 +3756,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7847, - serialized_end=7886, + serialized_start=7821, + serialized_end=7860, ) @@ -3801,8 +3787,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7888, - serialized_end=7914, + serialized_start=7862, + serialized_end=7888, ) @@ -3832,8 +3818,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7916, - serialized_end=7945, + serialized_start=7890, + serialized_end=7919, ) @@ -3863,8 +3849,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7947, - serialized_end=7984, + serialized_start=7921, + serialized_end=7958, ) @@ -3901,8 +3887,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7986, - serialized_end=8037, + serialized_start=7960, + serialized_end=8011, ) @@ -3939,8 +3925,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8039, - serialized_end=8087, + serialized_start=8013, + serialized_end=8061, ) @@ -4026,8 +4012,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8090, - serialized_end=8305, + serialized_start=8064, + serialized_end=8279, ) @@ -4064,8 +4050,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8307, - serialized_end=8412, + serialized_start=8281, + serialized_end=8386, ) @@ -4102,8 +4088,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8483, - serialized_end=8527, + serialized_start=8457, + serialized_end=8501, ) _TRANSACTIONCOUNT = _descriptor.Descriptor( @@ -4132,8 +4118,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8414, - serialized_end=8527, + serialized_start=8388, + serialized_end=8501, ) @@ -4191,8 +4177,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8530, - serialized_end=8675, + serialized_start=8504, + serialized_end=8649, ) @@ -4243,8 +4229,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8678, - serialized_end=8844, + serialized_start=8652, + serialized_end=8818, ) @@ -4288,8 +4274,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8846, - serialized_end=8973, + serialized_start=8820, + serialized_end=8947, ) @@ -4326,8 +4312,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8975, - serialized_end=9025, + serialized_start=8949, + serialized_end=8999, ) @@ -4357,8 +4343,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9027, - serialized_end=9095, + serialized_start=9001, + serialized_end=9069, ) @@ -4402,8 +4388,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9855, - serialized_end=9922, + serialized_start=9829, + serialized_end=9896, ) _TRANSACTION_COINBASE = _descriptor.Descriptor( @@ -4439,8 +4425,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9924, - serialized_end=9967, + serialized_start=9898, + serialized_end=9941, ) _TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -4471,13 +4457,6 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='pk4', full_name='qrl.Transaction.LatticePublicKey.pk4', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=_b(""), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -4490,8 +4469,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9969, - serialized_end=10039, + serialized_start=9943, + serialized_end=10000, ) _TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -4527,8 +4506,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10041, - serialized_end=10089, + serialized_start=10002, + serialized_end=10050, ) _TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -4585,8 +4564,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10091, - serialized_end=10207, + serialized_start=10052, + serialized_end=10168, ) _TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -4629,8 +4608,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10209, - serialized_end=10281, + serialized_start=10170, + serialized_end=10242, ) _TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -4666,8 +4645,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10283, - serialized_end=10331, + serialized_start=10244, + serialized_end=10292, ) _TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( @@ -4710,8 +4689,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10333, - serialized_end=10406, + serialized_start=10294, + serialized_end=10367, ) _TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( @@ -4761,8 +4740,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10408, - serialized_end=10514, + serialized_start=10369, + serialized_end=10475, ) _TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( @@ -4805,8 +4784,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10516, - serialized_end=10588, + serialized_start=10477, + serialized_end=10549, ) _TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( @@ -4835,8 +4814,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10825, - serialized_end=10848, + serialized_start=10786, + serialized_end=10809, ) _TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( @@ -4973,75 +4952,68 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='lattice_pk4_max_length', full_name='qrl.Transaction.ProposalCreate.Config.lattice_pk4_max_length', index=18, + name='foundation_multi_sig_address_threshold_percentage', full_name='qrl.Transaction.ProposalCreate.Config.foundation_multi_sig_address_threshold_percentage', index=18, number=19, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='foundation_multi_sig_address_threshold_percentage', full_name='qrl.Transaction.ProposalCreate.Config.foundation_multi_sig_address_threshold_percentage', index=19, + name='proposal_threshold_per', full_name='qrl.Transaction.ProposalCreate.Config.proposal_threshold_per', index=19, number=20, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='proposal_threshold_per', full_name='qrl.Transaction.ProposalCreate.Config.proposal_threshold_per', index=20, - number=21, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='proposal_default_options', full_name='qrl.Transaction.ProposalCreate.Config.proposal_default_options', index=20, + number=21, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='proposal_default_options', full_name='qrl.Transaction.ProposalCreate.Config.proposal_default_options', index=21, - number=22, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='description_max_length', full_name='qrl.Transaction.ProposalCreate.Config.description_max_length', index=21, + number=22, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='description_max_length', full_name='qrl.Transaction.ProposalCreate.Config.description_max_length', index=22, + name='options_max_number', full_name='qrl.Transaction.ProposalCreate.Config.options_max_number', index=22, number=23, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='options_max_number', full_name='qrl.Transaction.ProposalCreate.Config.options_max_number', index=23, + name='option_max_text_length', full_name='qrl.Transaction.ProposalCreate.Config.option_max_text_length', index=23, number=24, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='option_max_text_length', full_name='qrl.Transaction.ProposalCreate.Config.option_max_text_length', index=24, + name='proposal_config_activation_delay', full_name='qrl.Transaction.ProposalCreate.Config.proposal_config_activation_delay', index=24, number=25, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='proposal_config_activation_delay', full_name='qrl.Transaction.ProposalCreate.Config.proposal_config_activation_delay', index=25, + name='N_measurement', full_name='qrl.Transaction.ProposalCreate.Config.N_measurement', index=25, number=26, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='N_measurement', full_name='qrl.Transaction.ProposalCreate.Config.N_measurement', index=26, + name='kp', full_name='qrl.Transaction.ProposalCreate.Config.kp', index=26, number=27, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='kp', full_name='qrl.Transaction.ProposalCreate.Config.kp', index=27, - number=28, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -5054,8 +5026,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10851, - serialized_end=11760, + serialized_start=10812, + serialized_end=11689, ) _TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( @@ -5084,8 +5056,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11762, - serialized_end=11786, + serialized_start=11691, + serialized_end=11715, ) _TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( @@ -5145,8 +5117,8 @@ name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', index=0, containing_type=None, fields=[]), ], - serialized_start=10591, - serialized_end=11802, + serialized_start=10552, + serialized_end=11731, ) _TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( @@ -5182,8 +5154,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11804, - serialized_end=11854, + serialized_start=11733, + serialized_end=11783, ) _TRANSACTION = _descriptor.Descriptor( @@ -5334,8 +5306,8 @@ name='transactionType', full_name='qrl.Transaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=9098, - serialized_end=11873, + serialized_start=9072, + serialized_end=11802, ) @@ -5414,8 +5386,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11876, - serialized_end=12060, + serialized_start=11805, + serialized_end=11989, ) @@ -5487,8 +5459,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12063, - serialized_end=12246, + serialized_start=11992, + serialized_end=12175, ) @@ -5518,8 +5490,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12248, - serialized_end=12293, + serialized_start=12177, + serialized_end=12222, ) @@ -5549,8 +5521,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12295, - serialized_end=12328, + serialized_start=12224, + serialized_end=12257, ) @@ -5594,8 +5566,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12330, - serialized_end=12395, + serialized_start=12259, + serialized_end=12324, ) @@ -5639,8 +5611,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12397, - serialized_end=12466, + serialized_start=12326, + serialized_end=12395, ) @@ -5684,8 +5656,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12468, - serialized_end=12537, + serialized_start=12397, + serialized_end=12466, ) @@ -5722,8 +5694,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12539, - serialized_end=12610, + serialized_start=12468, + serialized_end=12539, ) @@ -5753,8 +5725,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12773, - serialized_end=12809, + serialized_start=12702, + serialized_end=12738, ) _ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( @@ -5818,8 +5790,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12613, - serialized_end=12809, + serialized_start=12542, + serialized_end=12738, ) @@ -5849,8 +5821,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12811, - serialized_end=12843, + serialized_start=12740, + serialized_end=12772, ) @@ -5894,8 +5866,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12845, - serialized_end=12941, + serialized_start=12774, + serialized_end=12870, ) @@ -5946,8 +5918,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12944, - serialized_end=13073, + serialized_start=12873, + serialized_end=13002, ) @@ -5984,8 +5956,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13075, - serialized_end=13140, + serialized_start=13004, + serialized_end=13069, ) @@ -6029,8 +6001,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13142, - serialized_end=13230, + serialized_start=13071, + serialized_end=13159, ) @@ -6088,8 +6060,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13232, - serialized_end=13358, + serialized_start=13161, + serialized_end=13287, ) @@ -6126,8 +6098,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13360, - serialized_end=13420, + serialized_start=13289, + serialized_end=13349, ) @@ -6157,8 +6129,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13422, - serialized_end=13467, + serialized_start=13351, + serialized_end=13396, ) @@ -6216,8 +6188,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13469, - serialized_end=13593, + serialized_start=13398, + serialized_end=13522, ) @@ -6247,8 +6219,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13595, - serialized_end=13641, + serialized_start=13524, + serialized_end=13570, ) @@ -6292,8 +6264,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13929, - serialized_end=14028, + serialized_start=13858, + serialized_end=13957, ) _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( @@ -6336,8 +6308,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14238, - serialized_end=14357, + serialized_start=14167, + serialized_end=14286, ) _DEVCONFIG_BLOCK = _descriptor.Descriptor( @@ -6394,8 +6366,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14031, - serialized_end=14357, + serialized_start=13960, + serialized_end=14286, ) _DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -6424,8 +6396,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14739, - serialized_end=14768, + serialized_start=14668, + serialized_end=14697, ) _DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -6454,8 +6426,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14770, - serialized_end=14806, + serialized_start=14699, + serialized_end=14735, ) _DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -6491,8 +6463,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14808, - serialized_end=14867, + serialized_start=14737, + serialized_end=14796, ) _DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( @@ -6523,13 +6495,6 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='pk4_max_length', full_name='qrl.DevConfig.Transaction.Lattice.pk4_max_length', index=3, - number=4, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -6542,8 +6507,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14869, - serialized_end=14974, + serialized_start=14798, + serialized_end=14879, ) _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( @@ -6572,8 +6537,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14976, - serialized_end=15026, + serialized_start=14881, + serialized_end=14931, ) _DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( @@ -6637,8 +6602,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15029, - serialized_end=15221, + serialized_start=14934, + serialized_end=15126, ) _DEVCONFIG_TRANSACTION = _descriptor.Descriptor( @@ -6709,8 +6674,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14360, - serialized_end=15221, + serialized_start=14289, + serialized_end=15126, ) _DEVCONFIG_POW = _descriptor.Descriptor( @@ -6746,8 +6711,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15223, - serialized_end=15263, + serialized_start=15128, + serialized_end=15168, ) _DEVCONFIG = _descriptor.Descriptor( @@ -6825,8 +6790,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13644, - serialized_end=15263, + serialized_start=13573, + serialized_end=15168, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -8176,8 +8141,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=15266, - serialized_end=17941, + serialized_start=15171, + serialized_end=17846, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -8533,8 +8498,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=17943, - serialized_end=17953, + serialized_start=17848, + serialized_end=17858, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index a1108a186..327c35e65 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -383,9 +383,8 @@ message LatticeTxnReq { bytes pk1 = 2; bytes pk2 = 3; bytes pk3 = 4; - bytes pk4 = 5; - uint64 fee = 6; - bytes xmss_pk = 7; + uint64 fee = 5; + bytes xmss_pk = 6; } message MiniTransaction { @@ -480,8 +479,7 @@ message LatticePKsDetail { bytes pk1 = 1; bytes pk2 = 2; bytes pk3 = 3; - bytes pk4 = 4; - bytes tx_hash = 5; + bytes tx_hash = 4; } message GetLatticePKsByAddressResp { @@ -789,7 +787,6 @@ message Transaction { bytes pk1 = 1; // kyber_pk bytes pk2 = 2; // dilithium_pk bytes pk3 = 3; // ecdsa_pk - bytes pk4 = 4; // ecies_pk } message Message { @@ -876,19 +873,18 @@ message Transaction { uint64 lattice_pk1_max_length = 16; uint64 lattice_pk2_max_length = 17; uint64 lattice_pk3_max_length = 18; - uint64 lattice_pk4_max_length = 19; - uint64 foundation_multi_sig_address_threshold_percentage = 20; + uint64 foundation_multi_sig_address_threshold_percentage = 19; - uint64 proposal_threshold_per = 21; - repeated string proposal_default_options = 22; - uint64 description_max_length = 23; - uint64 options_max_number = 24; - uint64 option_max_text_length = 25; - uint64 proposal_config_activation_delay = 26; + uint64 proposal_threshold_per = 20; + repeated string proposal_default_options = 21; + uint64 description_max_length = 22; + uint64 options_max_number = 23; + uint64 option_max_text_length = 24; + uint64 proposal_config_activation_delay = 25; - uint64 N_measurement = 27; - uint64 kp = 28; + uint64 N_measurement = 26; + uint64 kp = 27; } message Other { @@ -1081,7 +1077,6 @@ message DevConfig { uint64 pk1_max_length = 1; uint64 pk2_max_length = 2; uint64 pk3_max_length = 3; - uint64 pk4_max_length = 4; } message FoundationMultiSig { diff --git a/src/qrl/services/PublicAPIService.py b/src/qrl/services/PublicAPIService.py index 8e9b1aa00..f0e791ad8 100644 --- a/src/qrl/services/PublicAPIService.py +++ b/src/qrl/services/PublicAPIService.py @@ -278,7 +278,6 @@ def GetLatticeTxn(self, request: qrl_pb2.LatticeTxnReq, context) -> qrl_pb2.Tran tx = self.qrlnode.create_lattice_tx(pk1=request.pk1, pk2=request.pk2, pk3=request.pk3, - pk4=request.pk4, fee=request.fee, xmss_pk=request.xmss_pk, master_addr=request.master_addr) diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index a8fc4bd1a..5d6149e0e 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -717,7 +717,6 @@ def test_add_block4(self, time_mock): lattice_pk = LatticeTransaction.create(pk1=b'alice_pk1', pk2=b'alice_pk2', pk3=b'alice_pk3', - pk4=b'alice_pk4', fee=5, xmss_pk=alice_xmss.pk) lattice_pk.sign(alice_xmss) @@ -758,7 +757,6 @@ def test_add_block4(self, time_mock): lattice_pk2 = LatticeTransaction.create(pk1=b'alice_pk11', pk2=b'alice_pk12', pk3=b'alice_pk13', - pk4=b'alice_pk14', fee=5, xmss_pk=alice_xmss.pk) lattice_pk2.sign(alice_xmss) From 6958a95ffebef8e75fcc1b4b544e9c643672d4ae Mon Sep 17 00:00:00 2001 From: cyyber Date: Tue, 18 Feb 2020 19:11:36 +0530 Subject: [PATCH 45/67] Updated p2p protocol --- src/qrl/core/p2p/p2pPeerManager.py | 69 ++++++++++++++++++++------- src/qrl/core/p2p/p2pfactory.py | 65 ++++++++++++++++++++----- src/qrl/core/p2p/p2pprotocol.py | 13 +++++ src/qrl/core/qrlnode.py | 6 +-- src/qrl/main.py | 1 - tests/core/p2p/test_p2pPeerManager.py | 7 ++- tests/core/p2p/test_p2pfactory.py | 16 ++++--- tests/core/test_qrlnode.py | 4 -- 8 files changed, 131 insertions(+), 50 deletions(-) diff --git a/src/qrl/core/p2p/p2pPeerManager.py b/src/qrl/core/p2p/p2pPeerManager.py index 7cb7ee0e2..975f1bb7a 100644 --- a/src/qrl/core/p2p/p2pPeerManager.py +++ b/src/qrl/core/p2p/p2pPeerManager.py @@ -4,6 +4,7 @@ import os from enum import Enum from typing import Callable, Set, List +from ipaddress import IPv4Address import simplejson as json from pyqryptonight.pyqryptonight import UInt256ToString @@ -40,11 +41,14 @@ def __init__(self): filename=self.banned_peers_filename) self._observable = Observable(self) - self._p2pfactory = None + self._p2p_factory = None def register(self, message_type: EventType, func: Callable): self._observable.register(message_type, func) + def set_p2p_factory(self, p2p_factory): + self._p2p_factory = p2p_factory + @property def known_peer_addresses(self): return self._known_peers @@ -63,7 +67,7 @@ def trusted_peer(self, channel: P2PProtocol): @property def trusted_addresses(self): - return set([peer.peer.full_address for peer in self._p2pfactory.connections if self.trusted_peer(peer)]) + return set([peer.peer.full_address for peer in self._p2p_factory.connections if self.trusted_peer(peer)]) @property def peer_node_status(self): @@ -81,7 +85,7 @@ def load_known_peers(self) -> List[str]: return [IPMetadata.canonical_full_address(fa) for fa in known_peers] def save_known_peers(self, known_peers: List[str]): - tmp = list(known_peers) + tmp = list(known_peers)[:3 * config.user.max_peers_limit] config.create_path(config.user.data_dir) with open(self.peers_path, 'w') as outfile: json.dump(tmp, outfile) @@ -95,9 +99,8 @@ def load_peer_addresses(self) -> None: def extend_known_peers(self, new_peer_addresses: set) -> None: new_addresses = set(new_peer_addresses) - self._known_peers - if self._p2pfactory is not None: - for peer_address in new_addresses: - self._p2pfactory.connect_peer(peer_address) + if self._p2p_factory is not None: + self._p2p_factory.connect_peer(new_addresses) self._known_peers |= set(new_peer_addresses) self.save_known_peers(list(self._known_peers)) @@ -131,7 +134,37 @@ def get_better_difficulty(self, current_cumulative_difficulty): logger.debug('Remote Best Diff : %s', best_cumulative_difficulty) return best_channel + def insert_to_last_connected_peer(self, ip_public_port, connected_peer=False): + known_peers = self.load_known_peers() + connection_set = set() + + if self._p2p_factory is not None: + # Prepare set of connected peers + for conn in self._p2p_factory._peer_connections: + connection_set.add(conn.ip_public_port) + + # Move the current peer to the last position of connected peers + # or to the start position of disconnected peers + try: + index = 0 + if connected_peer: + if ip_public_port in known_peers: + known_peers.remove(ip_public_port) + else: + index = known_peers.index(ip_public_port) + del known_peers[index] + + while index < len(known_peers): + if known_peers[index] not in connection_set: + break + index += 1 + known_peers.insert(index, ip_public_port) + self.save_known_peers(known_peers) + except ValueError: + pass + def remove_channel(self, channel): + self.insert_to_last_connected_peer(channel.ip_public_port) if channel in self._channels: self._channels.remove(channel) if channel in self._peer_node_status: @@ -190,13 +223,24 @@ def handle_peer_list(self, source, message: qrllegacy_pb2.LegacyMessage): if not message.plData.peer_ips: return + # If public port is invalid, ignore rest of the data + if not (0 < message.plData.public_port < 65536): + return + + source.set_public_port(message.plData.public_port) + + self.insert_to_last_connected_peer(source.ip_public_port, True) + sender_peer = IPMetadata(source.peer.ip, message.plData.public_port) - new_peers = self.combine_peer_lists(message.plData.peer_ips, [sender_peer.full_address], check_global=True) - new_peers.discard(source.host.full_address) # Remove local address + # Check if peer list contains global ip, if it was sent by peer from a global ip address + new_peers = self.combine_peer_lists(message.plData.peer_ips, + [sender_peer.full_address], + check_global=IPv4Address(source.peer.ip).is_global) logger.info('%s peers data received: %s', source.peer.ip, new_peers) - self.extend_known_peers(new_peers) + if self._p2p_factory is not None: + self._p2p_factory.add_new_peers_to_peer_q(new_peers) def handle_sync(self, source, message: qrllegacy_pb2.LegacyMessage): P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.SYNC) @@ -273,13 +317,6 @@ def ban_channel(self, channel: P2PProtocol): logger.warning('Banned %s', channel.peer.ip) channel.loseConnection() - def connect_peers(self): - logger.info('<< list: peers_stat = [] # Copying the list of keys, to avoid any change by other thread diff --git a/src/qrl/core/p2p/p2pfactory.py b/src/qrl/core/p2p/p2pfactory.py index 860093bc4..3923bf032 100644 --- a/src/qrl/core/p2p/p2pfactory.py +++ b/src/qrl/core/p2p/p2pfactory.py @@ -92,10 +92,32 @@ def __init__(self, self.peer_blockheight = dict() - reactor.callLater(config.user.monitor_connections_interval, self.monitor_connections) + reactor.callLater(config.user.monitor_connections_interval, + self.monitor_connections) self.p2p_msg_priority = p2p_msg_priority + # Maintains the list of ips in the queue that can be tried to form a new p2p connection + self._peer_q = [] + + def add_new_peers_to_peer_q(self, peer_list): + """ + Checks ip must not already be in the _peer_q and + connection has not already been established from that ip and port + before adding the new set of peer into _peer_q + """ + peer_set = set(peer_list) + for peer_conn in self._peer_connections: + ip_port = peer_conn.peer.full_address + if ip_port in peer_set: + peer_set.remove(ip_port) + + for ip_port in self._peer_q: + if ip_port in peer_set: + peer_set.remove(ip_port) + + self._peer_q.extend(peer_set) + ################################################### ################################################### ################################################### @@ -500,6 +522,7 @@ def add_connection(self, conn_protocol) -> bool: logger.info('Peer limit hit. Disconnecting client %s', conn_protocol.peer) return False + # Remove your own ip address from the connection if conn_protocol.peer.ip == conn_protocol.host.ip and conn_protocol.peer.port == config.user.p2p_public_port: peer_list = [p for p in self._qrl_node.peer_manager.known_peer_addresses if p != conn_protocol.peer.full_address] self._qrl_node.peer_manager.extend_known_peers(peer_list) @@ -522,8 +545,8 @@ def monitor_connections(self): if len(self._peer_connections) == 0: logger.warning('No Connected Peer Found') - reactor.callLater(10, self._qrl_node.peer_manager.connect_peers) - return + known_peers = self._qrl_node.peer_manager.load_known_peers() + self._peer_q.extend(known_peers) connected_peers_set = set() for conn_protocol in self._peer_connections: @@ -531,18 +554,34 @@ def monitor_connections(self): for peer_item in config.user.peer_list: peer_metadata = IPMetadata.from_full_address(peer_item) + if peer_metadata.full_address in self._peer_q: + self._peer_q.remove(peer_metadata.full_address) if peer_metadata.full_address not in connected_peers_set: - self.connect_peer(peer_metadata.full_address) + self.connect_peer([peer_metadata.full_address]) - def connect_peer(self, full_address): - try: - addr = IPMetadata.from_full_address(full_address) + if len(self._peer_connections) >= config.user.max_peers_limit: + return - connected_peers = self.get_connected_peer_addrs() - should_connect = addr.full_address not in connected_peers + if len(self._peer_q) == 0: + return - if should_connect: - reactor.connectTCP(addr.ip, addr.port, self) + peer_address_list = [] + max_length = min(10, config.user.max_peers_limit) + while len(self._peer_q) > 0 and len(peer_address_list) != max_length: + peer_address_list.append(self._peer_q.pop(0)) - except Exception as e: - logger.warning("Could not connect to %s - %s", full_address, str(e)) + self.connect_peer(peer_address_list) + + def connect_peer(self, full_address_list): + for full_address in full_address_list: + try: + addr = IPMetadata.from_full_address(full_address) + + connected_peers = self.get_connected_peer_addrs() + should_connect = addr.full_address not in connected_peers + + if should_connect: + reactor.connectTCP(addr.ip, addr.port, self) + + except Exception as e: + logger.warning("Could not connect to %s - %s", full_address, str(e)) diff --git a/src/qrl/core/p2p/p2pprotocol.py b/src/qrl/core/p2p/p2pprotocol.py index a14485167..a843b523d 100644 --- a/src/qrl/core/p2p/p2pprotocol.py +++ b/src/qrl/core/p2p/p2pprotocol.py @@ -39,6 +39,8 @@ def __init__(self): self._connected_at = ntp.getTime() self._valid_message_count = 0 + self._public_port = 0 + @property def peer(self): return IPMetadata(self.transport.getPeer().host, self.transport.getPeer().port) @@ -47,6 +49,14 @@ def peer(self): def host(self): return IPMetadata(self.transport.getHost().host, self.transport.getHost().port) + @property + def public_port(self): + return self._public_port + + @property + def ip_public_port(self): + return "{}:{}".format(self.transport.getHost().host, self._public_port) + @property def connected_at(self): return self._connected_at @@ -74,6 +84,9 @@ def tx_manager(self): # FIXME: this is breaking encapsulation return self.factory._qrl_node.tx_manager + def set_public_port(self, public_port): + self._public_port = public_port + def register(self, message_type, func: Callable): self._observable.register(message_type, func) diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 29390d964..42651e540 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -41,7 +41,6 @@ def __init__(self, mining_address: bytes): self.peer_manager = P2PPeerManager() self.peer_manager.load_peer_addresses() - self.peer_manager.register(P2PPeerManager.EventType.NO_PEERS, self.connect_peers) self.p2pchain_manager = P2PChainManager() @@ -152,9 +151,6 @@ def coin_supply_max(self): def get_peers_stat(self) -> list: return self.peer_manager.get_peers_stat() - def connect_peers(self): - self.peer_manager.connect_peers() - #################################################### #################################################### #################################################### @@ -203,7 +199,7 @@ def start_listening(self): sync_state=self.sync_state, qrl_node=self) # FIXME: Try to avoid cyclic references - self.peer_manager._p2pfactory = self._p2pfactory + self.peer_manager.set_p2p_factory(self._p2pfactory) self._p2pfactory.start_listening() #################################################### diff --git a/src/qrl/main.py b/src/qrl/main.py index 2370cc228..6b2eab0c7 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -129,7 +129,6 @@ def main(): admin_service, grpc_service, mining_service, debug_service = start_services(qrlnode) qrlnode.start_listening() - qrlnode.connect_peers() qrlnode.start_pow(args.mining_thread_count) diff --git a/tests/core/p2p/test_p2pPeerManager.py b/tests/core/p2p/test_p2pPeerManager.py index 9b74071b2..36edebc3f 100644 --- a/tests/core/p2p/test_p2pPeerManager.py +++ b/tests/core/p2p/test_p2pPeerManager.py @@ -151,13 +151,13 @@ def test_update_peer_addresses_also_connects_to_new_peers(self, logger): """ extend_known_peers() not only writes out, it automatically connects to any new peers. """ - self.peer_manager._p2pfactory = Mock() + self.peer_manager._p2p_factory = Mock() self.peer_manager._known_peers = {'1.1.1.1:9000'} with set_qrl_dir('no_data') as tempdir: self.peer_manager.peers_path = os.path.join(tempdir, config.dev.peers_filename) self.peer_manager.extend_known_peers({'2.2.2.2:9000'}) - self.peer_manager._p2pfactory.connect_peer.assert_called_once_with('2.2.2.2:9000') + self.peer_manager._p2p_factory.connect_peer.assert_called_once_with({'2.2.2.2:9000'}) def test_remove_channel(self): """ @@ -286,11 +286,10 @@ def test_handle_peer_list_works(self, logger): channel = make_channel() channel.host = IPMetadata('187.0.0.1', 9000) channel.peer = IPMetadata('187.0.0.2', 9000) + channel.ip_public_port = '187.0.0.1:9000' # handle_peer_list() will call extend_known_peers(), so we gotta mock it out. It's tested elsewhere anyway. - self.peer_manager.extend_known_peers = Mock(autospec=P2PPeerManager.extend_known_peers) self.peer_manager.handle_peer_list(channel, peer_list_message) - self.peer_manager.extend_known_peers.assert_called_once_with({channel.peer.full_address}) @patch('qrl.core.p2p.p2pPeerManager.logger', autospec=True) def test_handle_peer_list_empty_peer_list_message(self, logger): diff --git a/tests/core/p2p/test_p2pfactory.py b/tests/core/p2p/test_p2pfactory.py index 3944939c3..882f2d08b 100644 --- a/tests/core/p2p/test_p2pfactory.py +++ b/tests/core/p2p/test_p2pfactory.py @@ -56,6 +56,7 @@ def setUp(self): self.m_qrlnode = Mock(autospec=QRLNode, name='Fake QRLNode') self.m_qrlnode.peer_manager = Mock(autospec=P2PPeerManager, name='Fake PeerManager') self.m_qrlnode.peer_manager.is_banned.return_value = False + self.m_qrlnode.peer_manager.load_known_peers.return_value = ['8.8.8.8', '9.9.9.9'] self.channel_1 = Mock(autospec=P2PProtocol, name='mock Channel 1', @@ -175,22 +176,22 @@ def test_connect_peer(self, m_reactor, m_logger): """ connecting to previously unconnected peers should work. """ - self.factory.connect_peer('127.0.0.1:9000') + self.factory.connect_peer(['127.0.0.1:9000']) m_reactor.connectTCP.assert_called_once() m_reactor.connectTCP.reset_mock() - self.factory.connect_peer('5.5.5.5:9000') + self.factory.connect_peer(['5.5.5.5:9000']) m_reactor.connectTCP.assert_called_once() m_reactor.connectTCP.reset_mock() - self.factory.connect_peer('5.5.5.5') + self.factory.connect_peer(['5.5.5.5']) m_reactor.connectTCP.assert_called_once() def test_connect_peer_bad_ipport(self, m_reactor, m_logger): - self.factory.connect_peer('1.1.1.1:65536') + self.factory.connect_peer(['1.1.1.1:65536']) m_reactor.connectTCP.assert_not_called() - self.factory.connect_peer('1.1.1.1:') + self.factory.connect_peer(['1.1.1.1:']) m_reactor.connectTCP.assert_not_called() def test_monitor_connections(self, m_reactor, m_logger): @@ -205,8 +206,9 @@ def test_monitor_connections(self, m_reactor, m_logger): self.factory.connect_peer = Mock(autospec=P2PFactory.connect_peer) with patch('qrl.core.p2p.p2pfactory.config', autospec=True) as m_config: m_config.user.peer_list = ['1.1.1.1', '2.2.2.2', '3.3.3.3', '4.4.4.4'] + m_config.user.max_peers_limit = 100 self.factory.monitor_connections() - self.factory.connect_peer.assert_called_once_with(make_address('4.4.4.4')) + self.factory.connect_peer.assert_called_once_with([make_address('4.4.4.4')]) def test_monitor_connections_no_peers_connected(self, m_reactor, m_logger): self.factory.remove_connection(self.channel_1) @@ -215,7 +217,7 @@ def test_monitor_connections_no_peers_connected(self, m_reactor, m_logger): self.factory.connect_peer = Mock(autospec=P2PFactory.connect_peer) self.factory.monitor_connections() - self.factory.connect_peer.assert_not_called() + self.assertEqual(self.factory.connect_peer.call_count, 5) def test_request_full_message(self, m_reactor, m_logger): """ diff --git a/tests/core/test_qrlnode.py b/tests/core/test_qrlnode.py index f15f3ab1c..211853f42 100644 --- a/tests/core/test_qrlnode.py +++ b/tests/core/test_qrlnode.py @@ -541,7 +541,3 @@ def test_coin_supply_max(self): def test_get_peers_stat(self): self.qrlnode.get_peers_stat() self.m_peer_manager.get_peers_stat.assert_called_once() - - def test_connect_peers(self): - self.qrlnode.connect_peers() - self.m_peer_manager.connect_peers.assert_called_once() From 7c8cced1e6650e98b0caf31e6121c29c4eba4ab5 Mon Sep 17 00:00:00 2001 From: cyyber Date: Tue, 18 Feb 2020 19:25:54 +0530 Subject: [PATCH 46/67] Fix: Replaced getHost by getPeer for ip_public_port in p2pprotocol --- src/qrl/core/p2p/p2pprotocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qrl/core/p2p/p2pprotocol.py b/src/qrl/core/p2p/p2pprotocol.py index a843b523d..b81395c49 100644 --- a/src/qrl/core/p2p/p2pprotocol.py +++ b/src/qrl/core/p2p/p2pprotocol.py @@ -55,7 +55,7 @@ def public_port(self): @property def ip_public_port(self): - return "{}:{}".format(self.transport.getHost().host, self._public_port) + return "{}:{}".format(self.transport.getPeer().host, self._public_port) @property def connected_at(self): From c9f58aa21017846e60a91e655ee124fee204425b Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 19 Feb 2020 15:38:55 +0530 Subject: [PATCH 47/67] Added node version check for compatibility after hard fork activation --- src/qrl/core/p2p/p2pPeerManager.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/qrl/core/p2p/p2pPeerManager.py b/src/qrl/core/p2p/p2pPeerManager.py index 975f1bb7a..debc0f269 100644 --- a/src/qrl/core/p2p/p2pPeerManager.py +++ b/src/qrl/core/p2p/p2pPeerManager.py @@ -182,6 +182,17 @@ def new_channel(self, channel): channel.register(qrllegacy_pb2.LegacyMessage.SYNC, self.handle_sync) channel.register(qrllegacy_pb2.LegacyMessage.P2P_ACK, self.handle_p2p_acknowledgement) + def _get_version_compatibility(self, version) -> bool: + if self._p2p_factory.chain_height >= config.dev.hard_fork_heights[0]: + try: + major_version = version.split(".")[0] + if int(major_version) < 2: + return False + except Exception: + return False + + return True + def handle_version(self, source, message: qrllegacy_pb2.LegacyMessage): """ Version @@ -206,6 +217,13 @@ def handle_version(self, source, message: qrllegacy_pb2.LegacyMessage): message.veData.version, message.veData.genesis_prev_hash) + if not self._get_version_compatibility(message.veData.version): + logger.warning("Disconnecting from Peer %s running incompatible node version %s", + source.peer.ip, + message.veData.version) + source.loseConnection() + return + source.rate_limit = min(config.user.peer_rate_limit, message.veData.rate_limit) if message.veData.genesis_prev_hash != config.user.genesis_prev_headerhash: @@ -278,7 +296,6 @@ def broadcast_chain_state(self, node_chain_state: qrl_pb2.NodeChainState): self._observable.notify(ObservableEvent(self.EventType.NO_PEERS)) def handle_chain_state(self, source, message: qrllegacy_pb2.LegacyMessage): - # FIXME: Not sure this belongs to peer management P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.CHAINSTATE) message.chainStateData.timestamp = ntp.getTime() # Receiving time @@ -292,6 +309,13 @@ def handle_chain_state(self, source, message: qrllegacy_pb2.LegacyMessage): self._peer_node_status[source] = message.chainStateData + if not self._get_version_compatibility(message.chainStateData.version): + logger.warning("Disconnecting from Peer %s running incompatible node version %s", + source.peer.ip, + message.veData.version) + source.loseConnection() + return + def handle_p2p_acknowledgement(self, source, message: qrllegacy_pb2.LegacyMessage): P2PBaseObserver._validate_message(message, qrllegacy_pb2.LegacyMessage.P2P_ACK) From b9c66e01e9816391fb424efa052ba5fe259f0f77 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 19 Feb 2020 15:47:35 +0530 Subject: [PATCH 48/67] Ignore compatibility check if p2p_factory has not been initialized --- src/qrl/core/p2p/p2pPeerManager.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qrl/core/p2p/p2pPeerManager.py b/src/qrl/core/p2p/p2pPeerManager.py index debc0f269..72f2665dc 100644 --- a/src/qrl/core/p2p/p2pPeerManager.py +++ b/src/qrl/core/p2p/p2pPeerManager.py @@ -183,6 +183,9 @@ def new_channel(self, channel): channel.register(qrllegacy_pb2.LegacyMessage.P2P_ACK, self.handle_p2p_acknowledgement) def _get_version_compatibility(self, version) -> bool: + if self._p2p_factory is None: + return True + if self._p2p_factory.chain_height >= config.dev.hard_fork_heights[0]: try: major_version = version.split(".")[0] From 0430733c33f479c8947cd16b32763527316cec9c Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 19 Feb 2020 16:05:34 +0530 Subject: [PATCH 49/67] Flake 8 fix --- src/qrl/core/p2p/p2pPeerManager.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qrl/core/p2p/p2pPeerManager.py b/src/qrl/core/p2p/p2pPeerManager.py index 72f2665dc..7dd68ffa5 100644 --- a/src/qrl/core/p2p/p2pPeerManager.py +++ b/src/qrl/core/p2p/p2pPeerManager.py @@ -182,10 +182,9 @@ def new_channel(self, channel): channel.register(qrllegacy_pb2.LegacyMessage.SYNC, self.handle_sync) channel.register(qrllegacy_pb2.LegacyMessage.P2P_ACK, self.handle_p2p_acknowledgement) - def _get_version_compatibility(self, version) -> bool: + def _get_version_compatibility(self, version) -> bool: if self._p2p_factory is None: return True - if self._p2p_factory.chain_height >= config.dev.hard_fork_heights[0]: try: major_version = version.split(".")[0] From b6a53cd3cdeb4994ed475a4136fcba78e0f9dbef Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 21 Feb 2020 17:19:45 +0530 Subject: [PATCH 50/67] Added arguments for grpcProxy and wallet daemon --- src/qrl/daemon/walletd.py | 24 ++++++++++++++++++++++++ src/qrl/grpcProxy.py | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/qrl/daemon/walletd.py b/src/qrl/daemon/walletd.py index f45ce5caa..894afc1ee 100644 --- a/src/qrl/daemon/walletd.py +++ b/src/qrl/daemon/walletd.py @@ -3,6 +3,7 @@ # file LICENSE or http://www.opensource.org/licenses/mit-license.php. from concurrent.futures import ThreadPoolExecutor +import argparse import os import logging import grpc @@ -946,7 +947,30 @@ def run(): wallet_server.stop(0) +def parse_arguments(): + parser = argparse.ArgumentParser(description='QRL node') + parser.add_argument('--qrldir', '-d', dest='qrl_dir', default=config.user.qrl_dir, + help="Use a different directory for node data/configuration") + parser.add_argument('--network-type', dest='network_type', choices=['mainnet', 'testnet'], + default='mainnet', required=False, help="Runs QRL Testnet Node") + return parser.parse_args() + + def main(): + args = parse_arguments() + + qrl_dir_post_fix = '' + copy_files = [] + if args.network_type == 'testnet': + qrl_dir_post_fix = '-testnet' + package_directory = os.path.dirname(os.path.abspath(__file__)) + copy_files.append(os.path.join(package_directory, '../network/testnet/genesis.yml')) + copy_files.append(os.path.join(package_directory, '../network/testnet/config.yml')) + + config.user.qrl_dir = os.path.expanduser(os.path.normpath(args.qrl_dir) + qrl_dir_post_fix) + config.create_path(config.user.qrl_dir, copy_files) + config.user.load_yaml(config.user.config_path) + daemon = Daemonize(app="qrl_walletd", pid=pid, action=run) daemon.start() diff --git a/src/qrl/grpcProxy.py b/src/qrl/grpcProxy.py index b1d2dd74b..92262c023 100644 --- a/src/qrl/grpcProxy.py +++ b/src/qrl/grpcProxy.py @@ -1,6 +1,8 @@ # coding=utf-8 # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. +import argparse +import os import simplejson as json import grpc from google.protobuf.json_format import MessageToJson @@ -226,7 +228,30 @@ def transfer(destinations, fee, mixin, unlock_time): app.add_url_rule('/json_rpc', 'api', api.as_view(), methods=['POST']) +def parse_arguments(): + parser = argparse.ArgumentParser(description='QRL node') + parser.add_argument('--qrldir', '-d', dest='qrl_dir', default=config.user.qrl_dir, + help="Use a different directory for node data/configuration") + parser.add_argument('--network-type', dest='network_type', choices=['mainnet', 'testnet'], + default='mainnet', required=False, help="Runs QRL Testnet Node") + return parser.parse_args() + + def main(): + args = parse_arguments() + + qrl_dir_post_fix = '' + copy_files = [] + if args.network_type == 'testnet': + qrl_dir_post_fix = '-testnet' + package_directory = os.path.dirname(os.path.abspath(__file__)) + copy_files.append(os.path.join(package_directory, 'network/testnet/genesis.yml')) + copy_files.append(os.path.join(package_directory, 'network/testnet/config.yml')) + + config.user.qrl_dir = os.path.expanduser(os.path.normpath(args.qrl_dir) + qrl_dir_post_fix) + config.create_path(config.user.qrl_dir, copy_files) + config.user.load_yaml(config.user.config_path) + global payment_slaves, payment_xmss global mining_stub, public_stub mining_stub = qrlmining_pb2_grpc.MiningAPIStub(grpc.insecure_channel('{0}:{1}'.format(config.user.mining_api_host, From 8a3547315e0de0fd882c63bc5a93b53aa566f074 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 22 Feb 2020 18:02:32 +0530 Subject: [PATCH 51/67] API fixes & maintaining token list associated with an address --- src/qrl/core/ChainManager.py | 32 ++++++++++++++------ src/qrl/core/txs/TransferTokenTransaction.py | 1 + 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 357bf9d8a..685dd6ffd 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -104,33 +104,46 @@ def get_address_state(self, address: bytes) -> AddressState: Transform Optimized Address State into Older Address State format """ optimized_address_state = self.get_optimized_address_state(address) - ots_bitfield = [b'\x00'] * int(ceil((2 ** optimized_address_state.height) / 8)) + ots_bitfield = [b'\x00'] * max(1024, int(ceil((2 ** optimized_address_state.height) / 8))) + transaction_hashes = list() tokens = dict() slave_pks_access_type = dict() - max_bitfield_page = (2 ** optimized_address_state.height) // config.dev.ots_tracking_per_page + max_bitfield_page = ceil((2 ** optimized_address_state.height) / config.dev.ots_tracking_per_page) offset = 0 for page in range(1, max_bitfield_page + 1): page_data = self.get_bitfield(address, page) for data in page_data: + if offset >= len(ots_bitfield): + break ots_bitfield[offset] = data offset += 1 offset = (page - 1) * config.dev.ots_tracking_per_page - for page in range(1, optimized_address_state.tokens_count() + 1): - page_data = self.get_token_transaction_hashes(address, page) + max_transaction_hash_page = ceil(optimized_address_state.transaction_hash_count() / config.dev.data_per_page) + + for page in range(0, max_transaction_hash_page + 1): + page_data = self.get_transaction_hashes(address, page * config.dev.data_per_page) + transaction_hashes.extend(page_data) + + max_token_page = ceil(optimized_address_state.tokens_count() / config.dev.data_per_page) + + for page in range(0, max_token_page + 1): + page_data = self.get_token_transaction_hashes(address, page * config.dev.data_per_page) for token_txn_hash in page_data: token_balance = self.get_token(address, token_txn_hash) tokens[token_txn_hash] = token_balance.balance - for page in range(1, optimized_address_state.slaves_count() + 1): - page_data = self.get_slave_transaction_hashes(address, page) + max_slave_page = ceil(optimized_address_state.slaves_count() / config.dev.data_per_page) + + for page in range(0, max_slave_page + 1): + page_data = self.get_slave_transaction_hashes(address, page * config.dev.data_per_page) for slave_txn_hash in page_data: tx, _ = self.get_tx_metadata(slave_txn_hash) for slave_pk in tx.slave_pks: slave_meta_data = self.get_slave_pk_access_type(address, slave_pk) - slave_pks_access_type[slave_pk] = slave_meta_data.access_type + slave_pks_access_type[str(slave_pk)] = slave_meta_data.access_type addr_state = AddressState.create(address=optimized_address_state.address, nonce=optimized_address_state.nonce, @@ -139,6 +152,7 @@ def get_address_state(self, address: bytes) -> AddressState: tokens=tokens, slave_pks_access_type=slave_pks_access_type, ots_counter=0) + addr_state.transaction_hashes.extend(transaction_hashes) return addr_state @@ -177,12 +191,12 @@ def get_multi_sig_spend_txn_hashes(self, multi_sig_address: bytes, item_index: i return p.get_paginated_data(multi_sig_address, item_index) def get_token_transaction_hashes(self, address: bytes, item_index: int) -> list: - p = PaginatedData(b'p_token', False, self._state._db) + p = PaginatedData(b'p_tokens', False, self._state._db) with self.lock: return p.get_paginated_data(address, item_index) def get_slave_transaction_hashes(self, address: bytes, item_index: int) -> list: - p = PaginatedData(b'p_slave', False, self._state._db) + p = PaginatedData(b'p_slaves', False, self._state._db) with self.lock: return p.get_paginated_data(address, item_index) diff --git a/src/qrl/core/txs/TransferTokenTransaction.py b/src/qrl/core/txs/TransferTokenTransaction.py index 8272e4018..d2e345b20 100644 --- a/src/qrl/core/txs/TransferTokenTransaction.py +++ b/src/qrl/core/txs/TransferTokenTransaction.py @@ -174,6 +174,7 @@ def apply(self, if self.addr_from != addr_to: state_container.paginated_tx_hash.insert(address_state, self.txhash) + state_container.paginated_tokens_hash.insert(address_state, self.txhash) return self._apply_state_changes_for_PK(state_container) From d37fe785f07d399332976613de571291da5f871d Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 22 Feb 2020 18:14:08 +0530 Subject: [PATCH 52/67] Fix: Avoid adding same token tx hash into paginated token hash multiple times --- src/qrl/core/txs/TransferTokenTransaction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qrl/core/txs/TransferTokenTransaction.py b/src/qrl/core/txs/TransferTokenTransaction.py index d2e345b20..79a99a9a5 100644 --- a/src/qrl/core/txs/TransferTokenTransaction.py +++ b/src/qrl/core/txs/TransferTokenTransaction.py @@ -170,11 +170,12 @@ def apply(self, self.token_txhash)] = TokenBalance(balance=0, decimals=decimals, delete=False) + state_container.paginated_tokens_hash.insert(address_state, self.txhash) + state_container.tokens.data[(addr_to, self.token_txhash)].balance += amount if self.addr_from != addr_to: state_container.paginated_tx_hash.insert(address_state, self.txhash) - state_container.paginated_tokens_hash.insert(address_state, self.txhash) return self._apply_state_changes_for_PK(state_container) From 70055c652cc691163514437050670cca5fa85007 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 22 Feb 2020 18:32:50 +0530 Subject: [PATCH 53/67] Fix: Unit Tests for get_address_state API --- tests/services/test_PublicAPIService.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/services/test_PublicAPIService.py b/tests/services/test_PublicAPIService.py index d1453ecba..88fa28269 100644 --- a/tests/services/test_PublicAPIService.py +++ b/tests/services/test_PublicAPIService.py @@ -178,8 +178,7 @@ def test_getAddressState(self): self.assertEqual(alice_xmss.address, response.state.address) self.assertEqual(25, response.state.nonce) self.assertEqual(10, response.state.balance) - count = int(ceil((2 ** optimized_address_state.height) / 8)) - self.assertEqual([b'\x00'] * count, response.state.ots_bitfield) + self.assertEqual([b'\x00'] * config.dev.ots_bitfield_size, response.state.ots_bitfield) self.assertEqual([], response.state.transaction_hashes) def test_getObject(self): From 4dbdcc40d69ac16d09b39fafeb44266062a898dd Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 22 Feb 2020 18:36:55 +0530 Subject: [PATCH 54/67] Fix flake8 --- tests/services/test_PublicAPIService.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/services/test_PublicAPIService.py b/tests/services/test_PublicAPIService.py index 88fa28269..a148cfab0 100644 --- a/tests/services/test_PublicAPIService.py +++ b/tests/services/test_PublicAPIService.py @@ -2,7 +2,6 @@ # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. import heapq -from math import ceil from unittest import TestCase from grpc import ServicerContext, StatusCode From b03a78fe44ed114b39434b1582b2a3642d5b68a9 Mon Sep 17 00:00:00 2001 From: cyyber Date: Mon, 24 Feb 2020 19:20:48 +0530 Subject: [PATCH 55/67] State maintenance of incoming messages via message txn --- src/qrl/core/ChainManager.py | 6 + src/qrl/core/OptimizedAddressState.py | 11 + src/qrl/core/StateContainer.py | 1 + src/qrl/core/txs/MessageTransaction.py | 2 + src/qrl/generated/qrl_pb2.py | 289 +++++++++++++------------ src/qrl/protos/qrl.proto | 9 +- 6 files changed, 173 insertions(+), 145 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 685dd6ffd..684f78186 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -926,6 +926,8 @@ def _apply_state_changes(self, block, batch) -> bool: state_container.paginated_multi_sig_spend.put_paginated_data(batch) + state_container.paginated_inbox_message.put_paginated_data(batch) + # TODO: Add Key value storage to lattice pk state_container.tokens.put(batch) # This is needed to show list of tokens owned by an address on Web Wallet @@ -1029,6 +1031,10 @@ def revert_state_changes(self, block, batch) -> bool: logger.warning("Failed Revert Multi Sig Spend") return False + if not state_container.paginated_inbox_message.put_paginated_data(batch): + logger.warning("Failed Revert Inbox Message") + return False + if not state_container.paginated_multisig_address.put_paginated_data(batch): logger.warning("Failed Revert Multi Sig Addresses") return False diff --git a/src/qrl/core/OptimizedAddressState.py b/src/qrl/core/OptimizedAddressState.py index 05c102111..f92db37e8 100644 --- a/src/qrl/core/OptimizedAddressState.py +++ b/src/qrl/core/OptimizedAddressState.py @@ -33,6 +33,8 @@ def __init__(self, protobuf_block=None): self.update_multi_sig_address_count), b"p_multi_sig_spend": counter_mapping(self.multi_sig_spend_count, self.update_multi_sig_spend_count), + b"p_inbox_message": counter_mapping(self.inbox_message_count, + self.update_inbox_message_count), } @staticmethod @@ -111,6 +113,9 @@ def multi_sig_address_count(self): def multi_sig_spend_count(self): return self._data.multi_sig_spend_count + def inbox_message_count(self): + return self._data.inbox_message_count + def get_counter_by_name(self, name: bytes): return self._counter_by_name[name].get() @@ -190,6 +195,12 @@ def update_multi_sig_spend_count(self, value=1, subtract=False): else: self._data.multi_sig_spend_count += value + def update_inbox_message_count(self, value=1, subtract=False): + if subtract: + self._data.inbox_message_count -= value + else: + self._data.inbox_message_count += value + def increase_nonce(self): self._data.nonce += 1 diff --git a/src/qrl/core/StateContainer.py b/src/qrl/core/StateContainer.py index 784bd75a1..c3b9a0b38 100644 --- a/src/qrl/core/StateContainer.py +++ b/src/qrl/core/StateContainer.py @@ -27,6 +27,7 @@ def __init__(self, self.paginated_lattice_pk = PaginatedData(b'p_lattice_pk', write_access, my_db) self.paginated_multisig_address = PaginatedData(b'p_multisig_address', write_access, my_db) self.paginated_multi_sig_spend = PaginatedData(b'p_multi_sig_spend', write_access, my_db) + self.paginated_inbox_message = PaginatedData(b'p_inbox_message', write_access, my_db) self.addresses_state = addresses_state diff --git a/src/qrl/core/txs/MessageTransaction.py b/src/qrl/core/txs/MessageTransaction.py index 3190a3b22..5c81c5c7b 100644 --- a/src/qrl/core/txs/MessageTransaction.py +++ b/src/qrl/core/txs/MessageTransaction.py @@ -98,6 +98,7 @@ def apply(self, address_state = state_container.addresses_state[self.addr_to] if self.addr_to not in (self.addr_from, addr_from_pk): state_container.paginated_tx_hash.insert(address_state, self.txhash) + state_container.paginated_inbox_message.insert(address_state, self.txhash) return self._apply_state_changes_for_PK(state_container) @@ -113,5 +114,6 @@ def revert(self, address_state = state_container.addresses_state[self.addr_to] if self.addr_to not in (self.addr_from, addr_from_pk): state_container.paginated_tx_hash.remove(address_state, self.txhash) + state_container.paginated_inbox_message.remove(address_state, self.txhash) return self._revert_state_changes_for_PK(state_container) diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index 62ccf975a..571e133a7 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"i\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"J\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xc3\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0c \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\r \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0e \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0f \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xaa\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x39\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\x9b\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\xed\x06\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x13 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x14 \x01(\x04\x12 \n\x18proposal_default_options\x18\x15 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x16 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x17 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x18 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x19 \x01(\x04\x12\x15\n\rN_measurement\x18\x1a \x01(\x04\x12\n\n\x02kp\x18\x1b \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xbb\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xc5\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1aQ\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"i\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"J\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xe0\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12\x1b\n\x13inbox_message_count\x18\x0c \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\r \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0e \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0f \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x10 \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xaa\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x39\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\x9b\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\xed\x06\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x13 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x14 \x01(\x04\x12 \n\x18proposal_default_options\x18\x15 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x16 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x17 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x18 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x19 \x01(\x04\x12\x15\n\rN_measurement\x18\x1a \x01(\x04\x12\n\n\x02kp\x18\x1b \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xbb\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xc5\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1aQ\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -3564,29 +3564,36 @@ is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='foundation_multi_sig_spend_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_spend_txn_hash', index=11, - number=12, type=12, cpp_type=9, label=3, - has_default_value=False, default_value=[], + name='inbox_message_count', full_name='qrl.OptimizedAddressState.inbox_message_count', index=11, + number=12, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='foundation_multi_sig_vote_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_vote_txn_hash', index=12, + name='foundation_multi_sig_spend_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_spend_txn_hash', index=12, number=13, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='unvotes', full_name='qrl.OptimizedAddressState.unvotes', index=13, + name='foundation_multi_sig_vote_txn_hash', full_name='qrl.OptimizedAddressState.foundation_multi_sig_vote_txn_hash', index=13, number=14, type=12, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='proposal_vote_stats', full_name='qrl.OptimizedAddressState.proposal_vote_stats', index=14, - number=15, type=11, cpp_type=10, label=3, + name='unvotes', full_name='qrl.OptimizedAddressState.unvotes', index=14, + number=15, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proposal_vote_stats', full_name='qrl.OptimizedAddressState.proposal_vote_stats', index=15, + number=16, type=11, cpp_type=10, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, @@ -3604,7 +3611,7 @@ oneofs=[ ], serialized_start=6962, - serialized_end=7413, + serialized_end=7442, ) @@ -3725,8 +3732,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7416, - serialized_end=7819, + serialized_start=7445, + serialized_end=7848, ) @@ -3756,8 +3763,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7821, - serialized_end=7860, + serialized_start=7850, + serialized_end=7889, ) @@ -3787,8 +3794,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7862, - serialized_end=7888, + serialized_start=7891, + serialized_end=7917, ) @@ -3818,8 +3825,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7890, - serialized_end=7919, + serialized_start=7919, + serialized_end=7948, ) @@ -3849,8 +3856,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7921, - serialized_end=7958, + serialized_start=7950, + serialized_end=7987, ) @@ -3887,8 +3894,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7960, - serialized_end=8011, + serialized_start=7989, + serialized_end=8040, ) @@ -3925,8 +3932,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8013, - serialized_end=8061, + serialized_start=8042, + serialized_end=8090, ) @@ -4012,8 +4019,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8064, - serialized_end=8279, + serialized_start=8093, + serialized_end=8308, ) @@ -4050,8 +4057,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8281, - serialized_end=8386, + serialized_start=8310, + serialized_end=8415, ) @@ -4088,8 +4095,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8457, - serialized_end=8501, + serialized_start=8486, + serialized_end=8530, ) _TRANSACTIONCOUNT = _descriptor.Descriptor( @@ -4118,8 +4125,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8388, - serialized_end=8501, + serialized_start=8417, + serialized_end=8530, ) @@ -4177,8 +4184,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8504, - serialized_end=8649, + serialized_start=8533, + serialized_end=8678, ) @@ -4229,8 +4236,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8652, - serialized_end=8818, + serialized_start=8681, + serialized_end=8847, ) @@ -4274,8 +4281,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8820, - serialized_end=8947, + serialized_start=8849, + serialized_end=8976, ) @@ -4312,8 +4319,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8949, - serialized_end=8999, + serialized_start=8978, + serialized_end=9028, ) @@ -4343,8 +4350,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9001, - serialized_end=9069, + serialized_start=9030, + serialized_end=9098, ) @@ -4388,8 +4395,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9829, - serialized_end=9896, + serialized_start=9858, + serialized_end=9925, ) _TRANSACTION_COINBASE = _descriptor.Descriptor( @@ -4425,8 +4432,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9898, - serialized_end=9941, + serialized_start=9927, + serialized_end=9970, ) _TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -4469,8 +4476,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9943, - serialized_end=10000, + serialized_start=9972, + serialized_end=10029, ) _TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -4506,8 +4513,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10002, - serialized_end=10050, + serialized_start=10031, + serialized_end=10079, ) _TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -4564,8 +4571,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10052, - serialized_end=10168, + serialized_start=10081, + serialized_end=10197, ) _TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -4608,8 +4615,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10170, - serialized_end=10242, + serialized_start=10199, + serialized_end=10271, ) _TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -4645,8 +4652,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10244, - serialized_end=10292, + serialized_start=10273, + serialized_end=10321, ) _TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( @@ -4689,8 +4696,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10294, - serialized_end=10367, + serialized_start=10323, + serialized_end=10396, ) _TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( @@ -4740,8 +4747,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10369, - serialized_end=10475, + serialized_start=10398, + serialized_end=10504, ) _TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( @@ -4784,8 +4791,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10477, - serialized_end=10549, + serialized_start=10506, + serialized_end=10578, ) _TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( @@ -4814,8 +4821,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10786, - serialized_end=10809, + serialized_start=10815, + serialized_end=10838, ) _TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( @@ -5026,8 +5033,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10812, - serialized_end=11689, + serialized_start=10841, + serialized_end=11718, ) _TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( @@ -5056,8 +5063,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11691, - serialized_end=11715, + serialized_start=11720, + serialized_end=11744, ) _TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( @@ -5117,8 +5124,8 @@ name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', index=0, containing_type=None, fields=[]), ], - serialized_start=10552, - serialized_end=11731, + serialized_start=10581, + serialized_end=11760, ) _TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( @@ -5154,8 +5161,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11733, - serialized_end=11783, + serialized_start=11762, + serialized_end=11812, ) _TRANSACTION = _descriptor.Descriptor( @@ -5306,8 +5313,8 @@ name='transactionType', full_name='qrl.Transaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=9072, - serialized_end=11802, + serialized_start=9101, + serialized_end=11831, ) @@ -5386,8 +5393,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11805, - serialized_end=11989, + serialized_start=11834, + serialized_end=12018, ) @@ -5459,8 +5466,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11992, - serialized_end=12175, + serialized_start=12021, + serialized_end=12204, ) @@ -5490,8 +5497,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12177, - serialized_end=12222, + serialized_start=12206, + serialized_end=12251, ) @@ -5521,8 +5528,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12224, - serialized_end=12257, + serialized_start=12253, + serialized_end=12286, ) @@ -5566,8 +5573,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12259, - serialized_end=12324, + serialized_start=12288, + serialized_end=12353, ) @@ -5611,8 +5618,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12326, - serialized_end=12395, + serialized_start=12355, + serialized_end=12424, ) @@ -5656,8 +5663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12397, - serialized_end=12466, + serialized_start=12426, + serialized_end=12495, ) @@ -5694,8 +5701,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12468, - serialized_end=12539, + serialized_start=12497, + serialized_end=12568, ) @@ -5725,8 +5732,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12702, - serialized_end=12738, + serialized_start=12731, + serialized_end=12767, ) _ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( @@ -5790,8 +5797,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12542, - serialized_end=12738, + serialized_start=12571, + serialized_end=12767, ) @@ -5821,8 +5828,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12740, - serialized_end=12772, + serialized_start=12769, + serialized_end=12801, ) @@ -5866,8 +5873,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12774, - serialized_end=12870, + serialized_start=12803, + serialized_end=12899, ) @@ -5918,8 +5925,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12873, - serialized_end=13002, + serialized_start=12902, + serialized_end=13031, ) @@ -5956,8 +5963,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13004, - serialized_end=13069, + serialized_start=13033, + serialized_end=13098, ) @@ -6001,8 +6008,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13071, - serialized_end=13159, + serialized_start=13100, + serialized_end=13188, ) @@ -6060,8 +6067,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13161, - serialized_end=13287, + serialized_start=13190, + serialized_end=13316, ) @@ -6098,8 +6105,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13289, - serialized_end=13349, + serialized_start=13318, + serialized_end=13378, ) @@ -6129,8 +6136,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13351, - serialized_end=13396, + serialized_start=13380, + serialized_end=13425, ) @@ -6188,8 +6195,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13398, - serialized_end=13522, + serialized_start=13427, + serialized_end=13551, ) @@ -6219,8 +6226,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13524, - serialized_end=13570, + serialized_start=13553, + serialized_end=13599, ) @@ -6264,8 +6271,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13858, - serialized_end=13957, + serialized_start=13887, + serialized_end=13986, ) _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( @@ -6308,8 +6315,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14167, - serialized_end=14286, + serialized_start=14196, + serialized_end=14315, ) _DEVCONFIG_BLOCK = _descriptor.Descriptor( @@ -6366,8 +6373,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13960, - serialized_end=14286, + serialized_start=13989, + serialized_end=14315, ) _DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -6396,8 +6403,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14668, - serialized_end=14697, + serialized_start=14697, + serialized_end=14726, ) _DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -6426,8 +6433,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14699, - serialized_end=14735, + serialized_start=14728, + serialized_end=14764, ) _DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -6463,8 +6470,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14737, - serialized_end=14796, + serialized_start=14766, + serialized_end=14825, ) _DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( @@ -6507,8 +6514,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14798, - serialized_end=14879, + serialized_start=14827, + serialized_end=14908, ) _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( @@ -6537,8 +6544,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14881, - serialized_end=14931, + serialized_start=14910, + serialized_end=14960, ) _DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( @@ -6602,8 +6609,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14934, - serialized_end=15126, + serialized_start=14963, + serialized_end=15155, ) _DEVCONFIG_TRANSACTION = _descriptor.Descriptor( @@ -6674,8 +6681,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14289, - serialized_end=15126, + serialized_start=14318, + serialized_end=15155, ) _DEVCONFIG_POW = _descriptor.Descriptor( @@ -6711,8 +6718,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15128, - serialized_end=15168, + serialized_start=15157, + serialized_end=15197, ) _DEVCONFIG = _descriptor.Descriptor( @@ -6790,8 +6797,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13573, - serialized_end=15168, + serialized_start=13602, + serialized_end=15197, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -8141,8 +8148,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=15171, - serialized_end=17846, + serialized_start=15200, + serialized_end=17875, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -8498,8 +8505,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=17848, - serialized_end=17858, + serialized_start=17877, + serialized_end=17887, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index 327c35e65..c91b35557 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -633,12 +633,13 @@ message OptimizedAddressState { uint64 lattice_pk_count = 9; uint64 multi_sig_address_count = 10; uint64 multi_sig_spend_count = 11; + uint64 inbox_message_count = 12; - repeated bytes foundation_multi_sig_spend_txn_hash = 12; - repeated bytes foundation_multi_sig_vote_txn_hash = 13; - repeated bytes unvotes = 14; + repeated bytes foundation_multi_sig_spend_txn_hash = 13; + repeated bytes foundation_multi_sig_vote_txn_hash = 14; + repeated bytes unvotes = 15; - repeated Transaction proposal_vote_stats = 15; + repeated Transaction proposal_vote_stats = 16; } message MultiSigAddressState { From 5f8c5d0cda4c9efdb9470fe0dc6eb404a96a991e Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 26 Feb 2020 14:29:39 +0530 Subject: [PATCH 56/67] Fix missing parameter while calling set_mining_nonce_from_blob --- src/qrl/core/Miner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qrl/core/Miner.py b/src/qrl/core/Miner.py index d12ada503..ecffe203a 100644 --- a/src/qrl/core/Miner.py +++ b/src/qrl/core/Miner.py @@ -221,7 +221,7 @@ def submit_mined_block(self, blob: bytes) -> bool: return False blockheader = copy.deepcopy(self._mining_block.blockheader) - blockheader.set_mining_nonce_from_blob(blob) + blockheader.set_mining_nonce_from_blob(blob, dev_config) dev_config = self._chain_manager.get_config_by_block_number(blockheader.block_number) From af8ad00661fb5574cc5596ae1e25cee79be9134c Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 26 Feb 2020 15:55:17 +0530 Subject: [PATCH 57/67] Removed duplicate condition for LatticeTransaction during state update --- src/qrl/core/ChainManager.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 684f78186..15e81810d 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -877,9 +877,6 @@ def update_state_container(self, for address in multi_sig_spend_tx.addrs_to: if address not in state_container.addresses_state: address_set.add(address) - elif isinstance(tx, LatticeTransaction): - # TODO: Load lattice_pk and lattice_pk_tx_hashes - pass addresses_state, success = self.get_state_mainchain(address_set, ignore_addresses_set=state_container.addresses_state.keys()) From 6cca5002f53db7e9e87c4177712079c2ce14cbb3 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 26 Feb 2020 18:07:33 +0530 Subject: [PATCH 58/67] Added API GetInboxMessagesByAddress to provide list of message txns sent to an address --- src/qrl/core/ChainManager.py | 5 + src/qrl/core/qrlnode.py | 36 ++ src/qrl/generated/qrl_pb2.py | 522 ++++++++++++++++----------- src/qrl/generated/qrl_pb2_grpc.py | 16 + src/qrl/protos/qrl.proto | 14 + src/qrl/services/PublicAPIService.py | 9 + 6 files changed, 399 insertions(+), 203 deletions(-) diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 15e81810d..f58971632 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -210,6 +210,11 @@ def get_multi_sig_addresses(self, address: bytes, item_index: int) -> list: with self.lock: return p.get_paginated_data(address, item_index) + def get_inbox_message_transaction_hashes(self, address: bytes, item_index: int) -> list: + p = PaginatedData(b'p_inbox_message', False, self._state._db) + with self.lock: + return p.get_paginated_data(address, item_index) + def get_vote_stats(self, multi_sig_spend_txn_hash: bytes): with self.lock: return VoteStats.get_state(state=self._state, shared_key=multi_sig_spend_txn_hash) diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 42651e540..4990e6079 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -524,6 +524,21 @@ def _load_multi_sig_addresses(self, address: bytes, item_per_page: int, page_num actual_start_item_index)) return multi_sig_addresses[:item_per_page][-1::-1] + def _load_inbox_message_transaction_hashes(self, address: bytes, item_per_page: int, page_number: int) -> list: + address_state = self._chain_manager.get_optimized_address_state(address) + start_item_index = max(0, address_state.inbox_message_count() - item_per_page * page_number) + end_item_index = min(address_state.inbox_message_count(), start_item_index + item_per_page) + + transaction_hashes = self._chain_manager.get_inbox_message_transaction_hashes(address, + start_item_index) + actual_start_item_index = (start_item_index // config.dev.data_per_page) * config.dev.data_per_page + inbox_message_transaction_hashes = transaction_hashes[start_item_index - actual_start_item_index:] + while actual_start_item_index < end_item_index: + actual_start_item_index += config.dev.data_per_page + inbox_message_transaction_hashes.extend(self._chain_manager.get_inbox_message_transaction_hashes(address, + actual_start_item_index)) + return inbox_message_transaction_hashes[:item_per_page][-1::-1] + def get_mini_transactions_by_address(self, address: bytes, item_per_page: int, page_number: int): if item_per_page == 0: return None @@ -638,6 +653,27 @@ def get_vote_stats(self, multi_sig_spend_tx_hash: bytes): vote_stats = self._chain_manager.get_vote_stats(multi_sig_spend_tx_hash) return qrl_pb2.GetVoteStatsResp(vote_stats=vote_stats) + def get_inbox_messages_by_address(self, address: bytes, item_per_page: int, page_number: int): + if item_per_page == 0: + return None + transaction_hashes = self._load_inbox_message_transaction_hashes(address, + item_per_page, + page_number) + + response = qrl_pb2.GetTransactionsByAddressResp() + for tx_hash in transaction_hashes: + tx, block_number = self._chain_manager.get_tx_metadata(tx_hash) + b = self.get_block_from_index(block_number) + transaction_detail = qrl_pb2.GetTransactionResp(tx=tx.pbdata, + confirmations=self.block_height - block_number + 1, + block_number=block_number, + block_header_hash=b.headerhash, + timestamp=b.timestamp, + addr_from=tx.addr_from) + response.transactions_detail.extend([transaction_detail]) + + return response + def get_tokens_by_address(self, address: bytes, item_per_page: int, page_number: int): if item_per_page == 0: return None diff --git a/src/qrl/generated/qrl_pb2.py b/src/qrl/generated/qrl_pb2.py index 571e133a7..a0de28dce 100644 --- a/src/qrl/generated/qrl_pb2.py +++ b/src/qrl/generated/qrl_pb2.py @@ -19,7 +19,7 @@ name='qrl.proto', package='qrl', syntax='proto3', - serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"i\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"J\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xe0\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12\x1b\n\x13inbox_message_count\x18\x0c \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\r \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0e \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0f \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x10 \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xaa\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x39\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\x9b\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\xed\x06\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x13 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x14 \x01(\x04\x12 \n\x18proposal_default_options\x18\x15 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x16 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x17 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x18 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x19 \x01(\x04\x12\x15\n\rN_measurement\x18\x1a \x01(\x04\x12\n\n\x02kp\x18\x1b \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xbb\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xc5\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1aQ\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xf3\x14\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') + serialized_pb=_b('\n\tqrl.proto\x12\x03qrl\"\x07\n\x05\x45mpty\"\x11\n\x0fGetNodeStateReq\"/\n\x10GetNodeStateResp\x12\x1b\n\x04info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\"\x12\n\x10GetKnownPeersReq\"U\n\x11GetKnownPeersResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\x1e\n\x0bknown_peers\x18\x02 \x03(\x0b\x32\t.qrl.Peer\"\x11\n\x0fGetPeersStatReq\"5\n\x10GetPeersStatResp\x12!\n\npeers_stat\x18\x01 \x03(\x0b\x32\r.qrl.PeerStat\"\x12\n\x10GetChainStatsReq\"U\n\x11GetChainStatsResp\x12\x12\n\nstate_size\x18\x01 \x01(\x04\x12\x15\n\rstate_size_mb\x18\x02 \x01(\t\x12\x15\n\rstate_size_gb\x18\x03 \x01(\t\")\n\x0bGetStatsReq\x12\x1a\n\x12include_timeseries\x18\x01 \x01(\x08\"\x84\x02\n\x0cGetStatsResp\x12 \n\tnode_info\x18\x01 \x01(\x0b\x32\r.qrl.NodeInfo\x12\r\n\x05\x65poch\x18\x02 \x01(\x04\x12\x16\n\x0euptime_network\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_last_reward\x18\x04 \x01(\x04\x12\x17\n\x0f\x62lock_time_mean\x18\x05 \x01(\x04\x12\x15\n\rblock_time_sd\x18\x06 \x01(\x04\x12\x1a\n\x12\x63oins_total_supply\x18\x07 \x01(\x04\x12\x15\n\rcoins_emitted\x18\x08 \x01(\x04\x12-\n\x10\x62lock_timeseries\x18\t \x03(\x0b\x32\x13.qrl.BlockDataPoint\"!\n\x13GetAddressFromPKReq\x12\n\n\x02pk\x18\x01 \x01(\x0c\"\'\n\x14GetAddressFromPKResp\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"\xb2\x01\n\x0e\x42lockDataPoint\x12\x0e\n\x06number\x18\x01 \x01(\x04\x12\x12\n\ndifficulty\x18\x02 \x01(\t\x12\x11\n\ttimestamp\x18\x03 \x01(\x04\x12\x11\n\ttime_last\x18\x04 \x01(\x04\x12\x13\n\x0btime_movavg\x18\x05 \x01(\x04\x12\x12\n\nhash_power\x18\x06 \x01(\x02\x12\x13\n\x0bheader_hash\x18\x07 \x01(\x0c\x12\x18\n\x10header_hash_prev\x18\x08 \x01(\x0c\"g\n\x12GetAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x1c\n\x14\x65xclude_ots_bitfield\x18\x02 \x01(\x08\x12\"\n\x1a\x65xclude_transaction_hashes\x18\x03 \x01(\x08\"7\n\x13GetAddressStateResp\x12 \n\x05state\x18\x01 \x01(\x0b\x32\x11.qrl.AddressState\"I\n\x1cGetOptimizedAddressStateResp\x12)\n\x05state\x18\x01 \x01(\x0b\x32\x1a.qrl.OptimizedAddressState\"-\n\x1aGetMultiSigAddressStateReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"G\n\x1bGetMultiSigAddressStateResp\x12(\n\x05state\x18\x01 \x01(\x0b\x32\x19.qrl.MultiSigAddressState\"6\n\nIsSlaveReq\x12\x16\n\x0emaster_address\x18\x01 \x01(\x0c\x12\x10\n\x08slave_pk\x18\x02 \x01(\x0c\"\x1d\n\x0bIsSlaveResp\x12\x0e\n\x06result\x18\x01 \x01(\x08\"\"\n\x0fParseAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"J\n\x10ParseAddressResp\x12\x10\n\x08is_valid\x18\x01 \x01(\x08\x12$\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x16.qrl.AddressDescriptor\"\x1d\n\x0cGetObjectReq\x12\r\n\x05query\x18\x01 \x01(\x0c\"\xbc\x01\n\rGetObjectResp\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x33\n\raddress_state\x18\x02 \x01(\x0b\x32\x1a.qrl.OptimizedAddressStateH\x00\x12/\n\x0btransaction\x18\x03 \x01(\x0b\x32\x18.qrl.TransactionExtendedH\x00\x12,\n\x0e\x62lock_extended\x18\x04 \x01(\x0b\x32\x12.qrl.BlockExtendedH\x00\x42\x08\n\x06result\"\xb7\x01\n\x10GetLatestDataReq\x12,\n\x06\x66ilter\x18\x01 \x01(\x0e\x32\x1c.qrl.GetLatestDataReq.Filter\x12\x0e\n\x06offset\x18\x02 \x01(\r\x12\x10\n\x08quantity\x18\x03 \x01(\r\"S\n\x06\x46ilter\x12\x07\n\x03\x41LL\x10\x00\x12\x10\n\x0c\x42LOCKHEADERS\x10\x01\x12\x10\n\x0cTRANSACTIONS\x10\x02\x12\x1c\n\x18TRANSACTIONS_UNCONFIRMED\x10\x03\"\xaf\x01\n\x11GetLatestDataResp\x12.\n\x0c\x62lockheaders\x18\x01 \x03(\x0b\x32\x18.qrl.BlockHeaderExtended\x12.\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12:\n\x18transactions_unconfirmed\x18\x03 \x03(\x0b\x32\x18.qrl.TransactionExtended\"\x82\x01\n\x10TransferCoinsReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"T\n\x11TransferCoinsResp\x12?\n\x1d\x65xtended_transaction_unsigned\x18\x01 \x01(\x0b\x32\x18.qrl.TransactionExtended\"B\n\x12PushTransactionReq\x12,\n\x12transaction_signed\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\"\xca\x01\n\x13PushTransactionResp\x12\x39\n\nerror_code\x18\x01 \x01(\x0e\x32%.qrl.PushTransactionResp.ResponseCode\x12\x19\n\x11\x65rror_description\x18\x02 \x01(\t\x12\x0f\n\x07tx_hash\x18\x03 \x01(\x0c\"L\n\x0cResponseCode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x15\n\x11VALIDATION_FAILED\x10\x02\x12\r\n\tSUBMITTED\x10\x03\"\x82\x01\n\x14MultiSigCreateTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x02 \x03(\x0c\x12\x0f\n\x07weights\x18\x03 \x03(\r\x12\x11\n\tthreshold\x18\x04 \x01(\r\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"\xa3\x01\n\x13MultiSigSpendTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x19\n\x11multi_sig_address\x18\x02 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x03 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x06 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x07 \x01(\x0c\"k\n\x12MultiSigVoteTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x0e\n\x06unvote\x18\x03 \x01(\x08\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"d\n\rMessageTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0f\n\x07message\x18\x02 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x03 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"\xad\x01\n\x0bTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0e\n\x06symbol\x18\x02 \x01(\x0c\x12\x0c\n\x04name\x18\x03 \x01(\x0c\x12\r\n\x05owner\x18\x04 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x05 \x01(\x04\x12,\n\x10initial_balances\x18\x06 \x03(\x0b\x32\x12.qrl.AddressAmount\x12\x0b\n\x03\x66\x65\x65\x18\x07 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x08 \x01(\x0c\"\x85\x01\n\x13TransferTokenTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x14\n\x0c\x61\x64\x64resses_to\x18\x02 \x03(\x0c\x12\x14\n\x0ctoken_txhash\x18\x03 \x01(\x0c\x12\x0f\n\x07\x61mounts\x18\x04 \x03(\x04\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"i\n\x0bSlaveTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x11\n\tslave_pks\x18\x02 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x03 \x03(\r\x12\x0b\n\x03\x66\x65\x65\x18\x04 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x05 \x01(\x0c\"i\n\rLatticeTxnReq\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03pk1\x18\x02 \x01(\x0c\x12\x0b\n\x03pk2\x18\x03 \x01(\x0c\x12\x0b\n\x03pk3\x18\x04 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x05 \x01(\x04\x12\x0f\n\x07xmss_pk\x18\x06 \x01(\x0c\"H\n\x0fMiniTransaction\x12\x18\n\x10transaction_hash\x18\x01 \x01(\t\x12\x0b\n\x03out\x18\x02 \x01(\x08\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x04\"$\n\x11GetTransactionReq\x12\x0f\n\x07tx_hash\x18\x01 \x01(\x0c\"\xa0\x01\n\x12GetTransactionResp\x12\x1c\n\x02tx\x18\x01 \x01(\x0b\x32\x10.qrl.Transaction\x12\x15\n\rconfirmations\x18\x02 \x01(\x04\x12\x14\n\x0c\x62lock_number\x18\x03 \x01(\x04\x12\x19\n\x11\x62lock_header_hash\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\x12\x11\n\taddr_from\x18\x06 \x01(\x0c\"^\n\x1fGetMiniTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"d\n GetMiniTransactionsByAddressResp\x12/\n\x11mini_transactions\x18\x01 \x03(\x0b\x32\x14.qrl.MiniTransaction\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"Z\n\x1bGetTransactionsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\"T\n\x1cGetTransactionsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"\xb8\x02\n\x1fGetMultiSigSpendTxsByAddressReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x15\n\ritem_per_page\x18\x02 \x01(\x04\x12\x13\n\x0bpage_number\x18\x03 \x01(\x04\x12\x44\n\x0b\x66ilter_type\x18\x04 \x01(\x0e\x32/.qrl.GetMultiSigSpendTxsByAddressReq.FilterType\"\x91\x01\n\nFilterType\x12\x08\n\x04NONE\x10\x00\x12\x11\n\rEXECUTED_ONLY\x10\x01\x12\x10\n\x0cNON_EXECUTED\x10\x02\x12\x0b\n\x07\x45XPIRED\x10\x03\x12\x0f\n\x0bNON_EXPIRED\x10\x04\x12\x18\n\x14NON_EXECUTED_EXPIRED\x10\x05\x12\x1c\n\x18NON_EXECUTED_NON_EXPIRED\x10\x06\"X\n GetMultiSigSpendTxsByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"2\n\x0fGetVoteStatsReq\x12\x1f\n\x17multi_sig_spend_tx_hash\x18\x01 \x01(\x0c\"6\n\x10GetVoteStatsResp\x12\"\n\nvote_stats\x18\x01 \x01(\x0b\x32\x0e.qrl.VoteStats\"U\n\x1dGetInboxMessagesByAddressResp\x12\x34\n\x13transactions_detail\x18\x01 \x03(\x0b\x32\x17.qrl.GetTransactionResp\"l\n\x0cInboxMessage\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\x12\x0f\n\x07message\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x05 \x01(\x04\"R\n\x0bTokenDetail\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\x0e\n\x06symbol\x18\x03 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\"A\n\x16GetTokensByAddressResp\x12\'\n\rtokens_detail\x18\x01 \x03(\x0b\x32\x10.qrl.TokenDetail\"9\n\x0bSlaveDetail\x12\x15\n\rslave_address\x18\x01 \x01(\x0c\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\x04\"A\n\x16GetSlavesByAddressResp\x12\'\n\rslaves_detail\x18\x01 \x03(\x0b\x32\x10.qrl.SlaveDetail\"J\n\x10LatticePKsDetail\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x12\x0f\n\x07tx_hash\x18\x04 \x01(\x0c\"O\n\x1aGetLatticePKsByAddressResp\x12\x31\n\x12lattice_pks_detail\x18\x01 \x03(\x0b\x32\x15.qrl.LatticePKsDetail\"2\n\x0eMultiSigDetail\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"R\n!GetMultiSigAddressesByAddressResp\x12-\n\x10multi_sig_detail\x18\x01 \x03(\x0b\x32\x13.qrl.MultiSigDetail\" \n\rGetBalanceReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\"!\n\x0eGetBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"\'\n\x12GetTotalBalanceReq\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"&\n\x13GetTotalBalanceResp\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\"b\n\tGetOTSReq\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x11\n\tpage_from\x18\x02 \x01(\x04\x12\x12\n\npage_count\x18\x03 \x01(\x04\x12\x1d\n\x15unused_ots_index_from\x18\x04 \x01(\x04\">\n\x11OTSBitfieldByPage\x12\x14\n\x0cots_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0bpage_number\x18\x02 \x01(\x04\"\x81\x01\n\nGetOTSResp\x12\x34\n\x14ots_bitfield_by_page\x18\x01 \x03(\x0b\x32\x16.qrl.OTSBitfieldByPage\x12\x1d\n\x15next_unused_ots_index\x18\x02 \x01(\x04\x12\x1e\n\x16unused_ots_index_found\x18\x03 \x01(\x08\"\x0e\n\x0cGetHeightReq\"\x1f\n\rGetHeightResp\x12\x0e\n\x06height\x18\x01 \x01(\x04\"\"\n\x0bGetBlockReq\x12\x13\n\x0bheader_hash\x18\x01 \x01(\x0c\")\n\x0cGetBlockResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"+\n\x13GetBlockByNumberReq\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\"1\n\x14GetBlockByNumberResp\x12\x19\n\x05\x62lock\x18\x01 \x01(\x0b\x32\n.qrl.Block\"\x16\n\x14GetLocalAddressesReq\"*\n\x15GetLocalAddressesResp\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"\x8d\x02\n\x08NodeInfo\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\"\n\x05state\x18\x02 \x01(\x0e\x32\x13.qrl.NodeInfo.State\x12\x17\n\x0fnum_connections\x18\x03 \x01(\r\x12\x17\n\x0fnum_known_peers\x18\x04 \x01(\r\x12\x0e\n\x06uptime\x18\x05 \x01(\x04\x12\x14\n\x0c\x62lock_height\x18\x06 \x01(\x04\x12\x17\n\x0f\x62lock_last_hash\x18\x07 \x01(\x0c\x12\x12\n\nnetwork_id\x18\x08 \x01(\t\"G\n\x05State\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08UNSYNCED\x10\x01\x12\x0b\n\x07SYNCING\x10\x02\x12\n\n\x06SYNCED\x10\x03\x12\n\n\x06\x46ORKED\x10\x04\"\x85\x01\n\x11\x41\x64\x64ressDescriptor\x12\x15\n\rhash_function\x18\x01 \x01(\t\x12\x18\n\x10signature_scheme\x18\x02 \x01(\t\x12\x13\n\x0btree_height\x18\x03 \x01(\r\x12\x12\n\nsignatures\x18\x04 \x01(\r\x12\x16\n\x0e\x61\x64\x64ress_format\x18\x05 \x01(\t\"\'\n\x0bStoredPeers\x12\x18\n\x05peers\x18\x01 \x03(\x0b\x32\t.qrl.Peer\"\x12\n\x04Peer\x12\n\n\x02ip\x18\x01 \x01(\t\"\x91\x03\n\x0c\x41\x64\x64ressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x14\n\x0cots_bitfield\x18\x04 \x03(\x0c\x12\x1a\n\x12transaction_hashes\x18\x05 \x03(\x0c\x12-\n\x06tokens\x18\x06 \x03(\x0b\x32\x1d.qrl.AddressState.TokensEntry\x12&\n\x0elatticePK_list\x18\x07 \x03(\x0b\x32\x0e.qrl.LatticePK\x12H\n\x15slave_pks_access_type\x18\x08 \x03(\x0b\x32).qrl.AddressState.SlavePksAccessTypeEntry\x12\x13\n\x0bots_counter\x18\t \x01(\x04\x1a-\n\x0bTokensEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x39\n\x17SlavePksAccessTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\xe0\x03\n\x15OptimizedAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x1e\n\x16ots_bitfield_used_page\x18\x04 \x01(\x04\x12\x1a\n\x12used_ots_key_count\x18\x05 \x01(\x04\x12\x1e\n\x16transaction_hash_count\x18\x06 \x01(\x04\x12\x14\n\x0ctokens_count\x18\x07 \x01(\x04\x12\x14\n\x0cslaves_count\x18\x08 \x01(\x04\x12\x18\n\x10lattice_pk_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\x0b \x01(\x04\x12\x1b\n\x13inbox_message_count\x18\x0c \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\r \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0e \x03(\x0c\x12\x0f\n\x07unvotes\x18\x0f \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x10 \x03(\x0b\x32\x10.qrl.Transaction\"\x93\x03\n\x14MultiSigAddressState\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x18\n\x10\x63reation_tx_hash\x18\x02 \x01(\x0c\x12\r\n\x05nonce\x18\x03 \x01(\x04\x12\x0f\n\x07\x62\x61lance\x18\x04 \x01(\x04\x12\x13\n\x0bsignatories\x18\x05 \x03(\x0c\x12\x0f\n\x07weights\x18\x06 \x03(\r\x12\x11\n\tthreshold\x18\x07 \x01(\r\x12\x1e\n\x16transaction_hash_count\x18\x08 \x01(\x04\x12\x1d\n\x15multi_sig_spend_count\x18\t \x01(\x04\x12\x1f\n\x17multi_sig_address_count\x18\n \x01(\x04\x12+\n#foundation_multi_sig_spend_txn_hash\x18\x0b \x03(\x0c\x12*\n\"foundation_multi_sig_vote_txn_hash\x18\x0c \x03(\x0c\x12\x0f\n\x07unvotes\x18\r \x03(\x0c\x12-\n\x13proposal_vote_stats\x18\x0e \x03(\x0b\x32\x10.qrl.Transaction\"\'\n\x15MultiSigAddressesList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"\x1a\n\x08\x44\x61taList\x12\x0e\n\x06values\x18\x01 \x03(\x0c\"\x1d\n\x08\x42itfield\x12\x11\n\tbitfields\x18\x01 \x03(\x0c\"%\n\x13TransactionHashList\x12\x0e\n\x06hashes\x18\x01 \x03(\x0c\"3\n\tLatticePK\x12\x10\n\x08kyber_pk\x18\x01 \x01(\x0c\x12\x14\n\x0c\x64ilithium_pk\x18\x02 \x01(\x0c\"0\n\rAddressAmount\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\"\xd7\x01\n\x0b\x42lockHeader\x12\x13\n\x0bhash_header\x18\x01 \x01(\x0c\x12\x14\n\x0c\x62lock_number\x18\x02 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x03 \x01(\x04\x12\x18\n\x10hash_header_prev\x18\x04 \x01(\x0c\x12\x14\n\x0creward_block\x18\x05 \x01(\x04\x12\x12\n\nreward_fee\x18\x06 \x01(\x04\x12\x13\n\x0bmerkle_root\x18\x07 \x01(\x0c\x12\x14\n\x0cmining_nonce\x18\x08 \x01(\r\x12\x13\n\x0b\x65xtra_nonce\x18\t \x01(\x04\"i\n\x13\x42lockHeaderExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x30\n\x11transaction_count\x18\x02 \x01(\x0b\x32\x15.qrl.TransactionCount\"q\n\x10TransactionCount\x12/\n\x05\x63ount\x18\x01 \x03(\x0b\x32 .qrl.TransactionCount.CountEntry\x1a,\n\nCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x91\x01\n\x13TransactionExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x1c\n\x02tx\x18\x02 \x01(\x0b\x32\x10.qrl.Transaction\x12\x11\n\taddr_from\x18\x03 \x01(\x0c\x12\x0c\n\x04size\x18\x04 \x01(\x04\x12\x19\n\x11timestamp_seconds\x18\x05 \x01(\x04\"\xa6\x01\n\rBlockExtended\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12\x37\n\x15\x65xtended_transactions\x18\x02 \x03(\x0b\x32\x18.qrl.TransactionExtended\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\x12\x0c\n\x04size\x18\x04 \x01(\x04\"\x7f\n\x05\x42lock\x12 \n\x06header\x18\x01 \x01(\x0b\x32\x10.qrl.BlockHeader\x12&\n\x0ctransactions\x18\x02 \x03(\x0b\x32\x10.qrl.Transaction\x12,\n\x0fgenesis_balance\x18\x03 \x03(\x0b\x32\x13.qrl.GenesisBalance\"2\n\x0eGenesisBalance\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x0f\n\x07\x62\x61lance\x18\x02 \x01(\x04\"D\n\x11\x42lockMetaDataList\x12/\n\x13\x62lock_number_hashes\x18\x01 \x03(\x0b\x32\x12.qrl.BlockMetaData\"\xaa\x15\n\x0bTransaction\x12\x13\n\x0bmaster_addr\x18\x01 \x01(\x0c\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x12\n\npublic_key\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\r\n\x05nonce\x18\x05 \x01(\x04\x12\x18\n\x10transaction_hash\x18\x06 \x01(\x0c\x12-\n\x08transfer\x18\x07 \x01(\x0b\x32\x19.qrl.Transaction.TransferH\x00\x12-\n\x08\x63oinbase\x18\x08 \x01(\x0b\x32\x19.qrl.Transaction.CoinBaseH\x00\x12\x36\n\tlatticePK\x18\t \x01(\x0b\x32!.qrl.Transaction.LatticePublicKeyH\x00\x12+\n\x07message\x18\n \x01(\x0b\x32\x18.qrl.Transaction.MessageH\x00\x12\'\n\x05token\x18\x0b \x01(\x0b\x32\x16.qrl.Transaction.TokenH\x00\x12\x38\n\x0etransfer_token\x18\x0c \x01(\x0b\x32\x1e.qrl.Transaction.TransferTokenH\x00\x12\'\n\x05slave\x18\r \x01(\x0b\x32\x16.qrl.Transaction.SlaveH\x00\x12;\n\x10multi_sig_create\x18\x0e \x01(\x0b\x32\x1f.qrl.Transaction.MultiSigCreateH\x00\x12\x39\n\x0fmulti_sig_spend\x18\x0f \x01(\x0b\x32\x1e.qrl.Transaction.MultiSigSpendH\x00\x12\x37\n\x0emulti_sig_vote\x18\x10 \x01(\x0b\x32\x1d.qrl.Transaction.MultiSigVoteH\x00\x12:\n\x0fproposal_create\x18\x11 \x01(\x0b\x32\x1f.qrl.Transaction.ProposalCreateH\x00\x12\x36\n\rproposal_vote\x18\x12 \x01(\x0b\x32\x1d.qrl.Transaction.ProposalVoteH\x00\x1a\x43\n\x08Transfer\x12\x10\n\x08\x61\x64\x64rs_to\x18\x01 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x02 \x03(\x04\x12\x14\n\x0cmessage_data\x18\x03 \x01(\x0c\x1a+\n\x08\x43oinBase\x12\x0f\n\x07\x61\x64\x64r_to\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\x39\n\x10LatticePublicKey\x12\x0b\n\x03pk1\x18\x01 \x01(\x0c\x12\x0b\n\x03pk2\x18\x02 \x01(\x0c\x12\x0b\n\x03pk3\x18\x03 \x01(\x0c\x1a\x30\n\x07Message\x12\x14\n\x0cmessage_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07\x61\x64\x64r_to\x18\x02 \x01(\x0c\x1at\n\x05Token\x12\x0e\n\x06symbol\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\x0c\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x04\x12,\n\x10initial_balances\x18\x05 \x03(\x0b\x32\x12.qrl.AddressAmount\x1aH\n\rTransferToken\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x1a\x30\n\x05Slave\x12\x11\n\tslave_pks\x18\x01 \x03(\x0c\x12\x14\n\x0c\x61\x63\x63\x65ss_types\x18\x02 \x03(\r\x1aI\n\x0eMultiSigCreate\x12\x13\n\x0bsignatories\x18\x01 \x03(\x0c\x12\x0f\n\x07weights\x18\x02 \x03(\r\x12\x11\n\tthreshold\x18\x03 \x01(\r\x1aj\n\rMultiSigSpend\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x10\n\x08\x61\x64\x64rs_to\x18\x02 \x03(\x0c\x12\x0f\n\x07\x61mounts\x18\x03 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x04 \x01(\x04\x1aH\n\x0cMultiSigVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06unvote\x18\x02 \x01(\x08\x12\x14\n\x0cprev_tx_hash\x18\x03 \x01(\x0c\x1a\x9b\t\n\x0eProposalCreate\x12\x1b\n\x13\x65xpiry_block_number\x18\x01 \x01(\x04\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x32\n\x03qip\x18\x03 \x01(\x0b\x32#.qrl.Transaction.ProposalCreate.QIPH\x00\x12\x38\n\x06\x63onfig\x18\x04 \x01(\x0b\x32&.qrl.Transaction.ProposalCreate.ConfigH\x00\x12\x36\n\x05other\x18\x05 \x01(\x0b\x32%.qrl.Transaction.ProposalCreate.OtherH\x00\x1a\x17\n\x03QIP\x12\x10\n\x08qip_link\x18\x01 \x01(\t\x1a\xed\x06\n\x06\x43onfig\x12\x18\n\x10\x63hanges_bitfield\x18\x01 \x03(\x0c\x12\x13\n\x0breorg_limit\x18\x02 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x03 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x04 \x01(\x04\x12\x1b\n\x13mining_nonce_offset\x18\x05 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x06 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x07 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x08 \x01(\x04\x12 \n\x18number_of_blocks_analyze\x18\t \x01(\x04\x12\x1d\n\x15\x62lock_size_multiplier\x18\n \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x0b \x01(\x04\x12&\n\x1etransaction_multi_output_limit\x18\x0c \x01(\x04\x12\x1a\n\x12message_max_length\x18\r \x01(\x04\x12\x1f\n\x17token_symbol_max_length\x18\x0e \x01(\x04\x12\x1d\n\x15token_name_max_length\x18\x0f \x01(\x04\x12\x1e\n\x16lattice_pk1_max_length\x18\x10 \x01(\x04\x12\x1e\n\x16lattice_pk2_max_length\x18\x11 \x01(\x04\x12\x1e\n\x16lattice_pk3_max_length\x18\x12 \x01(\x04\x12\x39\n1foundation_multi_sig_address_threshold_percentage\x18\x13 \x01(\x04\x12\x1e\n\x16proposal_threshold_per\x18\x14 \x01(\x04\x12 \n\x18proposal_default_options\x18\x15 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x16 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x17 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x18 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x19 \x01(\x04\x12\x15\n\rN_measurement\x18\x1a \x01(\x04\x12\n\n\x02kp\x18\x1b \x01(\x04\x1a\x18\n\x05Other\x12\x0f\n\x07options\x18\x01 \x03(\tB\x0e\n\x0cproposalType\x1a\x32\n\x0cProposalVote\x12\x12\n\nshared_key\x18\x01 \x01(\x0c\x12\x0e\n\x06option\x18\x02 \x01(\rB\x11\n\x0ftransactionType\"\xb8\x01\n\tVoteStats\x12\x19\n\x11multi_sig_address\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x13\n\x0bsignatories\x18\x03 \x03(\x0c\x12\x11\n\ttx_hashes\x18\x04 \x03(\x0c\x12\x0f\n\x07unvotes\x18\x05 \x03(\x08\x12\x1b\n\x13\x65xpiry_block_number\x18\x06 \x01(\x04\x12\x14\n\x0ctotal_weight\x18\x07 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x08 \x01(\x08\"\xb7\x01\n\x11ProposalVoteStats\x12\x11\n\taddr_from\x18\x01 \x01(\x0c\x12\x12\n\nshared_key\x18\x02 \x01(\x0c\x12\x15\n\rproposal_type\x18\x03 \x01(\t\x12\x18\n\x10weight_by_option\x18\x04 \x03(\x04\x12\x1b\n\x13\x65xpiry_block_number\x18\x05 \x01(\x04\x12\x10\n\x08\x65xecuted\x18\x06 \x01(\x08\x12\x1b\n\x13number_of_tx_hashes\x18\x07 \x01(\x04\"-\n\x0eProposalRecord\x12\x1b\n\x13number_of_tx_hashes\x18\x01 \x01(\x04\"!\n\tTokenList\x12\x14\n\x0ctoken_txhash\x18\x01 \x03(\x0c\"A\n\x0cTokenBalance\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\x04\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\rSlaveMetadata\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x01 \x01(\x04\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"E\n\x11LatticePKMetadata\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x0f\n\x07tx_hash\x18\x02 \x01(\x0c\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\x08\"G\n\rTokenMetadata\x12\x14\n\x0ctoken_txhash\x18\x01 \x01(\x0c\x12 \n\x18transfer_token_tx_hashes\x18\x02 \x03(\x0c\"\xc4\x01\n\x19\x45ncryptedEphemeralMessage\x12\x0e\n\x06msg_id\x18\x01 \x01(\x0c\x12\x0b\n\x03ttl\x18\x02 \x01(\x04\x12\x0b\n\x03ttr\x18\x03 \x01(\x04\x12\x37\n\x07\x63hannel\x18\x05 \x01(\x0b\x32&.qrl.EncryptedEphemeralMessage.Channel\x12\r\n\x05nonce\x18\x06 \x01(\x04\x12\x0f\n\x07payload\x18\x07 \x01(\x0c\x1a$\n\x07\x43hannel\x12\x19\n\x11\x65nc_aes256_symkey\x18\x04 \x01(\x0c\" \n\x0b\x41\x64\x64ressList\x12\x11\n\taddresses\x18\x01 \x03(\x0c\"`\n\x0f\x42lockHeightData\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x18\n\x10\x62lock_headerhash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\"\x81\x01\n\rBlockMetaData\x12\x18\n\x10\x62lock_difficulty\x18\x01 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x02 \x01(\x0c\x12\x1a\n\x12\x63hild_headerhashes\x18\x03 \x03(\x0c\x12\x1b\n\x13last_N_headerhashes\x18\x04 \x03(\x0c\"A\n\x12\x42lockNumberMapping\x12\x12\n\nheaderhash\x18\x01 \x01(\x0c\x12\x17\n\x0fprev_headerhash\x18\x02 \x01(\x0c\"X\n\x08PeerStat\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12-\n\x10node_chain_state\x18\x03 \x01(\x0b\x32\x13.qrl.NodeChainState\"~\n\x0eNodeChainState\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x13\n\x0bheader_hash\x18\x02 \x01(\x0c\x12\x1d\n\x15\x63umulative_difficulty\x18\x03 \x01(\x0c\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x04\"<\n\x0eNodeHeaderHash\x12\x14\n\x0c\x62lock_number\x18\x01 \x01(\x04\x12\x14\n\x0cheaderhashes\x18\x02 \x03(\x0c\"-\n\x12P2PAcknowledgement\x12\x17\n\x0f\x62ytes_processed\x18\x01 \x01(\r\"|\n\x08PeerInfo\x12\x0f\n\x07peer_ip\x18\x01 \x01(\x0c\x12\x0c\n\x04port\x18\x02 \x01(\r\x12\x18\n\x10\x62\x61nned_timestamp\x18\x03 \x01(\r\x12\x13\n\x0b\x63redibility\x18\x04 \x01(\r\x12\"\n\x1alast_connections_timestamp\x18\x05 \x03(\r\".\n\x05Peers\x12%\n\x0epeer_info_list\x18\x01 \x03(\x0b\x32\r.qrl.PeerInfo\"\xbb\x0c\n\tDevConfig\x12\x16\n\x0eprev_state_key\x18\x01 \x01(\x0c\x12\x19\n\x11\x63urrent_state_key\x18\x02 \x01(\x0c\x12\x1e\n\x16\x61\x63tivation_header_hash\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63tivation_block_number\x18\x04 \x01(\x04\x12#\n\x05\x63hain\x18\x05 \x01(\x0b\x32\x14.qrl.DevConfig.Chain\x12#\n\x05\x62lock\x18\x06 \x01(\x0b\x32\x14.qrl.DevConfig.Block\x12/\n\x0btransaction\x18\x07 \x01(\x0b\x32\x1a.qrl.DevConfig.Transaction\x12\x1f\n\x03pow\x18\x08 \x01(\x0b\x32\x12.qrl.DevConfig.POW\x1a\x63\n\x05\x43hain\x12\x13\n\x0breorg_limit\x18\x01 \x01(\x04\x12\x17\n\x0fmax_coin_supply\x18\x02 \x01(\x04\x12,\n$complete_emission_time_span_in_years\x18\x03 \x01(\x04\x1a\xc6\x02\n\x05\x42lock\x12\x1b\n\x13mining_nonce_offset\x18\x01 \x01(\x04\x12\x1a\n\x12\x65xtra_nonce_offset\x18\x02 \x01(\x04\x12!\n\x19mining_blob_size_in_bytes\x18\x03 \x01(\x04\x12\x1f\n\x17\x62lock_timing_in_seconds\x18\x04 \x01(\x04\x12G\n\x15\x62lock_size_controller\x18\x05 \x01(\x0b\x32(.qrl.DevConfig.Block.BlockSizeController\x1aw\n\x13\x42lockSizeController\x12 \n\x18number_of_blocks_analyze\x18\x01 \x01(\x04\x12\x17\n\x0fsize_multiplier\x18\x02 \x01(\x04\x12%\n\x1d\x62lock_min_size_limit_in_bytes\x18\x03 \x01(\x04\x1a\xc5\x06\n\x0bTransaction\x12\x1a\n\x12multi_output_limit\x18\x01 \x01(\x04\x12\x33\n\x07message\x18\x02 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Message\x12/\n\x05slave\x18\x03 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Slave\x12/\n\x05token\x18\x04 \x01(\x0b\x32 .qrl.DevConfig.Transaction.Token\x12\x33\n\x07lattice\x18\x05 \x01(\x0b\x32\".qrl.DevConfig.Transaction.Lattice\x12K\n\x14\x66oundation_multi_sig\x18\x06 \x01(\x0b\x32-.qrl.DevConfig.Transaction.FoundationMultiSig\x12\x35\n\x08proposal\x18\x07 \x01(\x0b\x32#.qrl.DevConfig.Transaction.Proposal\x1a\x1d\n\x07Message\x12\x12\n\nmax_length\x18\x01 \x01(\x04\x1a$\n\x05Slave\x12\x1b\n\x13slave_pk_max_length\x18\x02 \x01(\x04\x1a;\n\x05Token\x12\x19\n\x11symbol_max_length\x18\x01 \x01(\x04\x12\x17\n\x0fname_max_length\x18\x02 \x01(\x04\x1aQ\n\x07Lattice\x12\x16\n\x0epk1_max_length\x18\x01 \x01(\x04\x12\x16\n\x0epk2_max_length\x18\x02 \x01(\x04\x12\x16\n\x0epk3_max_length\x18\x03 \x01(\x04\x1a\x32\n\x12\x46oundationMultiSig\x12\x1c\n\x14threshold_percentage\x18\x01 \x01(\x04\x1a\xc0\x01\n\x08Proposal\x12\x15\n\rthreshold_per\x18\x01 \x01(\x04\x12\x17\n\x0f\x64\x65\x66\x61ult_options\x18\x02 \x03(\t\x12\x1e\n\x16\x64\x65scription_max_length\x18\x03 \x01(\x04\x12\x1a\n\x12options_max_number\x18\x04 \x01(\x04\x12\x1e\n\x16option_max_text_length\x18\x05 \x01(\x04\x12(\n proposal_config_activation_delay\x18\x06 \x01(\x04\x1a(\n\x03POW\x12\x15\n\rN_measurement\x18\x01 \x01(\x04\x12\n\n\x02kp\x18\x02 \x01(\x04\x32\xd6\x15\n\tPublicAPI\x12;\n\x0cGetNodeState\x12\x14.qrl.GetNodeStateReq\x1a\x15.qrl.GetNodeStateResp\x12>\n\rGetKnownPeers\x12\x15.qrl.GetKnownPeersReq\x1a\x16.qrl.GetKnownPeersResp\x12;\n\x0cGetPeersStat\x12\x14.qrl.GetPeersStatReq\x1a\x15.qrl.GetPeersStatResp\x12/\n\x08GetStats\x12\x10.qrl.GetStatsReq\x1a\x11.qrl.GetStatsResp\x12\x44\n\x0fGetAddressState\x12\x17.qrl.GetAddressStateReq\x1a\x18.qrl.GetAddressStateResp\x12V\n\x18GetOptimizedAddressState\x12\x17.qrl.GetAddressStateReq\x1a!.qrl.GetOptimizedAddressStateResp\x12\\\n\x17GetMultiSigAddressState\x12\x1f.qrl.GetMultiSigAddressStateReq\x1a .qrl.GetMultiSigAddressStateResp\x12,\n\x07IsSlave\x12\x0f.qrl.IsSlaveReq\x1a\x10.qrl.IsSlaveResp\x12\x32\n\tGetObject\x12\x11.qrl.GetObjectReq\x1a\x12.qrl.GetObjectResp\x12>\n\rGetLatestData\x12\x15.qrl.GetLatestDataReq\x1a\x16.qrl.GetLatestDataResp\x12\x44\n\x0fPushTransaction\x12\x17.qrl.PushTransactionReq\x1a\x18.qrl.PushTransactionResp\x12>\n\rTransferCoins\x12\x15.qrl.TransferCoinsReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\x0cParseAddress\x12\x14.qrl.ParseAddressReq\x1a\x15.qrl.ParseAddressResp\x12>\n\rGetChainStats\x12\x15.qrl.GetChainStatsReq\x1a\x16.qrl.GetChainStatsResp\x12G\n\x10GetAddressFromPK\x12\x18.qrl.GetAddressFromPKReq\x1a\x19.qrl.GetAddressFromPKResp\x12I\n\x14GetMultiSigCreateTxn\x12\x19.qrl.MultiSigCreateTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetMultiSigSpendTxn\x12\x18.qrl.MultiSigSpendTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x45\n\x12GetMultiSigVoteTxn\x12\x17.qrl.MultiSigVoteTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetMessageTxn\x12\x12.qrl.MessageTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetTokenTxn\x12\x10.qrl.TokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12G\n\x13GetTransferTokenTxn\x12\x18.qrl.TransferTokenTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x37\n\x0bGetSlaveTxn\x12\x10.qrl.SlaveTxnReq\x1a\x16.qrl.TransferCoinsResp\x12;\n\rGetLatticeTxn\x12\x12.qrl.LatticeTxnReq\x1a\x16.qrl.TransferCoinsResp\x12\x41\n\x0eGetTransaction\x12\x16.qrl.GetTransactionReq\x1a\x17.qrl.GetTransactionResp\x12k\n\x1cGetMiniTransactionsByAddress\x12$.qrl.GetMiniTransactionsByAddressReq\x1a%.qrl.GetMiniTransactionsByAddressResp\x12_\n\x18GetTransactionsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a!.qrl.GetTransactionsByAddressResp\x12S\n\x12GetTokensByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetTokensByAddressResp\x12S\n\x12GetSlavesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1b.qrl.GetSlavesByAddressResp\x12[\n\x16GetLatticePKsByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\x1f.qrl.GetLatticePKsByAddressResp\x12i\n\x1dGetMultiSigAddressesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a&.qrl.GetMultiSigAddressesByAddressResp\x12k\n\x1cGetMultiSigSpendTxsByAddress\x12$.qrl.GetMultiSigSpendTxsByAddressReq\x1a%.qrl.GetMultiSigSpendTxsByAddressResp\x12;\n\x0cGetVoteStats\x12\x14.qrl.GetVoteStatsReq\x1a\x15.qrl.GetVoteStatsResp\x12\x61\n\x19GetInboxMessagesByAddress\x12 .qrl.GetTransactionsByAddressReq\x1a\".qrl.GetInboxMessagesByAddressResp\x12\x35\n\nGetBalance\x12\x12.qrl.GetBalanceReq\x1a\x13.qrl.GetBalanceResp\x12\x44\n\x0fGetTotalBalance\x12\x17.qrl.GetTotalBalanceReq\x1a\x18.qrl.GetTotalBalanceResp\x12)\n\x06GetOTS\x12\x0e.qrl.GetOTSReq\x1a\x0f.qrl.GetOTSResp\x12\x32\n\tGetHeight\x12\x11.qrl.GetHeightReq\x1a\x12.qrl.GetHeightResp\x12/\n\x08GetBlock\x12\x10.qrl.GetBlockReq\x1a\x11.qrl.GetBlockResp\x12G\n\x10GetBlockByNumber\x12\x18.qrl.GetBlockByNumberReq\x1a\x19.qrl.GetBlockByNumberResp2\n\n\x08\x41\x64minAPIb\x06proto3') ) @@ -155,8 +155,8 @@ ], containing_type=None, options=None, - serialized_start=6287, - serialized_end=6358, + serialized_start=6484, + serialized_end=6555, ) _sym_db.RegisterEnumDescriptor(_NODEINFO_STATE) @@ -2319,6 +2319,96 @@ ) +_GETINBOXMESSAGESBYADDRESSRESP = _descriptor.Descriptor( + name='GetInboxMessagesByAddressResp', + full_name='qrl.GetInboxMessagesByAddressResp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='transactions_detail', full_name='qrl.GetInboxMessagesByAddressResp.transactions_detail', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4780, + serialized_end=4865, +) + + +_INBOXMESSAGE = _descriptor.Descriptor( + name='InboxMessage', + full_name='qrl.InboxMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='addr_from', full_name='qrl.InboxMessage.addr_from', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='qrl.InboxMessage.timestamp', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='qrl.InboxMessage.message', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tx_hash', full_name='qrl.InboxMessage.tx_hash', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='block_number', full_name='qrl.InboxMessage.block_number', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4867, + serialized_end=4975, +) + + _TOKENDETAIL = _descriptor.Descriptor( name='TokenDetail', full_name='qrl.TokenDetail', @@ -2366,8 +2456,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4780, - serialized_end=4862, + serialized_start=4977, + serialized_end=5059, ) @@ -2397,8 +2487,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4864, - serialized_end=4929, + serialized_start=5061, + serialized_end=5126, ) @@ -2435,8 +2525,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4931, - serialized_end=4988, + serialized_start=5128, + serialized_end=5185, ) @@ -2466,8 +2556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4990, - serialized_end=5055, + serialized_start=5187, + serialized_end=5252, ) @@ -2518,8 +2608,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5057, - serialized_end=5131, + serialized_start=5254, + serialized_end=5328, ) @@ -2549,8 +2639,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5133, - serialized_end=5212, + serialized_start=5330, + serialized_end=5409, ) @@ -2587,8 +2677,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5214, - serialized_end=5264, + serialized_start=5411, + serialized_end=5461, ) @@ -2618,8 +2708,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5266, - serialized_end=5348, + serialized_start=5463, + serialized_end=5545, ) @@ -2649,8 +2739,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5350, - serialized_end=5382, + serialized_start=5547, + serialized_end=5579, ) @@ -2680,8 +2770,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5384, - serialized_end=5417, + serialized_start=5581, + serialized_end=5614, ) @@ -2711,8 +2801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5419, - serialized_end=5458, + serialized_start=5616, + serialized_end=5655, ) @@ -2742,8 +2832,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5460, - serialized_end=5498, + serialized_start=5657, + serialized_end=5695, ) @@ -2794,8 +2884,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5500, - serialized_end=5598, + serialized_start=5697, + serialized_end=5795, ) @@ -2832,8 +2922,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5600, - serialized_end=5662, + serialized_start=5797, + serialized_end=5859, ) @@ -2877,8 +2967,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5665, - serialized_end=5794, + serialized_start=5862, + serialized_end=5991, ) @@ -2901,8 +2991,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5796, - serialized_end=5810, + serialized_start=5993, + serialized_end=6007, ) @@ -2932,8 +3022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5812, - serialized_end=5843, + serialized_start=6009, + serialized_end=6040, ) @@ -2963,8 +3053,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5845, - serialized_end=5879, + serialized_start=6042, + serialized_end=6076, ) @@ -2994,8 +3084,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5881, - serialized_end=5922, + serialized_start=6078, + serialized_end=6119, ) @@ -3025,8 +3115,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5924, - serialized_end=5967, + serialized_start=6121, + serialized_end=6164, ) @@ -3056,8 +3146,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5969, - serialized_end=6018, + serialized_start=6166, + serialized_end=6215, ) @@ -3080,8 +3170,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6020, - serialized_end=6042, + serialized_start=6217, + serialized_end=6239, ) @@ -3111,8 +3201,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6044, - serialized_end=6086, + serialized_start=6241, + serialized_end=6283, ) @@ -3192,8 +3282,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6089, - serialized_end=6358, + serialized_start=6286, + serialized_end=6555, ) @@ -3251,8 +3341,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6361, - serialized_end=6494, + serialized_start=6558, + serialized_end=6691, ) @@ -3282,8 +3372,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6496, - serialized_end=6535, + serialized_start=6693, + serialized_end=6732, ) @@ -3313,8 +3403,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6537, - serialized_end=6555, + serialized_start=6734, + serialized_end=6752, ) @@ -3351,8 +3441,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6855, - serialized_end=6900, + serialized_start=7052, + serialized_end=7097, ) _ADDRESSSTATE_SLAVEPKSACCESSTYPEENTRY = _descriptor.Descriptor( @@ -3388,8 +3478,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6902, - serialized_end=6959, + serialized_start=7099, + serialized_end=7156, ) _ADDRESSSTATE = _descriptor.Descriptor( @@ -3474,8 +3564,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6558, - serialized_end=6959, + serialized_start=6755, + serialized_end=7156, ) @@ -3610,8 +3700,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6962, - serialized_end=7442, + serialized_start=7159, + serialized_end=7639, ) @@ -3732,8 +3822,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7445, - serialized_end=7848, + serialized_start=7642, + serialized_end=8045, ) @@ -3763,8 +3853,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7850, - serialized_end=7889, + serialized_start=8047, + serialized_end=8086, ) @@ -3794,8 +3884,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7891, - serialized_end=7917, + serialized_start=8088, + serialized_end=8114, ) @@ -3825,8 +3915,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7919, - serialized_end=7948, + serialized_start=8116, + serialized_end=8145, ) @@ -3856,8 +3946,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7950, - serialized_end=7987, + serialized_start=8147, + serialized_end=8184, ) @@ -3894,8 +3984,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7989, - serialized_end=8040, + serialized_start=8186, + serialized_end=8237, ) @@ -3932,8 +4022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8042, - serialized_end=8090, + serialized_start=8239, + serialized_end=8287, ) @@ -4019,8 +4109,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8093, - serialized_end=8308, + serialized_start=8290, + serialized_end=8505, ) @@ -4057,8 +4147,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8310, - serialized_end=8415, + serialized_start=8507, + serialized_end=8612, ) @@ -4095,8 +4185,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8486, - serialized_end=8530, + serialized_start=8683, + serialized_end=8727, ) _TRANSACTIONCOUNT = _descriptor.Descriptor( @@ -4125,8 +4215,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8417, - serialized_end=8530, + serialized_start=8614, + serialized_end=8727, ) @@ -4184,8 +4274,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8533, - serialized_end=8678, + serialized_start=8730, + serialized_end=8875, ) @@ -4236,8 +4326,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8681, - serialized_end=8847, + serialized_start=8878, + serialized_end=9044, ) @@ -4281,8 +4371,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8849, - serialized_end=8976, + serialized_start=9046, + serialized_end=9173, ) @@ -4319,8 +4409,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8978, - serialized_end=9028, + serialized_start=9175, + serialized_end=9225, ) @@ -4350,8 +4440,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9030, - serialized_end=9098, + serialized_start=9227, + serialized_end=9295, ) @@ -4395,8 +4485,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9858, - serialized_end=9925, + serialized_start=10055, + serialized_end=10122, ) _TRANSACTION_COINBASE = _descriptor.Descriptor( @@ -4432,8 +4522,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9927, - serialized_end=9970, + serialized_start=10124, + serialized_end=10167, ) _TRANSACTION_LATTICEPUBLICKEY = _descriptor.Descriptor( @@ -4476,8 +4566,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9972, - serialized_end=10029, + serialized_start=10169, + serialized_end=10226, ) _TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -4513,8 +4603,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10031, - serialized_end=10079, + serialized_start=10228, + serialized_end=10276, ) _TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -4571,8 +4661,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10081, - serialized_end=10197, + serialized_start=10278, + serialized_end=10394, ) _TRANSACTION_TRANSFERTOKEN = _descriptor.Descriptor( @@ -4615,8 +4705,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10199, - serialized_end=10271, + serialized_start=10396, + serialized_end=10468, ) _TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -4652,8 +4742,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10273, - serialized_end=10321, + serialized_start=10470, + serialized_end=10518, ) _TRANSACTION_MULTISIGCREATE = _descriptor.Descriptor( @@ -4696,8 +4786,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10323, - serialized_end=10396, + serialized_start=10520, + serialized_end=10593, ) _TRANSACTION_MULTISIGSPEND = _descriptor.Descriptor( @@ -4747,8 +4837,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10398, - serialized_end=10504, + serialized_start=10595, + serialized_end=10701, ) _TRANSACTION_MULTISIGVOTE = _descriptor.Descriptor( @@ -4791,8 +4881,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10506, - serialized_end=10578, + serialized_start=10703, + serialized_end=10775, ) _TRANSACTION_PROPOSALCREATE_QIP = _descriptor.Descriptor( @@ -4821,8 +4911,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10815, - serialized_end=10838, + serialized_start=11012, + serialized_end=11035, ) _TRANSACTION_PROPOSALCREATE_CONFIG = _descriptor.Descriptor( @@ -5033,8 +5123,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10841, - serialized_end=11718, + serialized_start=11038, + serialized_end=11915, ) _TRANSACTION_PROPOSALCREATE_OTHER = _descriptor.Descriptor( @@ -5063,8 +5153,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11720, - serialized_end=11744, + serialized_start=11917, + serialized_end=11941, ) _TRANSACTION_PROPOSALCREATE = _descriptor.Descriptor( @@ -5124,8 +5214,8 @@ name='proposalType', full_name='qrl.Transaction.ProposalCreate.proposalType', index=0, containing_type=None, fields=[]), ], - serialized_start=10581, - serialized_end=11760, + serialized_start=10778, + serialized_end=11957, ) _TRANSACTION_PROPOSALVOTE = _descriptor.Descriptor( @@ -5161,8 +5251,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11762, - serialized_end=11812, + serialized_start=11959, + serialized_end=12009, ) _TRANSACTION = _descriptor.Descriptor( @@ -5313,8 +5403,8 @@ name='transactionType', full_name='qrl.Transaction.transactionType', index=0, containing_type=None, fields=[]), ], - serialized_start=9101, - serialized_end=11831, + serialized_start=9298, + serialized_end=12028, ) @@ -5393,8 +5483,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11834, - serialized_end=12018, + serialized_start=12031, + serialized_end=12215, ) @@ -5466,8 +5556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12021, - serialized_end=12204, + serialized_start=12218, + serialized_end=12401, ) @@ -5497,8 +5587,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12206, - serialized_end=12251, + serialized_start=12403, + serialized_end=12448, ) @@ -5528,8 +5618,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12253, - serialized_end=12286, + serialized_start=12450, + serialized_end=12483, ) @@ -5573,8 +5663,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12288, - serialized_end=12353, + serialized_start=12485, + serialized_end=12550, ) @@ -5618,8 +5708,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12355, - serialized_end=12424, + serialized_start=12552, + serialized_end=12621, ) @@ -5663,8 +5753,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12426, - serialized_end=12495, + serialized_start=12623, + serialized_end=12692, ) @@ -5701,8 +5791,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12497, - serialized_end=12568, + serialized_start=12694, + serialized_end=12765, ) @@ -5732,8 +5822,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12731, - serialized_end=12767, + serialized_start=12928, + serialized_end=12964, ) _ENCRYPTEDEPHEMERALMESSAGE = _descriptor.Descriptor( @@ -5797,8 +5887,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12571, - serialized_end=12767, + serialized_start=12768, + serialized_end=12964, ) @@ -5828,8 +5918,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12769, - serialized_end=12801, + serialized_start=12966, + serialized_end=12998, ) @@ -5873,8 +5963,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12803, - serialized_end=12899, + serialized_start=13000, + serialized_end=13096, ) @@ -5925,8 +6015,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12902, - serialized_end=13031, + serialized_start=13099, + serialized_end=13228, ) @@ -5963,8 +6053,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13033, - serialized_end=13098, + serialized_start=13230, + serialized_end=13295, ) @@ -6008,8 +6098,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13100, - serialized_end=13188, + serialized_start=13297, + serialized_end=13385, ) @@ -6067,8 +6157,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13190, - serialized_end=13316, + serialized_start=13387, + serialized_end=13513, ) @@ -6105,8 +6195,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13318, - serialized_end=13378, + serialized_start=13515, + serialized_end=13575, ) @@ -6136,8 +6226,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13380, - serialized_end=13425, + serialized_start=13577, + serialized_end=13622, ) @@ -6195,8 +6285,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13427, - serialized_end=13551, + serialized_start=13624, + serialized_end=13748, ) @@ -6226,8 +6316,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13553, - serialized_end=13599, + serialized_start=13750, + serialized_end=13796, ) @@ -6271,8 +6361,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13887, - serialized_end=13986, + serialized_start=14084, + serialized_end=14183, ) _DEVCONFIG_BLOCK_BLOCKSIZECONTROLLER = _descriptor.Descriptor( @@ -6315,8 +6405,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14196, - serialized_end=14315, + serialized_start=14393, + serialized_end=14512, ) _DEVCONFIG_BLOCK = _descriptor.Descriptor( @@ -6373,8 +6463,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13989, - serialized_end=14315, + serialized_start=14186, + serialized_end=14512, ) _DEVCONFIG_TRANSACTION_MESSAGE = _descriptor.Descriptor( @@ -6403,8 +6493,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14697, - serialized_end=14726, + serialized_start=14894, + serialized_end=14923, ) _DEVCONFIG_TRANSACTION_SLAVE = _descriptor.Descriptor( @@ -6433,8 +6523,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14728, - serialized_end=14764, + serialized_start=14925, + serialized_end=14961, ) _DEVCONFIG_TRANSACTION_TOKEN = _descriptor.Descriptor( @@ -6470,8 +6560,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14766, - serialized_end=14825, + serialized_start=14963, + serialized_end=15022, ) _DEVCONFIG_TRANSACTION_LATTICE = _descriptor.Descriptor( @@ -6514,8 +6604,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14827, - serialized_end=14908, + serialized_start=15024, + serialized_end=15105, ) _DEVCONFIG_TRANSACTION_FOUNDATIONMULTISIG = _descriptor.Descriptor( @@ -6544,8 +6634,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14910, - serialized_end=14960, + serialized_start=15107, + serialized_end=15157, ) _DEVCONFIG_TRANSACTION_PROPOSAL = _descriptor.Descriptor( @@ -6609,8 +6699,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14963, - serialized_end=15155, + serialized_start=15160, + serialized_end=15352, ) _DEVCONFIG_TRANSACTION = _descriptor.Descriptor( @@ -6681,8 +6771,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14318, - serialized_end=15155, + serialized_start=14515, + serialized_end=15352, ) _DEVCONFIG_POW = _descriptor.Descriptor( @@ -6718,8 +6808,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15157, - serialized_end=15197, + serialized_start=15354, + serialized_end=15394, ) _DEVCONFIG = _descriptor.Descriptor( @@ -6797,8 +6887,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13602, - serialized_end=15197, + serialized_start=13799, + serialized_end=15394, ) _GETNODESTATERESP.fields_by_name['info'].message_type = _NODEINFO @@ -6840,6 +6930,7 @@ _GETMULTISIGSPENDTXSBYADDRESSREQ_FILTERTYPE.containing_type = _GETMULTISIGSPENDTXSBYADDRESSREQ _GETMULTISIGSPENDTXSBYADDRESSRESP.fields_by_name['transactions_detail'].message_type = _GETTRANSACTIONRESP _GETVOTESTATSRESP.fields_by_name['vote_stats'].message_type = _VOTESTATS +_GETINBOXMESSAGESBYADDRESSRESP.fields_by_name['transactions_detail'].message_type = _GETTRANSACTIONRESP _GETTOKENSBYADDRESSRESP.fields_by_name['tokens_detail'].message_type = _TOKENDETAIL _GETSLAVESBYADDRESSRESP.fields_by_name['slaves_detail'].message_type = _SLAVEDETAIL _GETLATTICEPKSBYADDRESSRESP.fields_by_name['lattice_pks_detail'].message_type = _LATTICEPKSDETAIL @@ -7022,6 +7113,8 @@ DESCRIPTOR.message_types_by_name['GetMultiSigSpendTxsByAddressResp'] = _GETMULTISIGSPENDTXSBYADDRESSRESP DESCRIPTOR.message_types_by_name['GetVoteStatsReq'] = _GETVOTESTATSREQ DESCRIPTOR.message_types_by_name['GetVoteStatsResp'] = _GETVOTESTATSRESP +DESCRIPTOR.message_types_by_name['GetInboxMessagesByAddressResp'] = _GETINBOXMESSAGESBYADDRESSRESP +DESCRIPTOR.message_types_by_name['InboxMessage'] = _INBOXMESSAGE DESCRIPTOR.message_types_by_name['TokenDetail'] = _TOKENDETAIL DESCRIPTOR.message_types_by_name['GetTokensByAddressResp'] = _GETTOKENSBYADDRESSRESP DESCRIPTOR.message_types_by_name['SlaveDetail'] = _SLAVEDETAIL @@ -7439,6 +7532,20 @@ )) _sym_db.RegisterMessage(GetVoteStatsResp) +GetInboxMessagesByAddressResp = _reflection.GeneratedProtocolMessageType('GetInboxMessagesByAddressResp', (_message.Message,), dict( + DESCRIPTOR = _GETINBOXMESSAGESBYADDRESSRESP, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.GetInboxMessagesByAddressResp) + )) +_sym_db.RegisterMessage(GetInboxMessagesByAddressResp) + +InboxMessage = _reflection.GeneratedProtocolMessageType('InboxMessage', (_message.Message,), dict( + DESCRIPTOR = _INBOXMESSAGE, + __module__ = 'qrl_pb2' + # @@protoc_insertion_point(class_scope:qrl.InboxMessage) + )) +_sym_db.RegisterMessage(InboxMessage) + TokenDetail = _reflection.GeneratedProtocolMessageType('TokenDetail', (_message.Message,), dict( DESCRIPTOR = _TOKENDETAIL, __module__ = 'qrl_pb2' @@ -8148,8 +8255,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=15200, - serialized_end=17875, + serialized_start=15397, + serialized_end=18171, methods=[ _descriptor.MethodDescriptor( name='GetNodeState', @@ -8439,10 +8546,19 @@ output_type=_GETVOTESTATSRESP, options=None, ), + _descriptor.MethodDescriptor( + name='GetInboxMessagesByAddress', + full_name='qrl.PublicAPI.GetInboxMessagesByAddress', + index=32, + containing_service=None, + input_type=_GETTRANSACTIONSBYADDRESSREQ, + output_type=_GETINBOXMESSAGESBYADDRESSRESP, + options=None, + ), _descriptor.MethodDescriptor( name='GetBalance', full_name='qrl.PublicAPI.GetBalance', - index=32, + index=33, containing_service=None, input_type=_GETBALANCEREQ, output_type=_GETBALANCERESP, @@ -8451,7 +8567,7 @@ _descriptor.MethodDescriptor( name='GetTotalBalance', full_name='qrl.PublicAPI.GetTotalBalance', - index=33, + index=34, containing_service=None, input_type=_GETTOTALBALANCEREQ, output_type=_GETTOTALBALANCERESP, @@ -8460,7 +8576,7 @@ _descriptor.MethodDescriptor( name='GetOTS', full_name='qrl.PublicAPI.GetOTS', - index=34, + index=35, containing_service=None, input_type=_GETOTSREQ, output_type=_GETOTSRESP, @@ -8469,7 +8585,7 @@ _descriptor.MethodDescriptor( name='GetHeight', full_name='qrl.PublicAPI.GetHeight', - index=35, + index=36, containing_service=None, input_type=_GETHEIGHTREQ, output_type=_GETHEIGHTRESP, @@ -8478,7 +8594,7 @@ _descriptor.MethodDescriptor( name='GetBlock', full_name='qrl.PublicAPI.GetBlock', - index=36, + index=37, containing_service=None, input_type=_GETBLOCKREQ, output_type=_GETBLOCKRESP, @@ -8487,7 +8603,7 @@ _descriptor.MethodDescriptor( name='GetBlockByNumber', full_name='qrl.PublicAPI.GetBlockByNumber', - index=37, + index=38, containing_service=None, input_type=_GETBLOCKBYNUMBERREQ, output_type=_GETBLOCKBYNUMBERRESP, @@ -8505,8 +8621,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=17877, - serialized_end=17887, + serialized_start=18173, + serialized_end=18183, methods=[ ]) _sym_db.RegisterServiceDescriptor(_ADMINAPI) diff --git a/src/qrl/generated/qrl_pb2_grpc.py b/src/qrl/generated/qrl_pb2_grpc.py index 016e8925d..d257d20d6 100644 --- a/src/qrl/generated/qrl_pb2_grpc.py +++ b/src/qrl/generated/qrl_pb2_grpc.py @@ -182,6 +182,11 @@ def __init__(self, channel): request_serializer=qrl__pb2.GetVoteStatsReq.SerializeToString, response_deserializer=qrl__pb2.GetVoteStatsResp.FromString, ) + self.GetInboxMessagesByAddress = channel.unary_unary( + '/qrl.PublicAPI/GetInboxMessagesByAddress', + request_serializer=qrl__pb2.GetTransactionsByAddressReq.SerializeToString, + response_deserializer=qrl__pb2.GetInboxMessagesByAddressResp.FromString, + ) self.GetBalance = channel.unary_unary( '/qrl.PublicAPI/GetBalance', request_serializer=qrl__pb2.GetBalanceReq.SerializeToString, @@ -418,6 +423,12 @@ def GetVoteStats(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def GetInboxMessagesByAddress(self, request, context): + # missing associated documentation comment in .proto file + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def GetBalance(self, request, context): # missing associated documentation comment in .proto file context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -617,6 +628,11 @@ def add_PublicAPIServicer_to_server(servicer, server): request_deserializer=qrl__pb2.GetVoteStatsReq.FromString, response_serializer=qrl__pb2.GetVoteStatsResp.SerializeToString, ), + 'GetInboxMessagesByAddress': grpc.unary_unary_rpc_method_handler( + servicer.GetInboxMessagesByAddress, + request_deserializer=qrl__pb2.GetTransactionsByAddressReq.FromString, + response_serializer=qrl__pb2.GetInboxMessagesByAddressResp.SerializeToString, + ), 'GetBalance': grpc.unary_unary_rpc_method_handler( servicer.GetBalance, request_deserializer=qrl__pb2.GetBalanceReq.FromString, diff --git a/src/qrl/protos/qrl.proto b/src/qrl/protos/qrl.proto index c91b35557..b0c517d9b 100644 --- a/src/qrl/protos/qrl.proto +++ b/src/qrl/protos/qrl.proto @@ -80,6 +80,8 @@ service PublicAPI rpc GetVoteStats(GetVoteStatsReq) returns (GetVoteStatsResp); + rpc GetInboxMessagesByAddress(GetTransactionsByAddressReq) returns (GetInboxMessagesByAddressResp); + rpc GetBalance(GetBalanceReq) returns (GetBalanceResp); rpc GetTotalBalance(GetTotalBalanceReq) returns (GetTotalBalanceResp); @@ -455,6 +457,18 @@ message GetVoteStatsResp { VoteStats vote_stats = 1; } +message GetInboxMessagesByAddressResp { + repeated GetTransactionResp transactions_detail = 1; +} + +message InboxMessage { + bytes addr_from = 1; + uint64 timestamp = 2; + bytes message = 3; + bytes tx_hash = 4; + uint64 block_number = 5; +} + message TokenDetail { bytes token_txhash = 1; bytes name = 2; diff --git a/src/qrl/services/PublicAPIService.py b/src/qrl/services/PublicAPIService.py index f0e791ad8..afb90f034 100644 --- a/src/qrl/services/PublicAPIService.py +++ b/src/qrl/services/PublicAPIService.py @@ -485,6 +485,15 @@ def GetMultiSigSpendTxsByAddress(self, request.page_number, request.filter_type) + @GrpcExceptionWrapper(qrl_pb2.GetInboxMessagesByAddressResp) + def GetInboxMessagesByAddress(self, + request: qrl_pb2.GetTransactionsByAddressReq, + context) -> qrl_pb2.GetInboxMessagesByAddressResp: + logger.debug("[PublicAPI] GetInboxMessagesByAddress") + return self.qrlnode.get_inbox_messages_by_address(request.address, + request.item_per_page, + request.page_number) + @GrpcExceptionWrapper(qrl_pb2.GetVoteStatsResp) def GetVoteStats(self, request: qrl_pb2.GetVoteStatsReq, From a24a090f9894aec628598ab24f15f8b46b083184 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 26 Feb 2020 19:47:55 +0530 Subject: [PATCH 59/67] Fix remove txn from the txn pool if state validation fails --- src/qrl/core/Miner.py | 1 + src/qrl/core/processors/TxnProcessor.py | 6 ++++++ src/qrl/core/txs/Transaction.py | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/qrl/core/Miner.py b/src/qrl/core/Miner.py index ecffe203a..a8e5393c4 100644 --- a/src/qrl/core/Miner.py +++ b/src/qrl/core/Miner.py @@ -157,6 +157,7 @@ def create_block(self, if not tx.validate_all(state_container, check_nonce=False): if not state_container.revert_update(): return None + tx_pool.remove_tx_from_pool(tx) continue if not self._chain_manager.apply_txn(tx, state_container): logger.error("[create_block] Failed to apply txn") diff --git a/src/qrl/core/processors/TxnProcessor.py b/src/qrl/core/processors/TxnProcessor.py index 18861a3ad..2d9bff544 100644 --- a/src/qrl/core/processors/TxnProcessor.py +++ b/src/qrl/core/processors/TxnProcessor.py @@ -32,6 +32,12 @@ def __next__(self): if not self.chain_manager.validate_all(tx, check_nonce=False): return False + is_valid_pool_state = tx.validate_transaction_pool(self.transaction_pool_obj.transaction_pool) + + if not is_valid_pool_state: + logger.info('>>>TX %s failed is_valid_pool_state', bin2hstr(tx.txhash)) + return False + logger.info('A TXN has been Processed %s', bin2hstr(tx.txhash)) self.transaction_pool_obj.add_tx_to_pool(tx, self.chain_manager.last_block.block_number, timestamp) self.broadcast_tx(tx) diff --git a/src/qrl/core/txs/Transaction.py b/src/qrl/core/txs/Transaction.py index 919cb8782..c73f97e2c 100644 --- a/src/qrl/core/txs/Transaction.py +++ b/src/qrl/core/txs/Transaction.py @@ -205,7 +205,7 @@ def validate_transaction_pool(self, transaction_pool): if txn.ots_key == self.ots_key: logger.info('State validation failed for %s because: OTS Public key re-use detected', bin2hstr(self.txhash)) - logger.info('Subtype %s', type(self)) + logger.info('Subtype %s', self.type) return False return True From 710a6d5181a1e7d0b366999455ceb2e5d8eea0c8 Mon Sep 17 00:00:00 2001 From: cyyber Date: Wed, 26 Feb 2020 21:05:59 +0530 Subject: [PATCH 60/67] Replaced get balance via GetOptimizedAddressState --- src/qrl/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qrl/cli.py b/src/qrl/cli.py index df368b568..a90b45c62 100755 --- a/src/qrl/cli.py +++ b/src/qrl/cli.py @@ -142,8 +142,8 @@ def _verbose(wallet): def _public_get_address_balance(ctx, address): stub = ctx.obj.get_stub_public_api() get_address_state_req = qrl_pb2.GetAddressStateReq(address=parse_qaddress(address)) - get_address_state_resp = stub.GetAddressState(get_address_state_req, timeout=CONNECTION_TIMEOUT) - return get_address_state_resp.state.balance + get_optimized_address_state_resp = stub.GetOptimizedAddressState(get_address_state_req, timeout=CONNECTION_TIMEOUT) + return get_optimized_address_state_resp.state.balance def _select_wallet(ctx, address_or_index): From 46106621a17a0761006845ba5bdf10b05c1dc864 Mon Sep 17 00:00:00 2001 From: cyyber Date: Thu, 27 Feb 2020 12:02:12 +0530 Subject: [PATCH 61/67] Added unit test when duplicate set of public keys are added into a lattice txn --- tests/core/test_ChainManager.py | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/core/test_ChainManager.py b/tests/core/test_ChainManager.py index 5d6149e0e..dd1986b65 100644 --- a/tests/core/test_ChainManager.py +++ b/tests/core/test_ChainManager.py @@ -709,6 +709,17 @@ def test_add_block3(self, time_mock): @set_hard_fork_block_number() @patch('qrl.core.misc.ntp.getTime') def test_add_block4(self, time_mock): + """ + Features Tested + - Behavior of Block validation with lattice transctions + + Expectation + - Block 1 and 2 must be added as both of them have valid lattice transaction + - Block 3 must not be added, as it includes a lattice txn adding duplicate public keys + + :param time_mock: + :return: + """ with patch.object(DifficultyTracker, 'get', return_value=ask_difficulty_tracker('2', config.dev)): self.chain_manager.load(self.genesis_block) @@ -779,6 +790,32 @@ def test_add_block4(self, time_mock): self.assertTrue(result) self.assertEqual(self.chain_manager.last_block, block_2) + # Duplicate set of public keys in lattice transaction + lattice_pk3 = LatticeTransaction.create(pk1=b'alice_pk11', + pk2=b'alice_pk12', + pk3=b'alice_pk13', + fee=5, + xmss_pk=alice_xmss.pk) + lattice_pk3.sign(alice_xmss) + lattice_pk3.pbdata.nonce = 3 + + seed_block = self.chain_manager.get_block_by_number(self._qn.get_seed_height(3)) + block_3 = Block.create(dev_config=config.dev, + block_number=3, + prev_headerhash=block_2.headerhash, + prev_timestamp=block_2.timestamp, + transactions=[lattice_pk3], + miner_address=bob_xmss.address, + seed_height=seed_block.block_number, + seed_hash=seed_block.headerhash) + block_3.set_nonces(config.dev, 1, 0) + + self.assertTrue(block_3.validate(self.chain_manager, {})) + result = self.chain_manager.add_block(block_3) + + self.assertFalse(result) + self.assertEqual(self.chain_manager.last_block, block_2) + @set_default_balance_size() @set_hard_fork_block_number() @patch('qrl.core.misc.ntp.getTime') From b9559c2de55d814abb65043ace216769c13f6441 Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 28 Feb 2020 11:03:02 +0530 Subject: [PATCH 62/67] Added third party ppa dependency --- .circleci/config.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 610c83033..2be74eef7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,9 +101,18 @@ jobs: TESTINPLACE: 1 steps: - checkout + - run: apt-get -y remove python3-dev python3-pip python3-venv --purge + - run: add-apt-repository ppa:deadsnakes/ppa -y + - run: apt-get update + - run: apt-get -y install python3.6 python3.6-dev python3-pip python3.6-venv + - run: update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1 + - run: python3 -m pip install + - run: python3 -m pip install -U pip setuptools - run: git submodule update --init --recursive --remote - - run: pip install -U -r tests_integration/requirements.txt - - run: pip install git+https://github.com/CurataEng/hypothesis-protobuf.git + - run: python3 -m pip install -U -r requirements.txt + - run: python3 -m pip install -U -r test-requirements.txt + - run: python3 -m pip install -U -r tests_integration/requirements.txt + - run: python3 -m pip install git+https://github.com/CurataEng/hypothesis-protobuf.git - run: pytest tests_integration/tests/python/fuzzing deploy-pypi: From c52c6416818cf315c8d2e9e8135d45a8b98faf7f Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 28 Feb 2020 13:11:16 +0530 Subject: [PATCH 63/67] Updated dependency versions --- requirements.txt | 4 ++-- setup.cfg | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6f15dfae5..814115bcb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ setuptools==39.0.1 plyvel==1.2.0 ntplib==0.3.3 -Twisted==19.2.1 +Twisted>=19.10.0 colorlog==3.1.0 simplejson==3.11.1 PyYAML==5.1 @@ -16,7 +16,7 @@ click==6.7 pyqrllib>=0.99.3,<1.1.0 pyqryptonight>=0.99.3,<1.1.0 pyqrandomx>=0.0.0,<1.0.0 -Flask==0.12.3 +Flask>=1.0.0 json-rpc==1.10.8 cryptography==2.3 mock==2.0.0 diff --git a/setup.cfg b/setup.cfg index 0b97c5d75..746fbac72 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ install_requires = setuptools==39.0.1 plyvel==1.2.0 ntplib==0.3.3 - Twisted==19.2.1 + Twisted>=19.7.0 colorlog==3.1.0 simplejson==3.11.1 PyYAML==5.1 @@ -42,7 +42,7 @@ install_requires = pyqrllib>=0.99.3,<1.1.0 pyqryptonight>=0.99.3,<1.1.0 pyqrandomx>=0.0.0,<1.0.0 - Flask==0.12.3 + Flask>=1.0.0 json-rpc==1.10.8 cryptography==2.3 mock==2.0.0 From 8bc8822f222cda57ae8136cff9fc3829e758988e Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 28 Feb 2020 13:55:07 +0530 Subject: [PATCH 64/67] Updated pyYAML version to 5.3 --- requirements.txt | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 814115bcb..9cb95e04c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ ntplib==0.3.3 Twisted>=19.10.0 colorlog==3.1.0 simplejson==3.11.1 -PyYAML==5.1 +PyYAML==5.3 grpcio-tools>=1.9.0,<=1.10.0 grpcio>=1.9.0,<=1.10.0 service_identity==17.0.0 diff --git a/setup.cfg b/setup.cfg index 746fbac72..6b7541505 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,7 +31,7 @@ install_requires = Twisted>=19.7.0 colorlog==3.1.0 simplejson==3.11.1 - PyYAML==5.1 + PyYAML==5.3 grpcio-tools>=1.9.0,<=1.10.0 grpcio>=1.9.0,<=1.10.0 service_identity==17.0.0 From e43b6941bbbc188518cd7b61ed4ed60faf8ce54a Mon Sep 17 00:00:00 2001 From: cyyber Date: Fri, 28 Feb 2020 15:23:46 +0530 Subject: [PATCH 65/67] Updated tests_integration submodule --- tests_integration | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests_integration b/tests_integration index e40df2e82..576988178 160000 --- a/tests_integration +++ b/tests_integration @@ -1 +1 @@ -Subproject commit e40df2e825dc87579c8d481e320f1a8088dd76c0 +Subproject commit 5769881780c20e6af449d9f18dfed77d53beca40 From 7dc58d05de79ef30f0d9aa8f7df953829d1897f0 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 29 Feb 2020 15:06:42 +0530 Subject: [PATCH 66/67] Added hard fork height for testnet --- src/qrl/core/config.py | 1 + src/qrl/core/p2p/p2pPeerManager.py | 4 ++++ src/qrl/main.py | 1 + 3 files changed, 6 insertions(+) diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index 4cb97dc4f..d8501c895 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -306,6 +306,7 @@ def __init__(self, pbdata, ignore_check=False, ignore_singleton=False): # HARD FORK HEIGHTS LIST # ====================================== self.hard_fork_heights = [50000] + self.testnet_hard_fork_heights = [10500] # ====================================== # PROPOSAL CONFIG diff --git a/src/qrl/core/p2p/p2pPeerManager.py b/src/qrl/core/p2p/p2pPeerManager.py index 7dd68ffa5..1788929e5 100644 --- a/src/qrl/core/p2p/p2pPeerManager.py +++ b/src/qrl/core/p2p/p2pPeerManager.py @@ -183,6 +183,10 @@ def new_channel(self, channel): channel.register(qrllegacy_pb2.LegacyMessage.P2P_ACK, self.handle_p2p_acknowledgement) def _get_version_compatibility(self, version) -> bool: + # Ignore compatibility test on Testnet + if config.dev.hard_fork_heights == config.dev.testnet_hard_fork_heights: + return True + if self._p2p_factory is None: return True if self._p2p_factory.chain_height >= config.dev.hard_fork_heights[0]: diff --git a/src/qrl/main.py b/src/qrl/main.py index 6b2eab0c7..0f1aa33f2 100644 --- a/src/qrl/main.py +++ b/src/qrl/main.py @@ -68,6 +68,7 @@ def main(): qrl_dir_post_fix = '' copy_files = [] if args.network_type == 'testnet': + config.dev.hard_fork_heights[0] = config.dev.testnet_hard_fork_heights[0] # Hard Fork Block Height For Testnet qrl_dir_post_fix = '-testnet' package_directory = os.path.dirname(os.path.abspath(__file__)) copy_files.append(os.path.join(package_directory, 'network/testnet/genesis.yml')) From 2b9b98245e2a681dcd012b33fdbdd19c038ff947 Mon Sep 17 00:00:00 2001 From: cyyber Date: Sat, 29 Feb 2020 15:07:01 +0530 Subject: [PATCH 67/67] Updated testnet config & genesis file --- src/qrl/core/config.py | 2 +- src/qrl/network/testnet/config.yml | 4 +-- src/qrl/network/testnet/genesis.yml | 48 ++++++++++++----------------- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/qrl/core/config.py b/src/qrl/core/config.py index d8501c895..79acdfdbc 100644 --- a/src/qrl/core/config.py +++ b/src/qrl/core/config.py @@ -305,7 +305,7 @@ def __init__(self, pbdata, ignore_check=False, ignore_singleton=False): # ====================================== # HARD FORK HEIGHTS LIST # ====================================== - self.hard_fork_heights = [50000] + self.hard_fork_heights = [1000000] self.testnet_hard_fork_heights = [10500] # ====================================== diff --git a/src/qrl/network/testnet/config.yml b/src/qrl/network/testnet/config.yml index 0134802b3..5d340a636 100644 --- a/src/qrl/network/testnet/config.yml +++ b/src/qrl/network/testnet/config.yml @@ -1,4 +1,4 @@ -peer_list: [ "18.130.83.207", "35.176.41.49", "18.130.187.220", "35.176.33.242" ] -genesis_prev_headerhash: 'The Testnet Genesis' +peer_list: [ "18.130.83.207", "209.250.246.234", "136.244.104.146", "95.179.154.132" ] +genesis_prev_headerhash: 'The Random Genesis' genesis_timestamp: 1530004179 genesis_difficulty: 5000 diff --git a/src/qrl/network/testnet/genesis.yml b/src/qrl/network/testnet/genesis.yml index cc18318a7..41ddc87ed 100644 --- a/src/qrl/network/testnet/genesis.yml +++ b/src/qrl/network/testnet/genesis.yml @@ -1,35 +1,25 @@ genesisBalance: -- {address: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, balance: '105000000000000000'} -header: {hashHeader: zTnPTGwZrMT+T1dxN/8mr2jArzsYatEQFFkboJJvfGg=, hashHeaderPrev: VGhlIFRlc3RuZXQgR2VuZXNpcw==, - merkleRoot: WI9TSXvP+6mAjffoX05uprLk/ace20rIN2iyLnYYyeU=, rewardBlock: '65000000000000000', - timestampSeconds: '1530004179'} +- address: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + balance: '105000000000000000' +header: + hashHeader: rckb4saj+nhyhITw/Sq8B1u41wuEQlXTgB6+ZY8w3OA= + hashHeaderPrev: VGhlIFJhbmRvbSBHZW5lc2lz + merkleRoot: 73X3ZuGhfJW0ZUYERkNUsOgnCHy/KEpzOBHrg1FoQwk= + rewardBlock: '65000000000000000' + timestampSeconds: '1530004179' transactions: -- coinbase: {addrTo: AQUAP581PQiqk/bKCLX92e0qtLZSJSTIq41N4yZpPA8qK3T0VC2l, amount: '65000000000000000'} +- coinbase: + addrTo: AQQAmNCiz8wvUfNHLG+tu0uOVpCUTbCdfJav9Nei1vYjJsbA9pro + amount: '65000000000000000' masterAddr: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= nonce: '1' - transactionHash: ySWhauTK7jCA7QT5r+kpgOIPGGavsWmTo37IuhqAAiM= + transactionHash: /dPYWbLfw7IN8y3DyHXAy3O2+i4bCIgPm/WwM5zRJiw= - nonce: '1' - publicKey: AQUADQjp7dOFQYDsWzaynbDdiPcs1bypV/Bfch68FOghq9iS36U210VGizuzg0PXjojTRTksDQv/Z4t1zXOrdMBt2A== - signature: AAAAALwB7YZL2an2Kc39uPAYRa2hnh1rAHQnhbExk5uRrA+7WVbG/7yK9s0OxJqeSSIlPaJxBhNi0ZbF7txTAzqZ/0VR2DFf3X1Khfz7RTh1zsjQKowBxyY5M1f+1TcmMD71S2bsTQ2TX+nyfITV+rH4kTHHhQ8k417RGBuZBju8kvJoWkLkDE5s0AfS+ocGqOBYc3+ECNYh/wktXgNu/nSiTuekiDxBLCSrg1zJtkwt+B4yTdc4lXU5Hle7zbozZuAZRUwyWUgHxM7JV3TwKP7NPAKcw4NftA3XMrCCCpDYqm3a7xs4wHrNNOW3nu9A5ZEHEl80meBXP8Woqvy6YLqcxAohjgDp3h8H+p3pZ9MkeB1FWT1cuDt0WxSKnpFyrIk+k6UqUW/X0s/leeppTKw9ugzBm9GqNPM+xm++pkn3AVm+ji5LO4WF2PPWQDhFT0vmJC7ZPaORYUXQkRlYHYkFXQ6t1RLm6KgWMx6sMZHOxCApIDKfIjT2df8qEtsIHpcd+hoWYvmUy+FCxtyxGCV+MgAKyjpshkFN9opmqUK5Tg2gFMpp8orPDDhpAsWVYgG+pNqZIRCUFRJJg20EKsijLEJYkzOABuJc5xjFt5QImWZvs4ju8WU6btgP4gd8cvlXcytfXr5lKJowlxQsufWRp6NF5+K/q2LyK5QlFfiPQhHKXVczdyWp9oFP63xh1oeSH225Cbcz04AohbostMjchXpEn2NJQDz8e4VO5rFWwuL7QD0jE9ZlHAhv+jPIaXoXmc/VUiWv6z+2Yu4BAzgFkOhA0sAFx17H9bk1uAhZQKu6DGE9hUgQLn2wfBHsfn9wN/d99g4EhZEqomzj9CQI8voUpMJ0uZO/y692QVgt8P7zxg0bH5dpC1SLDFKuf39c4+1PO68c6b34lwbWjfapSP//uyXUVNPm6jcBcyiszDsSE/N6vQFLGqtYzLLkorTGoKTMstFUnUN0zTtgdTyY9AUhVtA3+NeiVndNFxhnNztxzTAZTGwL/ijQ1rP0OYH0/X6mBg0S7usjLSOAMbSKDogKZsHAccyM9KPQX8InaJFeY+F67g06G8b4kOunGrExT3pkN3+SYJ1gSQ2TxA/bZtC1JWj1G4wIyvmCpvsziFYrYmP8Sb4dzPep5RHNIHM9w6NiKxpdxe8wAeB/kDmaQPPMnEugDm5zSW6M0QuEwahAJuOdDgL+EpAA0Kh+yn7cPVDPvVxLOK+APtcB+ObpOwEDe05W+RBGixs4QgdbVHTI//dSwImmyXC6Ird575jPnxkZLzz/UReVfiMaDrIuPG2hLykfbi8ZpE/St4epBB0/bIkks95NC7WNO5CzdHeS0Jst8Fj9fhwTKChJ3rbizHL2UCf05FaKpoiojrabY+glGwuGw/Ij1k5OSfBVTlzcLkPg96qSkUNv3l2lxMDs5YKMEbZCv3OGKplcP/9A380l9DeeL2q7eugfZ97ml8CJto6awQcQLGfkyJOznrDKORP8j3qlG+pfcmEG1h1+2YIp89i3ujSIbvs1cbbuv9MdHrJ54+hgA/hhQh40dmzQe529nKFbnkSbWqW4BsmuYrAMzR7UO/VhwE5ZFI97k3So0xOmZJ6FMD03ktUfJHWtTa/ydIzfnkTUSPZYpJsgFpyLNYhHnaPwSuNuLo9ut2aEHFJtvLHA93KWpELl03wKaLs1PGhJE3IJx0PwZRS//wq2ztxNXQTK1tJsGVMSwX3D05G3wGzw8yHK+mU6edHpazdiip1F76XY3gtdeDZD2JegqidYbPT5Xt1aQV5nddUqdmEFiQnsAL31fDAgatgyMjEiYPVCCgOot83EZyvaEWhau4uPF8EhC3hOW+w23t+HylTopMAPWBWJhLHOi4OTT/jfz5zP3vHCy1HDXMBFc1TVrGiWnYCDaQ+8J3q/dnAgCQYFUC3DankIs7qvX6UeyEojfd0DSE6/LaJIpm2Vmk0F5IRDjI8NohROU0oZzC3yHrVuU1ymdY/sefYSrVQbmBc71OAfaXP622cNEupfyPtI2XUAXCURVMvHrNTVS15cNmyZAynCWEjoTLuJGjOHAfrtAxUQhYpdLpwlAuVnePVzJWHWNoHIU291R94C6M5CGtsbrD5fF4okO9T5dD72iVTEFoK1fhxFpikY1zb1Gqrm+wF6zhrI39RUUrO39oiaIxGKDPTXRkO//wV2iHbOrwrHt3bMzMjR4gmkjSNHgmk+UOn/Y3i3izaPphMqeI7C/WBCHNSVhf/IYIaKWCjT7FFxDgzzgOGJQa0IOrFLcnwXo5Oyc4G+yh1vJcwbW8o6aHXhxlkdixm3dqY255gRgmkqrW3/4g8WqCXE4UrnVadWOYfiq6j+SrC15wRKHUnT/io9IxIxdNjvOS0pk9HUDBoO/40BHnp0Pa2n6+aKjo6taAOLM5IHvVf0D9qKabn4irijB/cPTZrqtLrZnX7uMy/uw6vx7GLlEJJa4tjGVQ5gQqQKOD057Rfomgs4qXbZK5H6n0SH6ghRj7/wMte20QIoGQUZHqDARcDSIg3ekZ/KLqgudX5nCYpV3c9McHmD3FjRsXGktNwIJrkyQJxCGOdMlGz2WsmCJGdNYuT5UGVdwp0PNxgdQ4A5zF/LS1X3WZC0D0sa4MtQFdz1DSdGo8fwabLQoKASYgXKXibWv7Ziuugok/RseXSsraGph8R7USwr17ofiy0G9VUggCwcWRwmwWhmN9wOQMo/xeyYKd/fZq1LMsITybRsoeMWmBywWpxm+ttDaHAtBtFvVw4PMRZ04B3rWONT1ZaXTGeDHH9dR69+8iJOCo8UKPnQVztFH++UjbVj2Mh0C1YQ+z+ZS/9u2S3i98uisUbaCZnW1sn1iZtkI7xJJgWiUo1rZoIYVbsOAyTPXUbtgzJREo9lYwLPlCTiAHRfZ8q7azTUQ+wQIUytXpKd3HTe60LWNJ0LJzj5cNx1Oeln7Ct6MEo4SLp/sGhpPSGLbVVuVvf1mpGKfrOKVDVi2zRiUPSLm+5PfXkriuz7Y3NQrXHJmTAX6jKoJHbhEpJLiNGYE2LzJTYbpndLFGVYq8mu8cf/tecpBXSsqMxQCxURkowcWe3MCzGIWRVR+TD2qfmYF6Fkb6tFmaP3cLkUuEh6Tf81XwyRnjN40bLeVrKUA01TwG1ATBoFGZ7UyFAmr6i0IV1i8GHQUowwvv1qLmulj0wovhD16byUANqpQbDYnwI5LyvDRd2n7cPU8T55+54V1/mlvNOdNb17XjZlMo5i89FcbZfhvXd3UECG9DFEpIXbyGeTnu78q8c1amHg9vFJVAi+0/zyMkQlJHUnhL+LJqbvfKMDzQ== - transactionHash: 6IhL/ZYfWzFAnhs01yS1QfGos4kQI6LHJadNuVR6KmA= + publicKey: AQQADERQmiPUWB/2vHpSB9/i14UyY8JH67O2dZhUJwNitUUifQ/ygixZfjofEAg/q2Qo7kyMBMA+XMon5nWTM6w5Dg== + signature: AAAAAMQ/u0ZGK2Y3cgsZha2WBSJIktMRoRqlDWYzWRMOa1uAJzG6k2Y3AM9RRpuivUHQuLeu83cGo6s0ENKLr03h0dWVHuP7munIVmqcotLi8uw56+zNNN6cT0X6B4oqgdt/z5gSxb/rK/zRo0XNx0aF+d/CO5zjiiZ1htpJ3+UgwUKba9wxAZyCwYOtAGhnZkTRYelnxwIrajISWMwmVrc+S0PY8RYXNMuiahV5BFhxO6iQqsyzDbjtwZ5+CwWpUOUPQ7UYHVRFrAATZXoTYnWeCuRJa7/7RCeylNFd0CDGyt0m6Vw2vFTDcNnUhWQMmaa+nWtarq4X3IUkkrP1p75BQLVawKmgCCH+5c16H5jfN6zZAiR+zFRu6xdx1uYiQeKRkqoArhTOhZ262QVjxaIBMmDE3dcxU0C2G6mTEamW9OgKX1Xy/3YzlEqDOQacyRie5DruzJojBC25zfMf0wpIKzPChaNwhaWTlfO6h7V//zxv8gvmvR1xu7rBXxL/gB3YavvEfeYr35d227ArZIWn/7q3iO4mOBfWLdZAJdE6yY3HJ98FasaO+7r9SEX42sI6T/2RaE39Al7wfAMuNjCSdSDwCEtlThITQqn+ANElgpCHVthwyVekZEmR10MeYp6R0t2iolnYew0WTRbmp7y0wgKaCFgmDesDgA/kOY7AjQPUtPta/j8pOSZ6vLLvfTc5nZ68kg44GhvkqVI8b9vVOuWAd4DaTvqsnXdT7gRENish3LAtBI1qyTABvi9zNMNOfHrRfptjJElbwWSRvZ9wHm7BPDbY6R+r4s8zm7u57ak9aGRaXJpOQqtEf810gH2jgjEH6VKy4ZsVJwjs1SP1lyqTe5UNgDNLU6/mlZ4dy8ZSwQ0QFryy1Eh6pP3yd1EtJ9+F5stqTzVEDOe+MYxQvykuMbVcWpo9BAU4LGirDPYDNbaIqCf0NW5oFVg7iKJ97GeHAaOGq7golPD4ftUc6uhz67frLFgEqeVIO+ZLWqLFWI0hVtiQV39PYDmjwoZvxGxe3PiiaqhnzezI0h0xlXFcEkazWy1KSO8oT1PXVnqQb3xSRCQZ2LxPpyWFUFAAS/3vEIZUZu5IMaP3eKoDTNU59BvRFZjoosEShT/RlI63y00ljqbP1g4VbWfZY7V/P57w2WZI0TI8ObDbXRBJD1zBsIJzqPsDrDbZkeCPhV4mmmBoKMCJTwp0iwtWRvqRGFRRho5Wjn0HYu1/cBSjmdZtv7GwuX3eQB5H0dTh9dshhpbegb0wBcUR6d6gEX68FurS+ChqB7UpR5IXmA9F3+MssLeOWWDORzX+dxrfy8hkG+B0jlChHvBf1rempO4Azf1sC3g2Xm+riPTewKXMo+MKnMDflQA7JxJSJ8UHd0hwaIuhW3nCGC6tKnoKjHxF9KXdzdK6i6USKvWVBnWrZcKuU/wCuzwmuj9XryZnJ3d7bbAaW9gUQAZqCjyX0pJwM2ylVyoVhTKu8pxkOGvPZTokwy8FuSlfVya2z2eyQKX2c6DqjwyaPDW9C4S7ndX3ClEeaNEdeV5l0uS4c6xFyC3z6yUJzrR1bO9NsVwOSYNoP4v7s6om+Y+wgvt3LZT5mZFyy8iNYMIMis0xtVjmgNCTO3/Flm9YFgxu8Gtcw77lLnH1q+N8oaT/buIvuA1c1GmlqCkti//vdN3lxwl6/jjtZOQ+l4Tf1aw1RZtYB5NM8K+/H8shpIcM8R43SzpbmnwTRNe7CS4SXu+f824yKPNHUCFUsIOoVC8HzazJ1RCExpeDVHjLvbi1B/ot286uDkJEh46iDfAUTdt52xxJd3kbsj/YZJFgYVmzHuZYiZ+JcxeWOkyn0deW0g7xrx13VOlJ3iqWE9fC2PDI0vhvBZmhlX3OOwDBCvXaisO7i+ywaT7JaIsEKRRZqERl2nnJXh0wLzLys35eDIEB3u5THz1HQ8h/dAM3/i/oR2s4K0TONl9XSd97/aMSxkUrVlKF+lzJSfDjj5HzlCg1Ga8HaGBaegIMYbCqIv1R4QuW/zMQ3eKbmh6UzHNQRhGf5kHTNAVa44JuizRen3/XtxPFFF89IwFIyqPX3kEe8FSBv+KWc76t6lbDz1GEyNK5fTGKtB0eWoj7gnqSvEFZ6hRyGxtTo4JWJeT+iBQrjrdLPLWGQsAWIt7dzpSWGstiN1mBxrCxVlUJVEsmbF6dS5CKZWAfS6lS6SRRrI6bjZt+e7DzNmVC8tF9q+Ti0AkpVJnlAhGoaD7Xsz4f8rOePVK5/Ew8bQMCUOl2Hh5XGcYZ3BPNW36ytabBiriUBA9U61rYXOPja7PEl9FZHFJkV/y6idva2/+Xc2C2e+ccOGAKZIcVfig4b0bwbkdfGj3BHJ1Cfx1kZ/szbZL+f8JR3vKJLcBLGXElHISNKxEUFG/ikvSdpCGGRveOGt19FcDkKGDLAFDqB839IVM8/15eHwEWdYUuCyUyb6x22q678JCT9KS4skqAaADV0m+NOTV+GilmKkx5vjWRXIAFg9lKK0hIFC0W8n21aijMT6sU5gMia4+3c0YfWtkCYjtXTHSxg8mJFrmsLAwgSuMFa/Lut9FR3puDXDuZvB+JN1mvb/ufUaOpICiUqmHWhHZD/t6shOPaDvhZtRX6tYNLx9Y28erN3aku0EWTHtRhBGHxVcyFIaM9fvCbnCn8NqZD3d766seqC3isrWsQcEcsJ3mch4SbJQwEvvl3cqp4BxnlhUVv4CnUdN+h1Ha2B/htiP4CDzNytwqBBHssACFK9QIg1CCuqHpEr2EE/pf6PPcIWN+i6ld56TKHicf60sRW/A42BSJ7h/vzlJZw3Xa6XPtDVQWuB8fq2MvO4qk32D+kmoS3/JzQX/WvLiZQAz5p8EGtAIKWBIPVUJ20skkscOYeTeBxSsQm2G74u7PaWlsiokUbu/Sut/wkJIQraH2VjCkbC6Vy3LIcx/F/+B6I98a5YlEuAFpD20qVfwHebpBWgqQjyRIo8hEEhXhbhEbfKtteDShxWA4M3q2BkKgoxv+wDAL1dlkPoAGxjL2PoumQ6EQOGvYgg8ZBE4joDH4MP3tNFXOD5B6aHR6rEii55cAnnFjlFH6IUiVCtsVguo7gIzaKMxDpgxVVjWB06OAcXs7L20wL8aqZUQmZAEWNPj+Yui2MqKbpv7hG9Qbqtf1pJdMmV15X8w2ydi4qEOip4tkNSKfN+1JU2BEEYYkl0+7DMVYijbGZtr4wYy1UxDR5dlLaP+Je + transactionHash: 6+NptoXHMhhBG+JYDRIy/KIuHkHiMMA4ExQVpJ0ar4M= transfer: - addrsTo: [AQMAmMXxlr05m0gMKMeyqzbGAScYYgnsHhkdos2btmV1N2YPRTAr, AQUAMXzlAhI8DeZxH9TqaDPqNg6Vy0CvcZRO6jjakL+12DdA0B5Q, - AQYA6/PGyseeabX7AQ5BnzvoH88YiCchKYh/9gHfF5RzUySiw2YQ, AQUA68H8kCdZsRrEOX2EiogYVRauKfBPAZbY0mNES8fcxw/MhQJ6, - AQUABwTFd9VXslEzMtSrzrVrouiULgw4amZLK3Wx7dTkAwGbhKo3, AQUAm7iePNiVDmIBbqElsOwidloXyYGpDL3JFLXAEojDunHZaH+r, - AQUAf03L/rELXH5iXmQh/P+PQ7xvT3pmYmi3Rx4vCGU54nAX+vCv, AQUABc41hpjQgCfRwDMKRnVVv8A2Udjmfb2dtzsv1BkfiYpISo2j, - AQQA6ZhwjU4fk/JcdK79OzmQojVo7es1SyQDLwS8DsZhZzv5t6ii, AQIAmLAUwLHjp9zry6yVbz3eIlHvDSp80Qby7N5SoOqhp+vpVyW/, - AQUAnx588JeaZ/auZUfbqfNSicAu8GUTHCGhKB51+YWKgzho42LT, AQUAC7VCLVflaTMQVdzuOhvAM0pDnSmRBdKhSax1vrqVzr0F0keP, - AQUA/oCF0pKJVfI++QoxwhVvV1vF8NUGcM4Jov87Y4HK/P/euEk+, AQUAdSDRJ+sbkEn562+2rTuRe9+oh7E40t2HTn4rM5I/HVAtDxOn, - AQUAJ/JiAyIcmLxiArWi9Wc0ioERD9SEEaTwPWCav25pnNipIshg, AQUAIpIoocpQTt8Ya7YH7gXrO3ArM/iyWt/RbD6eSTOqBdOoMMgS, - AQYAocRKrqQ8kKSrCY6qi1vsbCgwS9uebHQTKDeiQlWkampc+Ra6, AQUAs0fSxKHrpSdbYcN7LGakeXHVjdBsXnwNewjoYMl4ZYD74+/j, - AQUAfoSLiyaUrVmd5paF/z4sVW0qgXwWHtB0DedpHzzzrXV2Huur, AQUAY+xDh4hbJn2SPIHUrgeshkEtsWF+Em2jp9qo62IyT+DVcEDO, - AQUAi3RxgqQDsLccXFUPsj7NinQ8XjuX3ZcsB9fRXfibTa0tyy+W, AQUA2bjXCM0gQd406wvCbdsufuoUZ2QPG/N18IN95E2t6sXKRJ42, - AQUAjbzLqQvcLnkRXmRxzIzfTHEwsT7vRVW1jAAPkX6kArRBv45Q, AQUAWIZsC+m0CoqS1gbF3JCb/WyABRCddDQ36t77CEiHNf4/7v+1, - AQUAWBzM+xk/ywXCNm4FD5hP2yxTc5buOsRS0sfJL0VL2PPvGcQj, AQMA5vlJm3iJ7hX1pdU2srNNaOf9kVRzwq5Z5Qd7O0jHT5/ZkV2D, - AQYAJoas3IkIdHkQO2mhCUsbltqRZ1rcpJUqoW9Rsy2T1uG2vRDA] - amounts: ['70000000000000', '2000000000000', '500000000000000', '100000000000', - '50000000000', '1000000000000', '4000000000000', '10014000000000', '1715229300000', - '1100000000', '1000000000000', '540000000000', '5000000000', '55000000000', - '1000000000', '10000000000000', '100000000000', '1234000000000', '200000000000', - '1000000000000', '14804070700000', '10000000000000', '5000000000000', '1000000000', - '1000000000000', '60000000000000', '775000000000000'] + addrsTo: + - AQUAOMoiZKBu4VSmgSAfmQebzR3fKDVQYLlp2u0l3Zjvv5/9Ybm2 + amounts: + - '65000000000000000' \ No newline at end of file