Skip to content
Snippets Groups Projects
Commit 4a4d80ae authored by Moul's avatar Moul
Browse files

Merge branch 'multiple_outputs' into 'dev'

[enh] add support for multiple outputs

See merge request !78
parents 9bf2d8bc e093a8c4
No related branches found
No related tags found
1 merge request!78[enh] add support for multiple outputs
...@@ -39,9 +39,9 @@ def usage(): ...@@ -39,9 +39,9 @@ def usage():
\n - amount:\ \n - amount:\
\n --amountUD=<relative value> | --amount=<quantitative value>\ \n --amountUD=<relative value> | --amount=<quantitative value>\
\n [--allSources] \ \n [--allSources] \
\n --output=<public key>[:checksum] \ \n --output=<public key>[!checksum]:[<public key>[!checksum]] \
\n [--comment=<comment>] \ \n [--comment=<comment>] \
\n [--outputBackChange=<public key[:checksum]>] \ \n [--outputBackChange=<public key[!checksum]>] \
\n [-y | --yes], don't ask for prompt confirmation \ \n [-y | --yes], don't ask for prompt confirmation \
\n \ \n \
\n - cert: Send certification\ \n - cert: Send certification\
......
...@@ -52,11 +52,11 @@ def check_public_key(pubkey, display_error): ...@@ -52,11 +52,11 @@ def check_public_key(pubkey, display_error):
""" """
regex = compile('^[1-9A-HJ-NP-Za-km-z]{43,44}$') regex = compile('^[1-9A-HJ-NP-Za-km-z]{43,44}$')
regex_checksum = compile('^[1-9A-HJ-NP-Za-km-z]{43,44}' + regex_checksum = compile('^[1-9A-HJ-NP-Za-km-z]{43,44}' +
':[1-9A-HJ-NP-Za-km-z]{3}$') '![1-9A-HJ-NP-Za-km-z]{3}$')
if search(regex, pubkey): if search(regex, pubkey):
return pubkey return pubkey
elif search(regex_checksum, pubkey): elif search(regex_checksum, pubkey):
pubkey, checksum = pubkey.split(":") pubkey, checksum = pubkey.split("!")
pubkey_byte = b58_decode(pubkey) pubkey_byte = b58_decode(pubkey)
checksum_calculed = b58_encode(hash.sha256( checksum_calculed = b58_encode(hash.sha256(
hash.sha256(pubkey_byte, encoding.RawEncoder), hash.sha256(pubkey_byte, encoding.RawEncoder),
...@@ -64,11 +64,11 @@ def check_public_key(pubkey, display_error): ...@@ -64,11 +64,11 @@ def check_public_key(pubkey, display_error):
if checksum_calculed == checksum: if checksum_calculed == checksum:
return pubkey return pubkey
else: else:
print("error: bad checksum of the public key") print("Error: bad checksum for following public key:")
return False return False
elif display_error: elif display_error:
print("Error: the format of the public key is invalid") print("Error: bad format for following public key:")
return False return False
......
from re import compile, search from re import compile, search
import math import math
from time import sleep from time import sleep
from sys import exit
import urllib import urllib
from tabulate import tabulate from tabulate import tabulate
...@@ -24,12 +23,13 @@ def send_transaction(ep, cli_args): ...@@ -24,12 +23,13 @@ def send_transaction(ep, cli_args):
issuer_pubkey = get_publickey_from_seed(seed) issuer_pubkey = get_publickey_from_seed(seed)
pubkey_amount = get_amount_from_pubkey(ep, issuer_pubkey)[0] pubkey_amount = get_amount_from_pubkey(ep, issuer_pubkey)[0]
check_transaction_values(comment, output, outputBackChange, pubkey_amount < amount, issuer_pubkey) outputAddresses = output.split(':')
check_transaction_values(comment, outputAddresses, outputBackChange, pubkey_amount < amount * len(outputAddresses), issuer_pubkey)
if cli_args.contains_switches('yes') or cli_args.contains_switches('y') or \ if cli_args.contains_switches('yes') or cli_args.contains_switches('y') or \
input(tabulate(transaction_confirmation(ep, issuer_pubkey, amount, ud, output, comment), input(tabulate(transaction_confirmation(ep, issuer_pubkey, amount, ud, outputAddresses, comment),
tablefmt="fancy_grid") + "\nDo you confirm sending this transaction? [yes/no]: ") == "yes": tablefmt="fancy_grid") + "\nDo you confirm sending this transaction? [yes/no]: ") == "yes":
generate_and_send_transaction(ep, seed, issuer_pubkey, amount, output, comment, allSources, outputBackChange) generate_and_send_transaction(ep, seed, issuer_pubkey, amount, outputAddresses, comment, allSources, outputBackChange)
def cmd_transaction(cli_args, ud): def cmd_transaction(cli_args, ud):
...@@ -57,41 +57,45 @@ def cmd_transaction(cli_args, ud): ...@@ -57,41 +57,45 @@ def cmd_transaction(cli_args, ud):
return amount, output, comment, allSources, outputBackChange return amount, output, comment, allSources, outputBackChange
def check_transaction_values(comment, output, outputBackChange, enough_source, issuer_pubkey): def check_transaction_values(comment, outputAddresses, outputBackChange, enough_source, issuer_pubkey):
checkComment(comment) checkComment(comment)
for outputAddress in outputAddresses:
output = check_public_key(output, True) if check_public_key(outputAddress, True) is False:
message_exit(outputAddress)
if outputBackChange: if outputBackChange:
outputBackChange = check_public_key(outputBackChange, True) outputBackChange = check_public_key(outputBackChange, True)
if output is False or outputBackChange is False: if check_public_key(outputBackChange, True) is False:
exit(1) message_exit(outputBackChange)
if enough_source: if enough_source:
message_exit(issuer_pubkey + " pubkey don’t have enough money for this transaction.") message_exit(issuer_pubkey + " pubkey doesn’t have enough money for this transaction.")
def transaction_confirmation(ep, issuer_pubkey, amount, ud, output, comment): def transaction_confirmation(ep, issuer_pubkey, amount, ud, outputAddresses, comment):
""" """
Generate transaction confirmation Generate transaction confirmation
""" """
tx = list() tx = list()
currency_symbol = get_currency_symbol(get_current_block(ep)["currency"]) currency_symbol = get_currency_symbol(get_current_block(ep)["currency"])
tx.append(["amount (" + currency_symbol + ")", amount / 100]) tx.append(["amount (" + currency_symbol + ")", amount / 100 * len(outputAddresses)])
tx.append(["amount (UD " + currency_symbol + ")", amount / ud]) tx.append(["amount (UD " + currency_symbol + ")", amount / ud])
tx.append(["from", issuer_pubkey]) tx.append(["from", issuer_pubkey])
id_from = get_uid_from_pubkey(ep, issuer_pubkey) id_from = get_uid_from_pubkey(ep, issuer_pubkey)
if id_from is not NO_MATCHING_ID: if id_from is not NO_MATCHING_ID:
tx.append(["from (id)", id_from]) tx.append(["from (id)", id_from])
tx.append(["to", output]) for outputAddress in outputAddresses:
id_to = get_uid_from_pubkey(ep, output) tx.append(["to", outputAddress])
id_to = get_uid_from_pubkey(ep, outputAddress)
if id_to is not NO_MATCHING_ID: if id_to is not NO_MATCHING_ID:
tx.append(["to (id)", id_to]) tx.append(["to (id)", id_to])
tx.append(["comment", comment]) tx.append(["comment", comment])
return tx return tx
def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAddr, Comment="", all_input=False, OutputbackChange=None): def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAddresses, Comment="", all_input=False, OutputbackChange=None):
while True: while True:
listinput_and_amount = get_list_input_for_transaction(ep, issuers, AmountTransfered, all_input) listinput_and_amount = get_list_input_for_transaction(ep, issuers, AmountTransfered * len(outputAddresses), all_input)
intermediatetransaction = listinput_and_amount[2] intermediatetransaction = listinput_and_amount[2]
if intermediatetransaction: if intermediatetransaction:
...@@ -100,7 +104,7 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd ...@@ -100,7 +104,7 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd
print(" - From: " + issuers) print(" - From: " + issuers)
print(" - To: " + issuers) print(" - To: " + issuers)
print(" - Amount: " + str(totalAmountInput / 100)) print(" - Amount: " + str(totalAmountInput / 100))
transaction = generate_transaction_document(ep, issuers, totalAmountInput, listinput_and_amount, issuers, "Change operation") transaction = generate_transaction_document(ep, issuers, totalAmountInput, listinput_and_amount, outputAddresses, "Change operation")
transaction += sign_document_from_seed(transaction, seed) + "\n" transaction += sign_document_from_seed(transaction, seed) + "\n"
post_request(ep, "tx/process", "transaction=" + urllib.parse.quote_plus(transaction)) post_request(ep, "tx/process", "transaction=" + urllib.parse.quote_plus(transaction))
print("Change Transaction successfully sent.") print("Change Transaction successfully sent.")
...@@ -109,12 +113,13 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd ...@@ -109,12 +113,13 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd
else: else:
print("Generate Transaction:") print("Generate Transaction:")
print(" - From: " + issuers) print(" - From: " + issuers)
print(" - To: " + outputAddr) for outputAddress in outputAddresses:
print(" - To: " + outputAddress)
if all_input: if all_input:
print(" - Amount: " + str(listinput_and_amount[1] / 100)) print(" - Amount: " + str(listinput_and_amount[1] / 100))
else: else:
print(" - Amount: " + str(AmountTransfered / 100)) print(" - Amount: " + str(AmountTransfered / 100 * len(outputAddresses)))
transaction = generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_amount, outputAddr, Comment, OutputbackChange) transaction = generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_amount, outputAddresses, Comment, OutputbackChange)
transaction += sign_document_from_seed(transaction, seed) + "\n" transaction += sign_document_from_seed(transaction, seed) + "\n"
post_request(ep, "tx/process", "transaction=" + urllib.parse.quote_plus(transaction)) post_request(ep, "tx/process", "transaction=" + urllib.parse.quote_plus(transaction))
...@@ -122,10 +127,9 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd ...@@ -122,10 +127,9 @@ def generate_and_send_transaction(ep, seed, issuers, AmountTransfered, outputAdd
break break
def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_amount, outputaddr, Comment="", OutputbackChange=None): def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_amount, outputAddresses, Comment="", OutputbackChange=None):
check_public_key(outputaddr, True)
if OutputbackChange: totalAmountTransfered = AmountTransfered * len(outputAddresses)
OutputbackChange = check_public_key(OutputbackChange, True)
listinput = listinput_and_amount[0] listinput = listinput_and_amount[0]
totalAmountInput = listinput_and_amount[1] totalAmountInput = listinput_and_amount[1]
...@@ -139,13 +143,14 @@ def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_a ...@@ -139,13 +143,14 @@ def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_a
OutputbackChange = issuers OutputbackChange = issuers
# if it's not a foreign exchange transaction, we remove units after 2 digits after the decimal point. # if it's not a foreign exchange transaction, we remove units after 2 digits after the decimal point.
if issuers != outputaddr: if issuers not in outputAddresses:
AmountTransfered = (AmountTransfered // 10 ** curentUnitBase) * 10 ** curentUnitBase totalAmountTransfered = (totalAmountTransfered // 10 ** curentUnitBase) * 10 ** curentUnitBase
# Generate output # Generate output
################ ################
listoutput = [] listoutput = []
# Outputs to receiver (if not himself) # Outputs to receiver (if not himself)
for outputAddress in outputAddresses:
rest = AmountTransfered rest = AmountTransfered
unitbase = curentUnitBase unitbase = curentUnitBase
while rest > 0: while rest > 0:
...@@ -153,12 +158,12 @@ def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_a ...@@ -153,12 +158,12 @@ def generate_transaction_document(ep, issuers, AmountTransfered, listinput_and_a
rest -= outputAmount rest -= outputAmount
if outputAmount > 0: if outputAmount > 0:
outputAmount = int(outputAmount / math.pow(10, unitbase)) outputAmount = int(outputAmount / math.pow(10, unitbase))
listoutput.append(str(outputAmount) + ":" + str(unitbase) + ":SIG(" + outputaddr + ")") listoutput.append(str(outputAmount) + ":" + str(unitbase) + ":SIG(" + outputAddress + ")")
unitbase = unitbase - 1 unitbase = unitbase - 1
# Outputs to himself # Outputs to himself
unitbase = curentUnitBase unitbase = curentUnitBase
rest = totalAmountInput - AmountTransfered rest = totalAmountInput - totalAmountTransfered
while rest > 0: while rest > 0:
outputAmount = truncBase(rest, unitbase) outputAmount = truncBase(rest, unitbase)
rest -= outputAmount rest -= outputAmount
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment