Skip to content

Commit 75dd7c0

Browse files
committed
Hard fork changes
1 parent 130044c commit 75dd7c0

File tree

127 files changed

+21635
-5132
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+21635
-5132
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ __pycache__/*
1212
.DS_Store
1313
.*.swp
1414
*/.ipynb_checkpoints/*
15+
*_trial_temp
1516

1617
# Project files
1718
.ropeproject

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ six==1.11
1515
click==6.7
1616
pyqrllib>=0.99.3,<1.1.0
1717
pyqryptonight>=0.99.3,<1.1.0
18+
pyqrandomx>=0.0.0,<1.0.0
1819
Flask==0.12.3
1920
json-rpc==1.10.8
2021
cryptography==2.3
2122
mock==2.0.0
22-
daemonize==2.4.7
23+
daemonize==2.4.7

setup.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ install_requires =
4141
click==6.7
4242
pyqrllib>=0.99.3,<1.1.0
4343
pyqryptonight>=0.99.3,<1.1.0
44+
pyqrandomx>=0.0.0,<1.0.0
4445
Flask==0.12.3
4546
json-rpc==1.10.8
4647
cryptography==2.3

src/qrl/cli.py

+168-7
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414
from qrl.core import config
1515
from qrl.core.Wallet import Wallet, WalletDecryptionError
1616
from qrl.core.misc.helper import parse_hexblob, parse_qaddress
17+
from qrl.core.MultiSigAddressState import MultiSigAddressState
1718
from qrl.core.txs.MessageTransaction import MessageTransaction
1819
from qrl.core.txs.SlaveTransaction import SlaveTransaction
1920
from qrl.core.txs.TokenTransaction import TokenTransaction
2021
from qrl.core.txs.Transaction import Transaction
2122
from qrl.core.txs.TransferTokenTransaction import TransferTokenTransaction
2223
from qrl.core.txs.TransferTransaction import TransferTransaction
24+
from qrl.core.txs.multisig.MultiSigCreate import MultiSigCreate
25+
from qrl.core.txs.multisig.MultiSigSpend import MultiSigSpend
2326
from qrl.crypto.xmss import XMSS, hash_functions
2427
from qrl.generated import qrl_pb2_grpc, qrl_pb2
2528

@@ -181,15 +184,15 @@ def _quanta_to_shor(x: Decimal, base=Decimal(config.dev.shor_per_quanta)) -> int
181184
return int(Decimal(x * base).to_integral_value())
182185

183186

184-
def _parse_dsts_amounts(addresses: str, amounts: str, token_decimals: int = 0):
187+
def _parse_dsts_amounts(addresses: str, amounts: str, token_decimals: int = 0, check_multi_sig_address=False):
185188
"""
186189
'Qaddr1 Qaddr2...' -> [\\xcx3\\xc2, \\xc2d\\xc3]
187190
'10 10' -> [10e9, 10e9] (in shor)
188191
:param addresses:
189192
:param amounts:
190193
:return:
191194
"""
192-
addresses_split = [parse_qaddress(addr) for addr in addresses.split(' ')]
195+
addresses_split = [parse_qaddress(addr, check_multi_sig_address) for addr in addresses.split(' ')]
193196

194197
if token_decimals != 0:
195198
multiplier = Decimal(10 ** int(token_decimals))
@@ -471,11 +474,12 @@ def tx_push(ctx, txblob):
471474
@qrl.command()
472475
@click.option('--src', type=str, default='', prompt=True, help='signer QRL address')
473476
@click.option('--master', type=str, default='', prompt=True, help='master QRL address')
477+
@click.option('--addr_to', type=str, default='', prompt=True, help='QRL Address receiving this message (optional)')
474478
@click.option('--message', type=str, prompt=True, help='Message (max 80 bytes)')
475479
@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta')
476480
@click.option('--ots_key_index', default=1, prompt=True, help='OTS key Index (1..XMSS num signatures)')
477481
@click.pass_context
478-
def tx_message(ctx, src, master, message, fee, ots_key_index):
482+
def tx_message(ctx, src, master, addr_to, message, fee, ots_key_index):
479483
"""
480484
Message Transaction
481485
"""
@@ -491,6 +495,7 @@ def tx_message(ctx, src, master, message, fee, ots_key_index):
491495
src_xmss.set_ots_index(ots_key_index)
492496

493497
message = message.encode()
498+
addr_to = parse_qaddress(addr_to, False)
494499

495500
master_addr = None
496501
if master:
@@ -503,6 +508,7 @@ def tx_message(ctx, src, master, message, fee, ots_key_index):
503508
try:
504509
stub = ctx.obj.get_stub_public_api()
505510
tx = MessageTransaction.create(message_hash=message,
511+
addr_to=addr_to,
506512
fee=fee_shor,
507513
xmss_pk=address_src_pk,
508514
master_addr=master_addr)
@@ -516,6 +522,159 @@ def tx_message(ctx, src, master, message, fee, ots_key_index):
516522
print("Error {}".format(str(e)))
517523

518524

525+
@qrl.command()
526+
@click.option('--src', type=str, default='', prompt=True, help='source QRL address')
527+
@click.option('--master', type=str, default='', prompt=True, help='master QRL address')
528+
@click.option('--threshold', default=0, prompt=True, help='Threshold')
529+
@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta')
530+
@click.option('--ots_key_index', default=1, prompt=True, help='OTS key Index (1..XMSS num signatures)')
531+
@click.pass_context
532+
def tx_multi_sig_create(ctx, src, master, threshold, fee, ots_key_index):
533+
"""
534+
Creates Multi Sig Create Transaction, that results into the formation of new multi_sig_address if accepted.
535+
"""
536+
signatories = []
537+
weights = []
538+
while True:
539+
address = click.prompt('Address of Signatory ', default='')
540+
if address == '':
541+
break
542+
weight = int(click.prompt('Weight '))
543+
signatories.append(parse_qaddress(address))
544+
weights.append(weight)
545+
546+
try:
547+
_, src_xmss = _select_wallet(ctx, src)
548+
if not src_xmss:
549+
click.echo("A local wallet is required to sign the transaction")
550+
quit(1)
551+
552+
address_src_pk = src_xmss.pk
553+
554+
ots_key_index = validate_ots_index(ots_key_index, src_xmss)
555+
src_xmss.set_ots_index(ots_key_index)
556+
557+
master_addr = None
558+
if master_addr:
559+
master_addr = parse_qaddress(master)
560+
# FIXME: This could be problematic. Check
561+
fee_shor = _quanta_to_shor(fee)
562+
563+
except KeyboardInterrupt:
564+
click.echo("Terminated by user")
565+
quit(1)
566+
except Exception as e:
567+
click.echo("Error validating arguments: {}".format(e))
568+
quit(1)
569+
570+
try:
571+
stub = ctx.obj.get_stub_public_api()
572+
tx = MultiSigCreate.create(signatories=signatories,
573+
weights=weights,
574+
threshold=threshold,
575+
fee=fee_shor,
576+
xmss_pk=address_src_pk,
577+
master_addr=master_addr)
578+
579+
tx.sign(src_xmss)
580+
581+
push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata)
582+
push_transaction_resp = stub.PushTransaction(push_transaction_req, timeout=CONNECTION_TIMEOUT)
583+
584+
print(push_transaction_resp.error_code)
585+
print('Multi sig Address Q{}'.format(bin2hstr(MultiSigAddressState.generate_multi_sig_address(tx.txhash))))
586+
except Exception as e:
587+
print("Error {}".format(str(e)))
588+
589+
590+
@qrl.command()
591+
@click.option('--src', type=str, default='', prompt=True, help='signer QRL address')
592+
@click.option('--master', type=str, default='', help='master QRL address')
593+
@click.option('--multi_sig_address', type=str, default='', prompt=True, help='signer Multi Sig Address')
594+
@click.option('--dsts', type=str, prompt=True, help='List of destination addresses')
595+
@click.option('--amounts', type=str, prompt=True, help='List of amounts to transfer (Quanta)')
596+
@click.option('--expiry_block_number', type=int, prompt=True, help='Expiry Blocknumber')
597+
@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta')
598+
@click.option('--ots_key_index', default=1, help='OTS key Index (1..XMSS num signatures)')
599+
@click.pass_context
600+
def tx_multi_sig_spend(ctx, src, master, multi_sig_address, dsts, amounts, expiry_block_number, fee, ots_key_index):
601+
"""
602+
Transfer coins from src to dsts
603+
"""
604+
address_src_pk = None
605+
master_addr = None
606+
607+
addresses_dst = []
608+
shor_amounts = []
609+
fee_shor = []
610+
611+
signing_object = None
612+
613+
try:
614+
# Retrieve signing object
615+
selected_wallet = _select_wallet(ctx, src)
616+
if selected_wallet is None or len(selected_wallet) != 2:
617+
click.echo("A wallet was not found")
618+
quit(1)
619+
620+
_, src_xmss = selected_wallet
621+
622+
if not src_xmss:
623+
click.echo("A local wallet is required to sign the transaction")
624+
quit(1)
625+
626+
address_src_pk = src_xmss.pk
627+
628+
ots_key_index = validate_ots_index(ots_key_index, src_xmss)
629+
src_xmss.set_ots_index(ots_key_index)
630+
631+
signing_object = src_xmss
632+
633+
# Get and validate other inputs
634+
if master:
635+
master_addr = parse_qaddress(master)
636+
637+
addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts, check_multi_sig_address=True)
638+
fee_shor = _quanta_to_shor(fee)
639+
except Exception as e:
640+
click.echo("Error validating arguments: {}".format(e))
641+
quit(1)
642+
multi_sig_address = bytes(hstr2bin(multi_sig_address[1:]))
643+
try:
644+
# MultiSigSpend transaction
645+
tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
646+
addrs_to=addresses_dst,
647+
amounts=shor_amounts,
648+
expiry_block_number=expiry_block_number,
649+
fee=fee_shor,
650+
xmss_pk=address_src_pk,
651+
master_addr=master_addr)
652+
653+
# Sign transaction
654+
tx.sign(signing_object)
655+
656+
if not tx.validate():
657+
print("It was not possible to validate the signature")
658+
quit(1)
659+
660+
print("\nTransaction Blob (signed): \n")
661+
txblob = tx.pbdata.SerializeToString()
662+
txblobhex = hexlify(txblob).decode()
663+
print(txblobhex)
664+
665+
# Push transaction
666+
print()
667+
print("Sending to a QRL Node...")
668+
stub = ctx.obj.get_stub_public_api()
669+
push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata)
670+
push_transaction_resp = stub.PushTransaction(push_transaction_req, timeout=CONNECTION_TIMEOUT)
671+
672+
# Print result
673+
print(push_transaction_resp)
674+
except Exception as e:
675+
print("Error {}".format(str(e)))
676+
677+
519678
def base64tohex(data):
520679
return hexlify(a2b_base64(data))
521680

@@ -534,10 +693,11 @@ def tx_unbase64(tx_json_str):
534693
@click.option('--master', type=str, default='', help='master QRL address')
535694
@click.option('--dsts', type=str, prompt=True, help='List of destination addresses')
536695
@click.option('--amounts', type=str, prompt=True, help='List of amounts to transfer (Quanta)')
696+
@click.option('--message_data', type=str, prompt=True, help='Message (Optional)')
537697
@click.option('--fee', type=Decimal, default=0.0, prompt=True, help='fee in Quanta')
538698
@click.option('--ots_key_index', default=1, help='OTS key Index (1..XMSS num signatures)')
539699
@click.pass_context
540-
def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index):
700+
def tx_transfer(ctx, src, master, dsts, amounts, message_data, fee, ots_key_index):
541701
"""
542702
Transfer coins from src to dsts
543703
"""
@@ -549,6 +709,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index):
549709
fee_shor = []
550710

551711
signing_object = None
712+
message_data = message_data.encode()
552713

553714
try:
554715
# Retrieve signing object
@@ -573,8 +734,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index):
573734
# Get and validate other inputs
574735
if master:
575736
master_addr = parse_qaddress(master)
576-
577-
addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts)
737+
addresses_dst, shor_amounts = _parse_dsts_amounts(dsts, amounts, check_multi_sig_address=True)
578738
fee_shor = _quanta_to_shor(fee)
579739
except Exception as e:
580740
click.echo("Error validating arguments: {}".format(e))
@@ -584,6 +744,7 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index):
584744
# Create transaction
585745
tx = TransferTransaction.create(addrs_to=addresses_dst,
586746
amounts=shor_amounts,
747+
message_data=message_data,
587748
fee=fee_shor,
588749
xmss_pk=address_src_pk,
589750
master_addr=master_addr)
@@ -605,7 +766,6 @@ def tx_transfer(ctx, src, master, dsts, amounts, fee, ots_key_index):
605766
print(txblobhex)
606767

607768
# Push transaction
608-
print()
609769
print("Sending to a QRL Node...")
610770
stub = ctx.obj.get_stub_public_api()
611771
push_transaction_req = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata)
@@ -877,3 +1037,4 @@ def main():
8771037

8781038
if __name__ == '__main__':
8791039
main()
1040+

src/qrl/core/AddressState.py

+40
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pyqrllib.pyqrllib import QRLHelper, bin2hstr
66

77
from qrl.core import config
8+
from qrl.core.State import State
89
from qrl.generated import qrl_pb2
910

1011

@@ -234,3 +235,42 @@ def address_is_valid(address: bytes) -> bool:
234235

235236
def serialize(self):
236237
return self._data.SerializeToString()
238+
239+
@staticmethod
240+
def put_addresses_state(state: State, addresses_state: dict, batch=None):
241+
"""
242+
:param addresses_state:
243+
:param batch:
244+
:return:
245+
"""
246+
for address in addresses_state:
247+
address_state = addresses_state[address]
248+
AddressState.put_address_state(state, address_state, batch)
249+
250+
@staticmethod
251+
def put_address_state(state: State, address_state, batch=None):
252+
data = address_state.pbdata.SerializeToString()
253+
state._db.put_raw(address_state.address, data, batch)
254+
255+
@staticmethod
256+
def get_address_state(state: State, address: bytes):
257+
try:
258+
data = state._db.get_raw(address)
259+
pbdata = qrl_pb2.AddressState()
260+
pbdata.ParseFromString(bytes(data))
261+
address_state = AddressState(pbdata)
262+
return address_state
263+
except KeyError:
264+
return AddressState.get_default(address)
265+
266+
@staticmethod
267+
def return_all_addresses(state: State) -> list:
268+
addresses = []
269+
for key, data in state._db.db:
270+
if key[0] != b'Q':
271+
continue
272+
pbdata = qrl_pb2.AddressState()
273+
pbdata.ParseFromString(bytes(data))
274+
address_state = AddressState(pbdata)
275+
addresses.append(address_state)
276+
return addresses

0 commit comments

Comments
 (0)