...
 
Commits (27)
......@@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi"
[packages]
commandlines = "*"
click = "*"
ipaddress = "*"
tabulate = "*"
scrypt = "*"
......
This diff is collapsed.
#!/usr/bin/env python3
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from sys import exit
from silkaj.network_tools import check_port, best_node, EndPoint
from silkaj.cli_tools import manage_cmd
if __name__ == "__main__":
ep = EndPoint().ep
if not check_port(ep["port"]):
exit(1)
best_node(ep, True)
manage_cmd()
......@@ -22,7 +22,7 @@ check_branch() {
}
update_version() {
sed -i "s/SILKAJ_VERSION = \"silkaj.*\"/SILKAJ_VERSION = \"silkaj $VERSION\"/" silkaj/constants.py
sed -i "s/SILKAJ_VERSION = \".*\"/SILKAJ_VERSION = \"$VERSION\"/" silkaj/constants.py
sed -i "s/version=\".*\",/version=\"$VERSION\",/" setup.py
git diff
}
......
......@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="silkaj",
version="0.6.0",
version="0.6.5",
author="Moul",
author_email="moul@moul.re",
description="Command line client for Duniter",
......@@ -25,7 +25,7 @@ setuptools.setup(
"Operating System :: OS Independent",
),
install_requires=[
"commandlines",
"Click",
"ipaddress",
"tabulate",
"pynacl",
......
_silkaj_completion() {
local IFS=$'
'
COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \
COMP_CWORD=$COMP_CWORD \
_SILKAJ_COMPLETE=complete $1 ) )
return 0
}
_silkaj_completionetup() {
local COMPLETION_OPTIONS=""
local BASH_VERSION_ARR=(${BASH_VERSION//./ })
# Only BASH version 4.4 and later have the nosort option.
if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then
COMPLETION_OPTIONS="-o nosort"
fi
complete $COMPLETION_OPTIONS -F _silkaj_completion silkaj
}
_silkaj_completionetup;
_silkaj_completion() {
local -a completions
local -a completions_with_descriptions
local -a response
response=("${(@f)$( env COMP_WORDS="${words[*]}" \
COMP_CWORD=$((CURRENT-1)) \
_SILKAJ_COMPLETE="complete_zsh" \
silkaj )}")
for key descr in ${(kv)response}; do
if [[ "$descr" == "_" ]]; then
completions+=("$key")
else
completions_with_descriptions+=("$key":"$descr")
fi
done
if [ -n "$completions_with_descriptions" ]; then
_describe -V unsorted completions_with_descriptions -U -Q
fi
if [ -n "$completions" ]; then
compadd -U -V unsorted -Q -a completions
fi
compstate[insert]="automenu"
}
compdef _silkaj_completion silkaj;
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
name = "silkaj"
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from silkaj.crypto_tools import get_publickey_from_seed, b58_decode, xor_bytes
from silkaj.tools import message_exit
from nacl import encoding
......@@ -7,25 +24,25 @@ import pyaes
from getpass import getpass
from os import path
from re import compile, search
import click
def auth_method(cli_args):
if cli_args.contains_switches("auth-seed"):
@click.pass_context
def auth_method(ctx):
if ctx.obj["AUTH_SEED"]:
return auth_by_seed()
if cli_args.contains_switches("auth-file"):
return auth_by_auth_file(cli_args)
if cli_args.contains_switches("auth-wif"):
if ctx.obj["AUTH_FILE"]:
return auth_by_auth_file()
if ctx.obj["AUTH_WIF"]:
return auth_by_wif()
else:
return auth_by_scrypt(cli_args)
return auth_by_scrypt()
def generate_auth_file(cli_args):
if cli_args.contains_definitions("file"):
file = cli_args.get_definition("file")
else:
def generate_auth_file(file):
if not file:
file = "authfile"
seed = auth_method(cli_args)
seed = auth_method()
with open(file, "w") as f:
f.write(seed)
print(
......@@ -35,9 +52,10 @@ def generate_auth_file(cli_args):
)
def auth_by_auth_file(cli_args):
if cli_args.contains_definitions("file"):
file = cli_args.get_definition("file")
@click.pass_context
def auth_by_auth_file(ctx):
if ctx.obj["AUTH_FILE_PATH"]:
file = ctx.obj["AUTH_FILE_PATH"]
else:
file = "authfile"
if not path.isfile(file):
......@@ -69,20 +87,13 @@ def auth_by_seed():
return seed
def auth_by_scrypt(cli_args):
@click.pass_context
def auth_by_scrypt(ctx):
salt = getpass("Please enter your Scrypt Salt (Secret identifier): ")
password = getpass("Please enter your Scrypt password (masked): ")
if (
cli_args.contains_definitions("n")
and cli_args.contains_definitions("r")
and cli_args.contains_definitions("p")
):
n, r, p = (
cli_args.get_definition("n"),
cli_args.get_definition("r"),
cli_args.get_definition("p"),
)
if ctx.obj["AUTH_SCRYPT_PARAMS"]:
n, r, p = ctx.obj["AUTH_SCRYPT_PARAMS"].split(",")
if n.isnumeric() and r.isnumeric() and p.isnumeric():
n, r, p = int(n), int(r), int(p)
if n <= 0 or n > 65536 or r <= 0 or r > 512 or p <= 0 or p > 32:
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from silkaj.network_tools import get_request
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
import urllib
from time import time
from tabulate import tabulate
from silkaj.auth import auth_method
from silkaj.crypto_tools import get_publickey_from_seed, sign_document_from_seed
from silkaj.tools import message_exit
from silkaj.network_tools import post_request, HeadBlock
from silkaj.tools import convert_time, message_exit
from silkaj.network_tools import get_request, post_request, HeadBlock
from silkaj.blockchain_tools import BlockchainParams
from silkaj.license import license_approval
from silkaj.wot import is_member, get_uid_from_pubkey, get_informations_for_identity
def send_certification(cli_args):
id_to_certify = get_informations_for_identity(cli_args.subsubcmd)
def send_certification(id_to_certify):
id_to_certify = get_informations_for_identity(id_to_certify)
main_id_to_certify = id_to_certify["uids"][0]
# Display license and ask for confirmation
license_approval(HeadBlock().head_block["currency"])
# Authentication
seed = auth_method(cli_args)
seed = auth_method()
# Check whether current user is member
issuer_pubkey = get_publickey_from_seed(seed)
......@@ -28,9 +47,24 @@ def send_certification(cli_args):
if issuer_pubkey == id_to_certify["pubkey"]:
message_exit("You can’t certify yourself!")
for certifier in main_id_to_certify["others"]:
if certifier["pubkey"] == issuer_pubkey:
message_exit("Identity already certified by " + issuer_id)
# Check if the certification can be renewed
req = get_request("wot/requirements/" + id_to_certify["pubkey"])["identities"][0]
for cert in req["certifications"]:
if cert["from"] == issuer_pubkey:
params = BlockchainParams().params
# Change params["msWindow"] to params["sigReplay"] when deployed
# https://git.duniter.org/nodes/typescript/duniter/merge_requests/1270
# Ğ1: 0<–>2y - 2y + 2m
# ĞT: 0<–>6m - 6m + ¼m
renewable = cert["expiresIn"] - params["sigValidity"] + params["msWindow"]
if renewable > 0:
renewable_date = convert_time(time() + renewable, "date")
message_exit("Certification renewable the " + renewable_date)
# Check if the certification is already in the pending certifications
for pending_cert in req["pendingCerts"]:
if pending_cert["from"] == issuer_pubkey:
message_exit("Certification is currently been processed")
# Certification confirmation
if not certification_confirmation(
......
This diff is collapsed.
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from datetime import datetime
from time import sleep
from os import system, popen
......@@ -33,7 +50,6 @@ def currency_info():
]
head_block = HeadBlock().head_block
ep = EndPoint().ep
system("clear")
print(
"Connected to node:",
ep[best_node(ep, False)],
......@@ -127,6 +143,8 @@ network_sort_keys = ["block", "member", "diffi", "uid"]
def set_network_sort_keys(some_keys):
global network_sort_keys
if some_keys is None:
return
if some_keys.endswith(","):
message_exit(
"Argument 'sort' ends with a comma, you have probably inserted a space after the comma, which is incorrect."
......@@ -144,7 +162,8 @@ def get_network_sort_key(endpoint):
return tuple(t)
def network_info(discover):
def network_info(discover, sort):
set_network_sort_keys(sort)
rows, columns = popen("stty size", "r").read().split()
wide = int(columns)
if wide < 146:
......@@ -210,7 +229,6 @@ def network_info(discover):
else:
endpoints[i]["ip6"] = endpoints[i]["ip6"][:8] + "…"
i += 1
system("clear")
print(
len(endpoints),
"peers ups, with",
......@@ -224,7 +242,9 @@ def network_info(discover):
print(tabulate(endpoints, headers="keys", tablefmt="orgtbl", stralign="center"))
def list_issuers(nbr, last):
def list_issuers(nbr, detailed):
if nbr < 0:
message_exit("The number of blocks should be positive")
head_block = HeadBlock().head_block
current_nbr = head_block["number"]
if nbr == 0:
......@@ -235,7 +255,7 @@ def list_issuers(nbr, last):
while j < len(blocks):
issuer = OrderedDict()
issuer["pubkey"] = blocks[j]["issuer"]
if last or nbr <= 30:
if detailed or nbr <= 30:
issuer["block"] = blocks[j]["number"]
issuer["gentime"] = convert_time(blocks[j]["time"], "hour")
issuer["mediantime"] = convert_time(blocks[j]["medianTime"], "hour")
......@@ -254,14 +274,13 @@ def list_issuers(nbr, last):
):
issuer2["uid"] = uid
issuer2.pop("pubkey")
system("clear")
print(
"Issuers for last {0} blocks from block n°{1} to block n°{2}".format(
nbr, current_nbr - nbr + 1, current_nbr
),
end=" ",
)
if last or nbr <= 30:
if detailed or nbr <= 30:
sorted_list = sorted(list_issuers, key=itemgetter("block"), reverse=True)
print(
"\n"
......
SILKAJ_VERSION = "silkaj 0.6.0"
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
SILKAJ_VERSION = "0.6.5"
NO_MATCHING_ID = "No matching identity"
G1_SYMBOL = "Ğ1"
GTEST_SYMBOL = "ĞTest"
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from nacl import encoding, signing, hash, bindings
from re import compile, search
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
import webbrowser
from pydoc import pager
from sys import exit
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
import click
from silkaj.network_tools import get_request, HeadBlock
from silkaj.crypto_tools import get_publickey_from_seed
from silkaj.tools import CurrencySymbol
from silkaj.tools import CurrencySymbol, message_exit
from silkaj.auth import auth_method
from silkaj.wot import check_public_key
def cmd_amount(cli_args):
if not cli_args.subsubcmd.startswith("--auth-"):
pubkeys = cli_args.subsubcmd.split(":")
@click.pass_context
def cmd_amount(ctx, pubkeys):
if not (
ctx.obj["AUTH_SCRYPT"]
or ctx.obj["AUTH_FILE"]
or ctx.obj["AUTH_SEED"]
or ctx.obj["AUTH_WIF"]
):
if not pubkeys:
message_exit("You should specify pubkeys with -p option")
pubkeys = pubkeys.split(":")
for pubkey in pubkeys:
pubkey = check_public_key(pubkey, True)
if not pubkey:
......@@ -21,7 +47,7 @@ def cmd_amount(cli_args):
if len(pubkeys) > 1:
show_amount_from_pubkey("Total", total)
else:
seed = auth_method(cli_args)
seed = auth_method()
pubkey = get_publickey_from_seed(seed)
show_amount_from_pubkey(pubkey, get_amount_from_pubkey(pubkey))
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import unicode_literals
from ipaddress import ip_address
from json import loads
......@@ -5,7 +22,7 @@ import socket
import urllib.request
import logging
from sys import exit, stderr
from commandlines import Command
import click
from silkaj.constants import (
G1_DEFAULT_ENDPOINT,
......@@ -34,7 +51,7 @@ def discover_peers(discover):
return endpoints
def recursive_discovering(endpoints):
def recursive_discovering(endpoints, endpoint):
"""
Discover recursively new nodes.
If new node found add it and try to found new node from his known nodes.
......@@ -77,15 +94,15 @@ class EndPoint(object):
EndPoint.__instance = object.__new__(cls)
return EndPoint.__instance
def __init__(self):
cli_args = Command()
@click.pass_context
def __init__(ctx, self):
ep = dict()
if cli_args.contains_switches("p"):
ep["domain"], ep["port"] = cli_args.get_definition("p").rsplit(":", 1)
if ctx.obj["PEER"]:
ep["domain"], ep["port"] = ctx.obj["PEER"].rsplit(":", 1)
else:
ep["domain"], ep["port"] = (
G1_TEST_DEFAULT_ENDPOINT
if cli_args.contains_switches("gtest")
if ctx.obj["GTEST"]
else G1_DEFAULT_ENDPOINT
)
if ep["domain"].startswith("[") and ep["domain"].endswith("]"):
......@@ -137,7 +154,8 @@ def check_ip(address):
return 0
def get_request(path, ep=EndPoint().ep):
def get_request(path, ep=None):
ep = EndPoint().ep
address = best_node(ep, False)
if address is None:
return address
......@@ -150,7 +168,8 @@ def get_request(path, ep=EndPoint().ep):
return loads(response.read().decode(encoding))
def post_request(path, postdata, ep=EndPoint().ep):
def post_request(path, postdata, ep=None):
ep = EndPoint().ep
address = best_node(ep, False)
if address is None:
return address
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from datetime import datetime
from sys import exit
......
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from re import compile, search
import math
from time import sleep
......@@ -17,12 +34,16 @@ from silkaj.money import get_sources, get_amount_from_pubkey, UDValue
from silkaj.constants import NO_MATCHING_ID
def send_transaction(cli_args):
def send_transaction(
amount, amountUD, allSources, output, comment, outputBackChange, yes
):
"""
Main function
"""
tx_amount, output, comment, allSources, outputBackChange = cmd_transaction(cli_args)
seed = auth_method(cli_args)
tx_amount, comment = cmd_transaction(
amount, amountUD, allSources, output, comment, outputBackChange
)
seed = auth_method()
issuer_pubkey = get_publickey_from_seed(seed)
pubkey_amount = get_amount_from_pubkey(issuer_pubkey)[0]
......@@ -36,8 +57,7 @@ def send_transaction(cli_args):
)
if (
cli_args.contains_switches("yes")
or cli_args.contains_switches("y")
yes
or input(
tabulate(
transaction_confirmation(
......@@ -60,36 +80,22 @@ def send_transaction(cli_args):
)
def cmd_transaction(cli_args):
def cmd_transaction(amount, amountUD, allSources, output, comment, outputBackChange):
"""
Retrieve values from command line interface
Check command line interface arguments
"""
if not (
cli_args.contains_definitions("amount")
or cli_args.contains_definitions("amountUD")
):
message_exit("--amount or --amountUD is not set")
if not cli_args.contains_definitions("output"):
if not (amount or amountUD or allSources):
message_exit("--amount nor --amountUD nor --allSources is set")
if not output:
message_exit("--output is not set")
if cli_args.contains_definitions("amount"):
tx_amount = float(cli_args.get_definition("amount")) * 100
if cli_args.contains_definitions("amountUD"):
tx_amount = float(cli_args.get_definition("amountUD")) * UDValue().ud_value
output = cli_args.get_definition("output")
comment = (
cli_args.get_definition("comment")
if cli_args.contains_definitions("comment")
else ""
)
allSources = cli_args.contains_switches("allSources")
if cli_args.contains_definitions("outputBackChange"):
outputBackChange = cli_args.get_definition("outputBackChange")
else:
outputBackChange = None
return tx_amount, output, comment, allSources, outputBackChange
if amount:
tx_amount = float(amount) * 100
if amountUD:
tx_amount = float(amountUD) * UDValue().ud_value
if allSources:
tx_amount = 0
comment = comment if comment else ""
return tx_amount, comment
def check_transaction_values(
......@@ -180,7 +186,7 @@ def generate_and_send_transaction(
issuers,
totalAmountInput,
listinput_and_amount,
outputAddresses,
issuers,
"Change operation",
)
transaction += sign_document_from_seed(transaction, seed) + "\n"
......@@ -251,41 +257,15 @@ def generate_transaction_document(
################
listoutput = []
# Outputs to receiver (if not himself)
for outputAddress in outputAddresses:
rest = AmountTransfered
unitbase = curentUnitBase
while rest > 0:
outputAmount = truncBase(rest, unitbase)
rest -= outputAmount
if outputAmount > 0:
outputAmount = int(outputAmount / math.pow(10, unitbase))
listoutput.append(
str(outputAmount)
+ ":"
+ str(unitbase)
+ ":SIG("
+ outputAddress
+ ")"
)
unitbase = unitbase - 1
if isinstance(outputAddresses, str):
generate_output(listoutput, curentUnitBase, AmountTransfered, outputAddresses)
else:
for outputAddress in outputAddresses:
generate_output(listoutput, curentUnitBase, AmountTransfered, outputAddress)
# Outputs to himself
unitbase = curentUnitBase
rest = totalAmountInput - totalAmountTransfered
while rest > 0:
outputAmount = truncBase(rest, unitbase)
rest -= outputAmount
if outputAmount > 0:
outputAmount = int(outputAmount / math.pow(10, unitbase))
listoutput.append(
str(outputAmount)
+ ":"
+ str(unitbase)
+ ":SIG("
+ OutputbackChange
+ ")"
)
unitbase = unitbase - 1
generate_output(listoutput, curentUnitBase, rest, OutputbackChange)
# Generate transaction document
##############################
......@@ -311,6 +291,23 @@ def generate_transaction_document(
return transaction_document
def generate_output(listoutput, unitbase, rest, recipient_address):
while rest > 0:
outputAmount = truncBase(rest, unitbase)
rest -= outputAmount
if outputAmount > 0:
outputAmount = int(outputAmount / math.pow(10, unitbase))
listoutput.append(
str(outputAmount)
+ ":"
+ str(unitbase)
+ ":SIG("
+ recipient_address
+ ")"
)
unitbase = unitbase - 1
def get_list_input_for_transaction(pubkey, TXamount, allinput=False):
listinput, amount = get_sources(pubkey)
......
from os import system
"""
Copyright 2016-2019 Maël Azimi <m.a@moul.re>
Silkaj is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Silkaj is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
"""
from time import time
from tabulate import tabulate
from collections import OrderedDict
......@@ -33,7 +49,6 @@ def received_sent_certifications(id):
time_first_block = get_request("blockchain/block/1")["time"]
id_certs = get_informations_for_identity(id)
certifications = OrderedDict()
system("clear")
params = BlockchainParams().params
for certs in id_certs["uids"]:
if certs["uid"].lower() == id.lower():
......@@ -93,17 +108,15 @@ def membership_status(certifications, certs, pubkey, req):
)
member = is_member(pubkey, certs["uid"])
print("member:", member)
if not member and req["wasMember"]:
if req["revoked"]:
print(
"revoked:",
req["revoked"],
"\nrevoked on:",
convert_time(req["revoked_on"]),
"\nexpired:",
req["expired"],
"\nwasMember:",
req["wasMember"],
convert_time(req["revoked_on"], "date") + "\n",
)
if not member and req["wasMember"]:
print("expired:", req["expired"], "\nwasMember:", req["wasMember"])
elif member:
print(
"Membership document expiration: "
......
from subprocess import check_output
def test_info():
"""tests 'silkaj info' returns a number of members"""
output = check_output(["silkaj", "info"])
assert "Number of members" in output.decode()
def test_wot():
"""tests 'silkaj wot' returns a number of members"""
output = check_output(["silkaj", "wot", "moul"]).decode()
assert "moul (GfKER…) from block #0-E3B0C44298FC1…" in output
assert "received_expire" in output
assert "received" in output
assert "sent" in output
assert "sent_expire" in output
def test_id():
"""tests 'silkaj id' certification on gtest"""
output = check_output(["silkaj", "--gtest", "id", "elois"]).decode()
assert "D7CYHJXjaH4j7zRdWngUbsURPnSnjsCYtvo6f8dvW3C" in output
def test_amount():
"""tests 'silkaj amount' command on gtest"""
output = check_output(["silkaj", "--gtest", "amount", "--pubkeys", "3dnbnYY9i2bHMQUGyFp5GVvJ2wBkVpus31cDJA5cfRpj"]).decode()
assert "Total amount of: 3dnbnYY9i2bHMQUGyFp5GVvJ2wBkVpus31cDJA5cfRpj" in output
assert "Total Relative =" in output
assert "UD ĞTest" in output
assert "Total Quantitative =" in output
from unittest.mock import patch
from silkaj.cert import certification_confirmation
@patch('builtins.input')
def test_certification_confirmation(mock_input):
id_to_certify = {"pubkey": "pubkeyid to certify"}
main_id_to_certify = {"uid": "id to certify"}
mock_input.return_value = "yes"
assert certification_confirmation(
"certifier id",
"certifier pubkey",
id_to_certify,
main_id_to_certify)
mock_input.assert_called_once()
@patch('builtins.input')
def test_certification_confirmation_no(mock_input):
id_to_certify = {"pubkey": "pubkeyid to certify"}
main_id_to_certify = {"uid": "id to certify"}
mock_input.return_value = "no"
assert certification_confirmation(
"certifier id",
"certifier pubkey",
id_to_certify,
main_id_to_certify) is None
mock_input.assert_called_once()
import pytest
from silkaj.tx import truncBase
@pytest.mark.parametrize('amount,base,expected', [
(0, 0, 0),
(10, 2, 0),
(100, 2, 100),
(306, 2, 300),
(3060, 3, 3000),
])
def test_truncBase(amount, base, expected):
assert truncBase(amount, base) == expected