diff --git a/_chain b/_chain
index f43502e..85768c8 100755
--- a/_chain
+++ b/_chain
@@ -1 +1 @@
-Qma8qnxgJ8rtCoo6grgzYb9d346pAFjm7vcvxpXVwAFYo7
+QmYS8rkJee27cXLy6fbZAoweBFHNUkfTZ4V3YrWfNtWFwA
diff --git a/_comments b/_comments
index 7fd7e36..fad95b3 100755
--- a/_comments
+++ b/_comments
@@ -164,3 +164,5 @@ OK
2019-11-27: sms
2019-12-10:
2019-12-10:
+2019-12-10: fourletterphat
+2019-12-11:
diff --git a/_nanodate b/_nanodate
index 46c44af..b7d14df 100755
--- a/_nanodate
+++ b/_nanodate
@@ -1 +1 @@
-1575941136113508325
+1576059397859243783
diff --git a/_publishkey.gpg b/_publishkey.gpg
index 30b9790..817c0b5 100755
Binary files a/_publishkey.gpg and b/_publishkey.gpg differ
diff --git a/shell/init_keys.sh b/shell/init_keys.sh
index 55d0735..296e17d 100755
--- a/shell/init_keys.sh
+++ b/shell/init_keys.sh
@@ -53,8 +53,6 @@ if [[ -f ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate ]]; then
fi
fi
-echo $NANODATE > ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate
-
#################################################################
# CREATE NODE .$IPFSNODEID SPACE (G1Wallet + TASK + NODE DETAILS)
#################################################################
@@ -62,6 +60,7 @@ echo $NANODATE > ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate
if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then
mkdir -p ./wallets/.$IPFSNODEID/TASK
NODEG1WALLET=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$IPFSNODEID" -password="$GPGPASS")
+ if [[ ! $NODEG1WALLET ]]; then echo "PROBLEME CREATION DU WALLET G1 DE $IPFSNODEID"; exit; fi
echo "${GPGPASS}" | gpg -q --output "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.GPGPASS.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./authfile"
./shell/natools.py encrypt -p $NODEG1WALLET -i "./authfile" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.crypt"
rm -f ./authfile
@@ -101,6 +100,8 @@ if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then
gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "$NODEG1WALLET" 1>&2
fi
+echo $NANODATE > ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate
+
################################################################
#INFORM ABOUT NODE CAPACITIES
export NODEPUB=$(cat "./wallets/.$IPFSNODEID/$IPFSNODEID.pub")
diff --git a/shell/sms_G1TAG.sh b/shell/sms_G1TAG.sh
index 5aa00d8..bfb5345 100755
--- a/shell/sms_G1TAG.sh
+++ b/shell/sms_G1TAG.sh
@@ -10,6 +10,8 @@
# BJ: WRITE G1Tag
# WRITE ACCESS ONLY for B possessor and NODE G1Tag Creator
# TODO: MAKE http API for G1Tag accessible through local ipfs gateway !!!!
+# https://github.com/typicode/lowdb USE json and ipfs DAG??!
+#
# TAG 250 => Imprime un G1Tag rempli de 250 UNIT
# TAG 2 100 => Imprime 100 G1Tag BON de 2 UNIT
# PHONE any ./wallets/IDs
@@ -220,6 +222,8 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash
# WRITE G1Tag G1 amount
convert -pointsize 150 -fill black -gravity Center -draw 'text 240,-140 "'"$2"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png"
+ convert -pointsize 50 -fill black -gravity NorthEast -draw 'text -100,0 "'"G1"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png"
+
# WRITE G1Tag RR
convert -pointsize 40 -fill black -gravity SouthWest -draw 'text 0,0 "'"${RR}"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png"
diff --git a/shell/tag_OP.sh b/shell/tag_OP.sh
index 54145ef..7d30dd4 100755
--- a/shell/tag_OP.sh
+++ b/shell/tag_OP.sh
@@ -156,9 +156,9 @@ fi
echo "__SUB:tag_OP.sh: DONE. G1Tag balance updated:
$JSOURCERR (/ipns/$JSOURCE) : $JSOURCEVALUE => $FINALSOURCE
$JDESTRR (/ipns/$JSDEST) : $JDESTVALUE) => $FINALDEST"
-return 1
+
else
echo "__SUB:tag_OP.sh: NO OPERATION DONE"
- return 0
+
fi
######################################################################################################
diff --git a/shell/tag_READ_X.sh b/shell/tag_READ_X.sh
new file mode 100755
index 0000000..e514a7b
--- /dev/null
+++ b/shell/tag_READ_X.sh
@@ -0,0 +1,261 @@
+#!/bin/bash
+################################################################################
+# Author: Fred (support@qo-op.com)
+# Version: 0.1
+# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
+###########################################################################################
+###########################################################################################
+# Lit les données reçues depuis un lecteur de QR Code branché en USB/SERIE (/dev/ttyACM0)
+# Interpète les G1QRcodes et les G1Tag (R/W)
+# Saisie du montant à transférer par pavé numérique
+###########################################################################################
+echo "__SUB:tag_READ_X.sh: QRCODE READER : START"
+source ./shell/init.sh
+source ./shell/functions.sh
+
+# DOUCHETTE ES TU LA?
+if [ ! $G1TX ]; then echo "Branchez votre lecteur de QR code!"; exit; fi
+./shell/tools/4LETTER.scroll.py "G1TX SCAN QRCODE G1 + G1TAG PRET"
+./shell/timeout.sh -t 2 ./shell/tools/4LETTER.spinner.py
+
+# TABLEAU MEMOIRE DE SCAN
+declare -a act
+declare -a obj
+declare -a val
+
+cat /dev/ttyACM0 | while read line; do
+ lon=${#line}
+ pref=$(echo $line | cut -d ":" -f 1)
+ qrvalue=$(echo $line | cut -d ":" -f 2)
+ log "__SUB:tag_READ_X.sh: SCAN /dev/ttyACM0 ($lon) :: $line"
+
+ case $pref in
+ RJ)
+ R=$(echo $qrvalue | cut -d '#' -f 1)
+ J=$(echo $qrvalue | cut -d '#' -f 2)
+ log "__SUB:tag_READ_X.sh: Lecture G1Tag $R $J"
+ #
+ ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id");
+ if [[ "$ID" == "" ]]; then
+ ./shell/tools/4LETTER.scroll.py "MAUVAIS G1TAG DETRUIRE OU RAPPORTER A SON CREATEUR"
+ continue
+ fi
+ FID=$(echo $ID | awk '{print toupper($1)}')
+ RR=$(echo $ID | sed s/\ //g)
+
+ ./shell/tools/4LETTER.scroll.py "G1TAG $FID READ"
+ RVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount");
+ CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}')
+ if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation.
+ PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger");
+ if [[ "$PASSENGER" != "" ]]; then
+ ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $RVALUE"
+ else
+ G1VAL=$(bc -l <<< "scale=2; $RVALUE / 100" | cut -d '.' -f 1)
+ log "__SUB:tag_READ_X.sh: G1Tag $FID. Valeur $RVALUE $CURRENCY = $G1VAL G1"
+ ./shell/tools/4LETTER.scroll.py "ZEN $RVALUE"
+ fi
+ cmd="RJ"
+ CASHBACK=""
+ val+=("$RVALUE")
+ ;;
+
+ BJ)
+ BB=$(echo $qrvalue | cut -d '#' -f 1)
+ J=$(echo $qrvalue | cut -d '#' -f 2)
+ log "__SUB:tag_READ_X.sh: Ouverture G1Tag $BB $J"
+ #
+ ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id");
+ if [[ "$ID" == "" ]]; then
+ ./shell/tools/4LETTER.scroll.py "MAUVAIS G1TAG STOP"
+ continue
+ fi
+ FID=$(echo $ID | awk '{print toupper($1)}')
+ RR=$(echo $ID | sed s/\ //g)
+
+ ./shell/tools/4LETTER.scroll.py "G1TAG $FID WRITE"
+ BVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount")
+ CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}')
+ if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation.
+ PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger");
+ # DIG PUBLISHING KEY
+ if [[ -f /home/$YOU/.ipfs/keystore/$RR ]]; then
+ log "__SUB:tag_READ_X.sh: Clef de publication IPFS $RR déjà présente"
+ else
+ rm /tmp/TAG_publishkey.B.gpg
+ su $YOU -c "ipfs get -o /tmp/ /ipns/$J/TAG_publishkey.B.gpg"
+ # CHECK IF OK
+ gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg
+ if [[ ! -f /tmp/ipns.key ]]; then
+ ./shell/tools/4LETTER.scroll.py "ERREUR DECHIFFRAGE GPG"
+ continue
+ fi
+ mv /tmp/ipns.key /home/$YOU/.ipfs/keystore/$RR
+ log "__SUB:tag_READ_X.sh: Récupération de la clef de publication $RR"
+ ./shell/tools/4LETTER.scroll.py "DECHIFFRAGE CLEF"
+ fi
+ if [[ "$PASSENGER" != "" ]]; then
+ log "__SUB:tag_READ_X.sh: !!!! $FID REC Tag = $BVALUE $CURRENCY"
+ ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $BVALUE ZEN"
+ else
+ log "__SUB:tag_READ_X.sh: Ce G1 Tag $FID contient $BVALUE $CURRENCY"
+ ./shell/tools/4LETTER.scroll.py "ZEN $BVALUE"
+ fi
+ cmd="BJ"
+ val+=("$BVALUE")
+ ;;
+
+ *)
+ if [[ $lon -eq 44 ]]; then
+ ./shell/tools/4LETTER.scroll.py "PORTEFEUILLE G1" &
+ J=$qrvalue
+ if [[ "$J" != "${obj[0]}" ]]; then
+ VALUE=$(./shell/timeout.sh -t 25 ./silkaj/silkaj amount $J)
+
+ if [[ "$(echo $VALUE | cut -d ':' -f 1)" != "Error" && "$VALUE" != "" ]]; then
+ log "__SUB:tag_READ_X.sh: Ce compte monnaie libre contient $VALUE G1"
+ NOPOINT=$(echo $VALUE | cut -d '.' -f 1)
+ ./shell/tools/4LETTER.scroll.py "CONTIENT $NOPOINT G1 *** $NOPOINT G1 "
+ CASHBACK="$J"
+ cmd="G1"
+ val+=("$VALUE")
+ else
+ log "__SUB:tag_READ_X.sh: ERREUR QR code illisible. longueur $J = ${#J}"
+ if [[ "$VALUE" == "" ]]; then
+ DUNITER=$(./shell/checknodes.sh 'BAN')
+ echo "ERREUR TIMEOUT. CHANGE SILKAJ SERVER: $DUNITER"
+ ./shell/tools/4LETTER.scroll.py "ERREUR TIMEOUT SILKAJ"
+ ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py
+ CASHBACK=""
+ else
+ ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU"
+ ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py
+ CASHBACK=""
+ fi
+ fi
+ else
+ ./shell/tools/4LETTER.scroll.py "OUI CONTIENT ${val[0]} G1 !!"
+ fi
+ else
+ ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU"
+ fi
+
+ ;;
+
+ esac
+
+ ###############################################################
+ # APRES G1 CASHBACK : G1 Tag BJ WRITE => ENCAISSEMENT
+ if [[ "${cmd}" == "BJ" && "$CASHBACK" != "" && -f /home/$YOU/.ipfs/keystore/${RR} ]]; then
+ ./shell/tools/4LETTER.scroll.py "ENCAISSEMENT G1TAG"
+ log "__SUB:tag_READ_X.sh: G1 tag de $BVALUE G1 ! /ipns/$J Virement vers $CASHBACK? "
+
+ ./shell/tools/4LETTER.scroll.py "VERS PORTEFEUILLE G1"
+ # ipfs get G1Tag vers ./TAG/${RR}
+ mkdir -p ./TAG/${RR}; rm -f ./TAG/${RR}/*; chown -R $YOU ./TAG/${RR}/
+ log "__SUB:tag_READ_X.sh: ipfs get --output=./TAG/${RR} /ipns/$J"
+ su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/$J"
+
+ if [[ $(cat ./TAG/${RR}/TAG_passenger) != "" ]]; then ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER $BVALUE ZEN"; continue; fi
+
+ # Make Silkaj TX
+ G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1)
+ log "__SUB:tag_READ_X.sh: Silkaj TX $MASTERKEYFILE ($G1VAL) -> $CASHBACK"
+ PAY=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] CAPTURE G1Tag $RR" -y)
+
+ log "__SUB:tag_READ_X.sh: Silkaj output = $PAY"
+ if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" ]]; then
+ new=$(./shell/checknodes.sh "BAN")
+ sms_ERROR "$ADMINPHONE" "Il est survenu un problème avec un virement. Retour silkaj: $PAY ... $new";
+ ./shell/tools/4LETTER.scroll.py "ERREUR SILKAJ ERREUR"
+ else
+ # ENCAISSEMENT G1Tag
+ ./shell/tools/4LETTER.scroll.py "VIR ${FID} $G1VAL G1 ---) OK"
+ # CAPTURE / DESTRUCTION du G1 Tag
+ echo "0" > "./TAG/${RR}/TAG_amount"
+ echo "${J}" > "./TAG/${RR}/TAG_ipns"
+
+ # Iterate
+ if [[ -f ./TAG/${RR}/TAG_n ]]; then NN=$(cat ./TAG/${RR}/TAG_n); ((NN++)); else NN=0; fi
+
+ # TAG_actions
+ echo "$NN" > "./TAG/${RR}/TAG_n"
+ echo "${NANODATE}" > "./TAG/${RR}/TAG_nanodate"
+ echo "${IPFSNODEID}" > "./TAG/${RR}/TAG_writerid"
+
+ # EMPTY G1TAG ID AND REMOVE PUBLISHKEYS
+ echo "" > "./TAG/${RR}/TAG_id"
+ rm -f ./TAG/TAG_publishkey.*
+
+ log "__SUB:tag_READ_X.sh: Destruction G1Tag TAG_id $NN.${NANODATE} (par NODE ${IPFSNODEID}) => Value = 0"
+ I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1")
+ # TAG_chain
+ echo "$I" > "./TAG/${RR}/TAG_chain"
+ I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1")
+ # IPNS $RR PUBLISH
+ J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}")
+
+ log "__SUB:tag_READ_X.sh: Destruction de ce G1 Tag publish -k ${RR} --quieter /ipfs/${I} :: ipfs ls /ipns/$J"
+ ./shell/tools/4LETTER.scroll.py "${FID} G1TAG VIDE MERCI DE LE DETRUIRE"
+
+ # CLEAN IPFS keystore: remove NOT created NODE keys
+ SOURCENODEID=$(cat "./TAG/${RR}/TAG_nodeid")
+ if [[ "${SOURCENODEID}" != "${IPFSNODEID}" ]]; then
+ rm -f /home/$YOU/.ipfs/keystore/${RR}
+ fi
+ fi
+ else
+ # AJOUT MEMOIRE SCAN
+ ./shell/tools/4LETTER.scroll.py "ENSUITE"
+ act+=("$cmd")
+ obj+=("$J")
+ fi
+
+
+ # FLUSH MEMOIRE 2 SCAN
+ if [[ ${#act[@]} -eq 2 ]]; then
+ echo "${act[@]}"
+ echo "${obj[@]}"
+ echo "${val[@]}"
+ ###############################################################
+ # PRESENTATION RJ puis BJ différents Tag WRITE = TRANSFERT G1 TAG
+ if [[ "${act[0]}" == "RJ" && "${act[1]}" == "BJ" && "${obj[0]}" != "${obj[1]}" ]]; then
+ PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[1]}/TAG_passenger");
+ if [[ "$PASSENGER" != "" ]]; then
+ ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER";
+ else
+ # READ KEYBOARD VALUE !!!
+ COMBIEN=$(./shell/tools/matrixKeypad.py)
+ if [[ $COMBIEN -le ${val[1]} ]]; then
+ log "__SUB:tag_READ_X.sh: Transfert de G1 Tag à G1 Tag. $COMBIEN"
+ ./shell/tools/4LETTER.scroll.py "G1TAG ${FID} TRANSFERT DE $COMBIEN ZEN"
+ log "__SUB:tag_READ_X.sh: $(./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIEN $MASTERKEYFILE)"
+ else
+ ./shell/tools/4LETTER.scroll.py "$COMBIEN DEPASSE ${val[1]} $CUR DU G1TAG ${FID}"
+ fi
+ fi
+ CASHBACK=""
+ fi
+ ###############################################################
+ # PRESENTATION BJ identiques TRANSFORMATION G1 TAG en REC TAG
+ if [[ "${act[0]}" == "BJ" && "${act[1]}" == "BJ" && "${obj[0]}" == "${obj[1]}" ]]; then
+ PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[0]}/TAG_passenger");
+ if [[ "$PASSENGER" != "" ]]; then
+ ./shell/tools/4LETTER.scroll.py "DEJA TAG PASSENGER";
+ else
+ log "__SUB:tag_READ_X.sh: Transformation du G1 Tag en Rec Tag. ${val[0]} = ${val[1]}"
+ ./shell/tools/4LETTER.scroll.py "TRASNFORMATION G1TAG ${val[0]} $CUR EN PASSENGER ${FID}";
+ log "__SUB:tag_READ_X.sh: $(./shell/tag_OP.sh ${obj[0]} ${obj[0]} 0 $MASTERKEYFILE)"
+ fi
+ CASHBACK=""
+ fi
+
+ act=()
+ obj=()
+ val=()
+ ./shell/timeout.sh -t 2 ./shell/tools/4LETTER.spinner.py
+ fi
+
+ ./shell/tools/4LETTER.scroll.py "FLASHER QRCODE"
+
+done
diff --git a/shell/tools/4LETTER.clear.py b/shell/tools/4LETTER.clear.py
new file mode 100755
index 0000000..059c6c6
--- /dev/null
+++ b/shell/tools/4LETTER.clear.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+import fourletterphat
+fourletterphat.clear()
diff --git a/shell/tools/4LETTER.clock.py b/shell/tools/4LETTER.clock.py
new file mode 100755
index 0000000..138cd59
--- /dev/null
+++ b/shell/tools/4LETTER.clock.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+import time
+import fourletterphat
+
+while True:
+ fourletterphat.clear()
+
+ str_time = time.strftime("%H%M")
+
+ # Display the time
+ fourletterphat.print_number_str(str_time)
+
+ # Blink the middle decimal point
+ # int(time.time() % 2) will alternate 1 0 1 0
+ # which we can use to directly set the point
+ fourletterphat.set_decimal(1, int(time.time() % 2))
+
+ fourletterphat.show()
+ time.sleep(0.1)
diff --git a/shell/tools/4LETTER.scroll.py b/shell/tools/4LETTER.scroll.py
new file mode 100755
index 0000000..c77897f
--- /dev/null
+++ b/shell/tools/4LETTER.scroll.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+import sys
+import fourletterphat
+
+# if bad number of arguments...
+if len(sys.argv) != 2:
+
+ # display command usage
+ print("""
+ Usage:
+ python 4LETTER.scroll.py "message a afficher"
+ """)
+
+ # exit with status code error
+ exit(1)
+
+# Get message from arguments
+message = sys.argv[1]
+fourletterphat.scroll_print( message )
+
diff --git a/shell/tools/4LETTER.spinner.py b/shell/tools/4LETTER.spinner.py
new file mode 100755
index 0000000..2e4ca45
--- /dev/null
+++ b/shell/tools/4LETTER.spinner.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import time
+import fourletterphat as flp
+
+spinner = ["|", "/", "-", "\\"]
+
+while True:
+ for i in range(4):
+ for s in spinner:
+ s = s * 4
+ flp.clear()
+ flp.print_str(s)
+ flp.show()
+ time.sleep(0.1)
diff --git a/shell/tools/G1_TUX_keygen.py b/shell/tools/G1_TUX_keygen.py
new file mode 100644
index 0000000..395d75f
--- /dev/null
+++ b/shell/tools/G1_TUX_keygen.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+
+"""
+ CopyLeft 2019 Pascal Engélibert
+
+ This program 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.
+
+ This program 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 this program. If not, see .
+"""
+
+import sys
+from duniterpy.key import SigningKey
+
+def getargv(arg, default=""):
+ if arg in sys.argv and len(sys.argv) > sys.argv.index(arg)+1:
+ return sys.argv[sys.argv.index(arg)+1]
+ else:
+ return default
+
+if __name__ == "__main__":
+
+ if "--help" in sys.argv or not "-i" in sys.argv or not "-o" in sys.argv:
+ print("""Duniter MiniTools: Mass Keygen
+CopyLeft 2019 Pascal Engélibert
+
+Usage:
+python3 keygen.py -i -o
+Format: CSV ; Separator: tab
+""")
+ exit()
+
+ infile = open(getargv("-i"), "r")
+ outfile = open(getargv("-o"), "w")
+
+ i = 0
+ while True:
+ line = infile.readline()
+ if line == "":
+ break
+ i += 1
+ if "\n" in line:
+ line = line[:len(line)-1]
+
+ cols = line.split("\t")
+ while "" in cols:
+ cols.remove("")
+ if len(cols) < 2:
+ print("Error (line "+str(i)+"): less than 2 columns! (at least 2 expected)")
+ break
+
+ key = SigningKey.from_credentials(cols[0], cols[1])
+ outfile.write(cols[0]+"\t"+cols[1]+"\t"+key.pubkey+"\n")
+
+ infile.close()
+ outfile.close()
diff --git a/shell/tools/G1_TUX_natools.py b/shell/tools/G1_TUX_natools.py
new file mode 100644
index 0000000..5149743
--- /dev/null
+++ b/shell/tools/G1_TUX_natools.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+
+import os, sys, duniterpy.key, libnacl.sign
+
+def getargv(arg:str, default:str="", n:int=1, args:list=sys.argv) -> str:
+ if arg in args and len(args) > args.index(arg)+n:
+ return args[args.index(arg)+n]
+ else:
+ return default
+
+def read_data(data_path, b=True):
+ if data_path == "-":
+ if b:
+ return sys.stdin.read().encode()
+ else:
+ return sys.stdin.read()
+ else:
+ if b:
+ return open(os.path.expanduser(data_path), "rb").read()
+ else:
+ return open(os.path.expanduser(data_path), "r").read()
+
+def write_data(data, result_path):
+ (sys.stdout if result_path == "-" else open(os.path.expanduser(result_path), "wb")).write(data)
+
+def encrypt(data, pubkey):
+ return duniterpy.key.PublicKey(pubkey).encrypt_seal(data)
+
+def decrypt(data, privkey):
+ return duniterpy.key.SigningKey.from_seedhex(privkey).decrypt_seal(data)
+
+def sign(data, privkey):
+ return duniterpy.key.SigningKey.from_seedhex(privkey).sign(data)
+
+def verify(data, pubkey):
+ try:
+ return libnacl.sign.Verifier(duniterpy.key.PublicKey(pubkey).hex_pk()).verify(data)
+ except ValueError:
+ exit(1)
+
+def show_help():
+ print("""Usage:
+python3 natools.py [options]
+
+Commands:
+ encrypt Encrypt data
+ decrypt Decrypt data
+ sign Sign data
+ verify Verify data
+
+Options:
+ -i Input file path (default: -)
+ -k Privkey file path (default: authfile.key)
+ -p Pubkey (base58)
+ -o Output file path (default: -)
+
+Note: "-" means stdin or stdout.
+""")
+
+if __name__ == "__main__":
+
+ if "--help" in sys.argv:
+ show_help()
+ exit()
+
+ data_path = getargv("-i", "-")
+ privkey_path = getargv("-k", "authfile.key")
+ pubkey = getargv("-p")
+ result_path = getargv("-o", "-")
+
+ try:
+ if sys.argv[1] == "encrypt":
+ write_data(encrypt(read_data(data_path), pubkey), result_path)
+ elif sys.argv[1] == "decrypt":
+ write_data(decrypt(read_data(data_path), read_data(privkey_path, False)), result_path)
+ elif sys.argv[1] == "sign":
+ write_data(sign(read_data(data_path), read_data(privkey_path, False)), result_path)
+ elif sys.argv[1] == "verify":
+ write_data(verify(read_data(data_path), pubkey), result_path)
+ else:
+ show_help()
+ except Exception as e:
+ sys.stderr.write("Error: ", e, "\n")
+ show_help()
+ exit(1)
diff --git a/shell/g1_gen_pubkey.py b/shell/tools/G1_gen_pubkey.py
similarity index 100%
rename from shell/g1_gen_pubkey.py
rename to shell/tools/G1_gen_pubkey.py
diff --git a/shell/request_cesium_profile.py b/shell/tools/G1_request_cesium_profile.py
similarity index 100%
rename from shell/request_cesium_profile.py
rename to shell/tools/G1_request_cesium_profile.py
diff --git a/shell/g1_send_transaction.py b/shell/tools/G1_send_transaction.py
similarity index 100%
rename from shell/g1_send_transaction.py
rename to shell/tools/G1_send_transaction.py
diff --git a/shell/tools/matrixKeypad.py b/shell/tools/matrixKeypad.py
new file mode 100755
index 0000000..492de43
--- /dev/null
+++ b/shell/tools/matrixKeypad.py
@@ -0,0 +1,41 @@
+#! /usr/bin/python
+import fourletterphat
+from matrixKeypad_RPi_GPIO import keypad
+from time import sleep
+
+# Initialize the keypad class
+kp = keypad()
+
+fourletterphat.print_str("ZEN?")
+fourletterphat.show()
+
+def digit():
+ # Loop while waiting for a keypress
+ r = None
+ while r == None:
+ r = kp.getKey()
+ return r
+
+#print ("Please enter a 4 digit code: ")
+
+# Getting digit 1, printing it, then sleep to allow the next digit press.
+d1 = digit()
+#print (d1)
+sleep(0.25)
+
+d2 = digit()
+#print (d2)
+sleep(0.25)
+
+d3 = digit()
+#print (d3)
+sleep(0.25)
+
+d4 = digit()
+#print (d4)
+
+# printing out the assembled 4 digit code.
+print "%s%s%s%s"%(d1,d2,d3,d4)
+fourletterphat.clear()
+fourletterphat.scroll_print("OK %s%s%s%s"%(d1,d2,d3,d4))
+sleep(2)
diff --git a/shell/tools/matrixKeypad_RPi_GPIO.py b/shell/tools/matrixKeypad_RPi_GPIO.py
new file mode 100755
index 0000000..c162fcc
--- /dev/null
+++ b/shell/tools/matrixKeypad_RPi_GPIO.py
@@ -0,0 +1,102 @@
+# #####################################################
+# Python Library for 3x4 matrix keypad using
+# 7 of the avialable GPIO pins on the Raspberry Pi.
+#
+# This could easily be expanded to handle a 4x4 but I
+# don't have one for testing. The KEYPAD constant
+# would need to be updated. Also the setting/checking
+# of the colVal part would need to be expanded to
+# handle the extra column.
+#
+# Written by Chris Crumpacker
+# May 2013
+#
+# main structure is adapted from Bandono's
+# matrixQPI which is wiringPi based.
+# https://github.com/bandono/matrixQPi?source=cc
+# #####################################################
+
+import RPi.GPIO as GPIO
+
+class keypad():
+ # CONSTANTS
+ KEYPAD = [
+ [1,2,3],
+ [4,5,6],
+ [7,8,9],
+ ["*",0,"#"]
+ ]
+
+ ROW = [18,23,24,25]
+ COLUMN = [5,6,13]
+
+ def __init__(self):
+ GPIO.setmode(GPIO.BCM)
+
+ def getKey(self):
+
+ # Set all columns as output low
+ for j in range(len(self.COLUMN)):
+ GPIO.setup(self.COLUMN[j], GPIO.OUT)
+ GPIO.output(self.COLUMN[j], GPIO.LOW)
+
+ # Set all rows as input
+ for i in range(len(self.ROW)):
+ GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
+ # Scan rows for pushed key/button
+ # A valid key press should set "rowVal" between 0 and 3.
+ rowVal = -1
+ for i in range(len(self.ROW)):
+ tmpRead = GPIO.input(self.ROW[i])
+ if tmpRead == 0:
+ rowVal = i
+
+ # if rowVal is not 0 thru 3 then no button was pressed and we can exit
+ if rowVal <0 or rowVal >3:
+ self.exit()
+ return
+
+ # Convert columns to input
+ for j in range(len(self.COLUMN)):
+ GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
+
+ # Switch the i-th row found from scan to output
+ GPIO.setup(self.ROW[rowVal], GPIO.OUT)
+ GPIO.output(self.ROW[rowVal], GPIO.HIGH)
+
+ # Scan columns for still-pushed key/button
+ # A valid key press should set "colVal" between 0 and 2.
+ colVal = -1
+ for j in range(len(self.COLUMN)):
+ tmpRead = GPIO.input(self.COLUMN[j])
+ if tmpRead == 1:
+ colVal=j
+
+ # if colVal is not 0 thru 2 then no button was pressed and we can exit
+ if colVal <0 or colVal >2:
+ self.exit()
+ return
+
+ # Return the value of the key pressed
+ self.exit()
+ return self.KEYPAD[rowVal][colVal]
+
+ def exit(self):
+ # Reinitialize all rows and columns as input at exit
+ for i in range(len(self.ROW)):
+ GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
+ for j in range(len(self.COLUMN)):
+ GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
+if __name__ == '__main__':
+ # Initialize the keypad class
+ kp = keypad()
+
+ # Loop while waiting for a keypress
+ digit = None
+ while digit == None:
+ digit = kp.getKey()
+
+ # Print the result
+ print digit
diff --git a/shell/tools/matrixKeypad_RPi_GPIO.pyc b/shell/tools/matrixKeypad_RPi_GPIO.pyc
new file mode 100644
index 0000000..6d3fee1
Binary files /dev/null and b/shell/tools/matrixKeypad_RPi_GPIO.pyc differ