From 1475790f7e2496aeced9b7b3b8957f3e8adc8695 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Mon, 13 Sep 2021 16:19:12 +0300 Subject: [PATCH 01/32] Add `erdpy wallet new ` subcommand --- MANIFEST.in | 1 + erdpy/cli_wallet.py | 35 + erdpy/wallet/core.py | 15 + erdpy/wallet/keyfile.py | 64 +- erdpy/wallet/words.txt | 2048 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 2162 insertions(+), 1 deletion(-) create mode 100644 erdpy/wallet/words.txt diff --git a/MANIFEST.in b/MANIFEST.in index 4db03511..2a4e0bd9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ include erdpy/projects/*.txt include erdpy/projects/*.json +include erdpy/wallet/*.txt include erdpy/testnet/wallets/users/*.pem include erdpy/testnet/wallets/users/*.json diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index b7fcf968..8fa29a42 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -1,4 +1,8 @@ +from erdpy.wallet.keyfile import save_to_key_file +from erdpy.wallet.core import generate_mnemonic import logging +import getpass +from pathlib import Path from typing import Any, List from erdpy import cli_shared, wallet @@ -16,6 +20,22 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: ) subparsers = parser.add_subparsers() + sub = cli_shared.add_command_subparser( + subparsers, + "wallet", + "new", + "Create a new wallet" + ) + sub.add_argument("--output-path", + help="the output path and file name for the generated wallet files", type=str, default="wallet") + sub.add_argument("--with-json", + help="whether to create a json key file", action="store_true", default=False) + sub.add_argument("--with-pem", + help="whether to create a json key file", action="store_true", default=False) + sub.add_argument("--index", + help="the account index", type=int, default=0) + sub.set_defaults(func=new_wallet) + sub = cli_shared.add_command_subparser( subparsers, "wallet", @@ -69,6 +89,21 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: return subparsers +def new_wallet(args: Any): + mnemonic = generate_mnemonic() + print(f"Mnemonic: {mnemonic}") + seed, pubkey = wallet.derive_keys(mnemonic, account_index=args.index) + base_path = Path(args.output_path) + if args.with_pem: + pem_file = base_path.with_suffix(".pem") + address = Address(pubkey) + pem.write(pem_file, seed, pubkey, name=address.bech32()) + if args.with_json: + json_file = base_path.with_suffix(".json") + password = getpass.getpass("Enter a new password:") + save_to_key_file(json_file, seed, pubkey, password) + + def generate_pem(args: Any): pem_file = args.pem mnemonic = args.mnemonic diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index a22779b0..c865b056 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -1,6 +1,8 @@ import hashlib import hmac +import secrets import struct +from importlib.resources import open_text import nacl.signing @@ -9,6 +11,8 @@ BIP32_SEED_MODIFIER = b'ed25519 seed' ELROND_DERIVATION_PATH = [44, 508, 0, 0] HARDENED_OFFSET = 0x80000000 +BIP39_WORD_COUNT = 2048 +BIP39_MNEMONIC_WORD_LENGTH = 24 def derive_keys(mnemonic, account_index=0): @@ -29,6 +33,17 @@ def mnemonic_to_bip39seed(mnemonic, passphrase=""): return stretched[:64] +# Word list from: +# https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt +def generate_mnemonic() -> str: + with open_text("erdpy.wallet", "words.txt") as words_file: + words = words_file.read().splitlines() + assert len(words) == BIP39_WORD_COUNT + mnemonic_words = [secrets.choice(words) for _ in range(BIP39_MNEMONIC_WORD_LENGTH)] + mnemonic = " ".join(mnemonic_words) + return mnemonic + + # References: # https://ethereum.stackexchange.com/a/72871/59887s # https://github.com/alepop/ed25519-hd-key/blob/master/src/index.ts#L22 diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index 235575d5..1e4af709 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -1,6 +1,10 @@ import base64 +import os from binascii import b2a_base64, hexlify, unhexlify -from json import load +from pathlib import Path +import erdpy.accounts as accounts +from json import load, dump +from uuid import uuid4 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, hmac @@ -65,6 +69,64 @@ def load_from_key_file(key_file_json, password): return address_bech32, seed +def save_to_key_file(json_path: Path, seed: str, pubkey: str, password: str) -> None: + address = accounts.Address(pubkey) + address_hex = address.hex() + + address_bech32 = address.bech32() + + pvt_key = seed + pubkey + + backend = default_backend() + + # derive the encryption key + + salt = os.urandom(32) + kdf = Scrypt(salt=salt, length=32, n=4096, r=8, p=1, backend=backend) + key = kdf.derive(bytes(password.encode())) + + # encrypt the private key with half of the encryption key + + iv = os.urandom(16) + encryption_key = key[0:16] + cipher = Cipher(algorithms.AES(encryption_key), modes.CTR(iv), backend=backend) + encryptor = cipher.encryptor() + ciphertext = encryptor.update(pvt_key) + encryptor.finalize() + + hmac_key = key[16:32] + h = hmac.HMAC(hmac_key, hashes.SHA256(), backend=default_backend()) + h.update(ciphertext) + mac = h.finalize() + + uid = str(uuid4()) + + json = { + 'version': 4, + 'id': uid, + 'address': address_hex, + 'bech32': address_bech32, + 'crypto': { + 'cipher': 'aes-128-ctr', + 'cipherparams': { + 'iv': hexlify(iv).decode() + }, + 'ciphertext': hexlify(ciphertext).decode(), + 'kdf': 'scrypt', + 'kdfparams': { + 'dklen': 32, + 'n': 4096, + 'p': 1, + 'r': 8, + 'salt': hexlify(salt).decode(), + }, + 'mac': hexlify(mac).decode(), + } + } + + with open(json_path, 'w') as json_file: + dump(json, json_file, indent=4) + + def get_password(pass_file): with open(pass_file) as pass_f: return pass_f.read().strip() diff --git a/erdpy/wallet/words.txt b/erdpy/wallet/words.txt new file mode 100644 index 00000000..942040ed --- /dev/null +++ b/erdpy/wallet/words.txt @@ -0,0 +1,2048 @@ +abandon +ability +able +about +above +absent +absorb +abstract +absurd +abuse +access +accident +account +accuse +achieve +acid +acoustic +acquire +across +act +action +actor +actress +actual +adapt +add +addict +address +adjust +admit +adult +advance +advice +aerobic +affair +afford +afraid +again +age +agent +agree +ahead +aim +air +airport +aisle +alarm +album +alcohol +alert +alien +all +alley +allow +almost +alone +alpha +already +also +alter +always +amateur +amazing +among +amount +amused +analyst +anchor +ancient +anger +angle +angry +animal +ankle +announce +annual +another +answer +antenna +antique +anxiety +any +apart +apology +appear +apple +approve +april +arch +arctic +area +arena +argue +arm +armed +armor +army +around +arrange +arrest +arrive +arrow +art +artefact +artist +artwork +ask +aspect +assault +asset +assist +assume +asthma +athlete +atom +attack +attend +attitude +attract +auction +audit +august +aunt +author +auto +autumn +average +avocado +avoid +awake +aware +away +awesome +awful +awkward +axis +baby +bachelor +bacon +badge +bag +balance +balcony +ball +bamboo +banana +banner +bar +barely +bargain +barrel +base +basic +basket +battle +beach +bean +beauty +because +become +beef +before +begin +behave +behind +believe +below +belt +bench +benefit +best +betray +better +between +beyond +bicycle +bid +bike +bind +biology +bird +birth +bitter +black +blade +blame +blanket +blast +bleak +bless +blind +blood +blossom +blouse +blue +blur +blush +board +boat +body +boil +bomb +bone +bonus +book +boost +border +boring +borrow +boss +bottom +bounce +box +boy +bracket +brain +brand +brass +brave +bread +breeze +brick +bridge +brief +bright +bring +brisk +broccoli +broken +bronze +broom +brother +brown +brush +bubble +buddy +budget +buffalo +build +bulb +bulk +bullet +bundle +bunker +burden +burger +burst +bus +business +busy +butter +buyer +buzz +cabbage +cabin +cable +cactus +cage +cake +call +calm +camera +camp +can +canal +cancel +candy +cannon +canoe +canvas +canyon +capable +capital +captain +car +carbon +card +cargo +carpet +carry +cart +case +cash +casino +castle +casual +cat +catalog +catch +category +cattle +caught +cause +caution +cave +ceiling +celery +cement +census +century +cereal +certain +chair +chalk +champion +change +chaos +chapter +charge +chase +chat +cheap +check +cheese +chef +cherry +chest +chicken +chief +child +chimney +choice +choose +chronic +chuckle +chunk +churn +cigar +cinnamon +circle +citizen +city +civil +claim +clap +clarify +claw +clay +clean +clerk +clever +click +client +cliff +climb +clinic +clip +clock +clog +close +cloth +cloud +clown +club +clump +cluster +clutch +coach +coast +coconut +code +coffee +coil +coin +collect +color +column +combine +come +comfort +comic +common +company +concert +conduct +confirm +congress +connect +consider +control +convince +cook +cool +copper +copy +coral +core +corn +correct +cost +cotton +couch +country +couple +course +cousin +cover +coyote +crack +cradle +craft +cram +crane +crash +crater +crawl +crazy +cream +credit +creek +crew +cricket +crime +crisp +critic +crop +cross +crouch +crowd +crucial +cruel +cruise +crumble +crunch +crush +cry +crystal +cube +culture +cup +cupboard +curious +current +curtain +curve +cushion +custom +cute +cycle +dad +damage +damp +dance +danger +daring +dash +daughter +dawn +day +deal +debate +debris +decade +december +decide +decline +decorate +decrease +deer +defense +define +defy +degree +delay +deliver +demand +demise +denial +dentist +deny +depart +depend +deposit +depth +deputy +derive +describe +desert +design +desk +despair +destroy +detail +detect +develop +device +devote +diagram +dial +diamond +diary +dice +diesel +diet +differ +digital +dignity +dilemma +dinner +dinosaur +direct +dirt +disagree +discover +disease +dish +dismiss +disorder +display +distance +divert +divide +divorce +dizzy +doctor +document +dog +doll +dolphin +domain +donate +donkey +donor +door +dose +double +dove +draft +dragon +drama +drastic +draw +dream +dress +drift +drill +drink +drip +drive +drop +drum +dry +duck +dumb +dune +during +dust +dutch +duty +dwarf +dynamic +eager +eagle +early +earn +earth +easily +east +easy +echo +ecology +economy +edge +edit +educate +effort +egg +eight +either +elbow +elder +electric +elegant +element +elephant +elevator +elite +else +embark +embody +embrace +emerge +emotion +employ +empower +empty +enable +enact +end +endless +endorse +enemy +energy +enforce +engage +engine +enhance +enjoy +enlist +enough +enrich +enroll +ensure +enter +entire +entry +envelope +episode +equal +equip +era +erase +erode +erosion +error +erupt +escape +essay +essence +estate +eternal +ethics +evidence +evil +evoke +evolve +exact +example +excess +exchange +excite +exclude +excuse +execute +exercise +exhaust +exhibit +exile +exist +exit +exotic +expand +expect +expire +explain +expose +express +extend +extra +eye +eyebrow +fabric +face +faculty +fade +faint +faith +fall +false +fame +family +famous +fan +fancy +fantasy +farm +fashion +fat +fatal +father +fatigue +fault +favorite +feature +february +federal +fee +feed +feel +female +fence +festival +fetch +fever +few +fiber +fiction +field +figure +file +film +filter +final +find +fine +finger +finish +fire +firm +first +fiscal +fish +fit +fitness +fix +flag +flame +flash +flat +flavor +flee +flight +flip +float +flock +floor +flower +fluid +flush +fly +foam +focus +fog +foil +fold +follow +food +foot +force +forest +forget +fork +fortune +forum +forward +fossil +foster +found +fox +fragile +frame +frequent +fresh +friend +fringe +frog +front +frost +frown +frozen +fruit +fuel +fun +funny +furnace +fury +future +gadget +gain +galaxy +gallery +game +gap +garage +garbage +garden +garlic +garment +gas +gasp +gate +gather +gauge +gaze +general +genius +genre +gentle +genuine +gesture +ghost +giant +gift +giggle +ginger +giraffe +girl +give +glad +glance +glare +glass +glide +glimpse +globe +gloom +glory +glove +glow +glue +goat +goddess +gold +good +goose +gorilla +gospel +gossip +govern +gown +grab +grace +grain +grant +grape +grass +gravity +great +green +grid +grief +grit +grocery +group +grow +grunt +guard +guess +guide +guilt +guitar +gun +gym +habit +hair +half +hammer +hamster +hand +happy +harbor +hard +harsh +harvest +hat +have +hawk +hazard +head +health +heart +heavy +hedgehog +height +hello +helmet +help +hen +hero +hidden +high +hill +hint +hip +hire +history +hobby +hockey +hold +hole +holiday +hollow +home +honey +hood +hope +horn +horror +horse +hospital +host +hotel +hour +hover +hub +huge +human +humble +humor +hundred +hungry +hunt +hurdle +hurry +hurt +husband +hybrid +ice +icon +idea +identify +idle +ignore +ill +illegal +illness +image +imitate +immense +immune +impact +impose +improve +impulse +inch +include +income +increase +index +indicate +indoor +industry +infant +inflict +inform +inhale +inherit +initial +inject +injury +inmate +inner +innocent +input +inquiry +insane +insect +inside +inspire +install +intact +interest +into +invest +invite +involve +iron +island +isolate +issue +item +ivory +jacket +jaguar +jar +jazz +jealous +jeans +jelly +jewel +job +join +joke +journey +joy +judge +juice +jump +jungle +junior +junk +just +kangaroo +keen +keep +ketchup +key +kick +kid +kidney +kind +kingdom +kiss +kit +kitchen +kite +kitten +kiwi +knee +knife +knock +know +lab +label +labor +ladder +lady +lake +lamp +language +laptop +large +later +latin +laugh +laundry +lava +law +lawn +lawsuit +layer +lazy +leader +leaf +learn +leave +lecture +left +leg +legal +legend +leisure +lemon +lend +length +lens +leopard +lesson +letter +level +liar +liberty +library +license +life +lift +light +like +limb +limit +link +lion +liquid +list +little +live +lizard +load +loan +lobster +local +lock +logic +lonely +long +loop +lottery +loud +lounge +love +loyal +lucky +luggage +lumber +lunar +lunch +luxury +lyrics +machine +mad +magic +magnet +maid +mail +main +major +make +mammal +man +manage +mandate +mango +mansion +manual +maple +marble +march +margin +marine +market +marriage +mask +mass +master +match +material +math +matrix +matter +maximum +maze +meadow +mean +measure +meat +mechanic +medal +media +melody +melt +member +memory +mention +menu +mercy +merge +merit +merry +mesh +message +metal +method +middle +midnight +milk +million +mimic +mind +minimum +minor +minute +miracle +mirror +misery +miss +mistake +mix +mixed +mixture +mobile +model +modify +mom +moment +monitor +monkey +monster +month +moon +moral +more +morning +mosquito +mother +motion +motor +mountain +mouse +move +movie +much +muffin +mule +multiply +muscle +museum +mushroom +music +must +mutual +myself +mystery +myth +naive +name +napkin +narrow +nasty +nation +nature +near +neck +need +negative +neglect +neither +nephew +nerve +nest +net +network +neutral +never +news +next +nice +night +noble +noise +nominee +noodle +normal +north +nose +notable +note +nothing +notice +novel +now +nuclear +number +nurse +nut +oak +obey +object +oblige +obscure +observe +obtain +obvious +occur +ocean +october +odor +off +offer +office +often +oil +okay +old +olive +olympic +omit +once +one +onion +online +only +open +opera +opinion +oppose +option +orange +orbit +orchard +order +ordinary +organ +orient +original +orphan +ostrich +other +outdoor +outer +output +outside +oval +oven +over +own +owner +oxygen +oyster +ozone +pact +paddle +page +pair +palace +palm +panda +panel +panic +panther +paper +parade +parent +park +parrot +party +pass +patch +path +patient +patrol +pattern +pause +pave +payment +peace +peanut +pear +peasant +pelican +pen +penalty +pencil +people +pepper +perfect +permit +person +pet +phone +photo +phrase +physical +piano +picnic +picture +piece +pig +pigeon +pill +pilot +pink +pioneer +pipe +pistol +pitch +pizza +place +planet +plastic +plate +play +please +pledge +pluck +plug +plunge +poem +poet +point +polar +pole +police +pond +pony +pool +popular +portion +position +possible +post +potato +pottery +poverty +powder +power +practice +praise +predict +prefer +prepare +present +pretty +prevent +price +pride +primary +print +priority +prison +private +prize +problem +process +produce +profit +program +project +promote +proof +property +prosper +protect +proud +provide +public +pudding +pull +pulp +pulse +pumpkin +punch +pupil +puppy +purchase +purity +purpose +purse +push +put +puzzle +pyramid +quality +quantum +quarter +question +quick +quit +quiz +quote +rabbit +raccoon +race +rack +radar +radio +rail +rain +raise +rally +ramp +ranch +random +range +rapid +rare +rate +rather +raven +raw +razor +ready +real +reason +rebel +rebuild +recall +receive +recipe +record +recycle +reduce +reflect +reform +refuse +region +regret +regular +reject +relax +release +relief +rely +remain +remember +remind +remove +render +renew +rent +reopen +repair +repeat +replace +report +require +rescue +resemble +resist +resource +response +result +retire +retreat +return +reunion +reveal +review +reward +rhythm +rib +ribbon +rice +rich +ride +ridge +rifle +right +rigid +ring +riot +ripple +risk +ritual +rival +river +road +roast +robot +robust +rocket +romance +roof +rookie +room +rose +rotate +rough +round +route +royal +rubber +rude +rug +rule +run +runway +rural +sad +saddle +sadness +safe +sail +salad +salmon +salon +salt +salute +same +sample +sand +satisfy +satoshi +sauce +sausage +save +say +scale +scan +scare +scatter +scene +scheme +school +science +scissors +scorpion +scout +scrap +screen +script +scrub +sea +search +season +seat +second +secret +section +security +seed +seek +segment +select +sell +seminar +senior +sense +sentence +series +service +session +settle +setup +seven +shadow +shaft +shallow +share +shed +shell +sheriff +shield +shift +shine +ship +shiver +shock +shoe +shoot +shop +short +shoulder +shove +shrimp +shrug +shuffle +shy +sibling +sick +side +siege +sight +sign +silent +silk +silly +silver +similar +simple +since +sing +siren +sister +situate +six +size +skate +sketch +ski +skill +skin +skirt +skull +slab +slam +sleep +slender +slice +slide +slight +slim +slogan +slot +slow +slush +small +smart +smile +smoke +smooth +snack +snake +snap +sniff +snow +soap +soccer +social +sock +soda +soft +solar +soldier +solid +solution +solve +someone +song +soon +sorry +sort +soul +sound +soup +source +south +space +spare +spatial +spawn +speak +special +speed +spell +spend +sphere +spice +spider +spike +spin +spirit +split +spoil +sponsor +spoon +sport +spot +spray +spread +spring +spy +square +squeeze +squirrel +stable +stadium +staff +stage +stairs +stamp +stand +start +state +stay +steak +steel +stem +step +stereo +stick +still +sting +stock +stomach +stone +stool +story +stove +strategy +street +strike +strong +struggle +student +stuff +stumble +style +subject +submit +subway +success +such +sudden +suffer +sugar +suggest +suit +summer +sun +sunny +sunset +super +supply +supreme +sure +surface +surge +surprise +surround +survey +suspect +sustain +swallow +swamp +swap +swarm +swear +sweet +swift +swim +swing +switch +sword +symbol +symptom +syrup +system +table +tackle +tag +tail +talent +talk +tank +tape +target +task +taste +tattoo +taxi +teach +team +tell +ten +tenant +tennis +tent +term +test +text +thank +that +theme +then +theory +there +they +thing +this +thought +three +thrive +throw +thumb +thunder +ticket +tide +tiger +tilt +timber +time +tiny +tip +tired +tissue +title +toast +tobacco +today +toddler +toe +together +toilet +token +tomato +tomorrow +tone +tongue +tonight +tool +tooth +top +topic +topple +torch +tornado +tortoise +toss +total +tourist +toward +tower +town +toy +track +trade +traffic +tragic +train +transfer +trap +trash +travel +tray +treat +tree +trend +trial +tribe +trick +trigger +trim +trip +trophy +trouble +truck +true +truly +trumpet +trust +truth +try +tube +tuition +tumble +tuna +tunnel +turkey +turn +turtle +twelve +twenty +twice +twin +twist +two +type +typical +ugly +umbrella +unable +unaware +uncle +uncover +under +undo +unfair +unfold +unhappy +uniform +unique +unit +universe +unknown +unlock +until +unusual +unveil +update +upgrade +uphold +upon +upper +upset +urban +urge +usage +use +used +useful +useless +usual +utility +vacant +vacuum +vague +valid +valley +valve +van +vanish +vapor +various +vast +vault +vehicle +velvet +vendor +venture +venue +verb +verify +version +very +vessel +veteran +viable +vibrant +vicious +victory +video +view +village +vintage +violin +virtual +virus +visa +visit +visual +vital +vivid +vocal +voice +void +volcano +volume +vote +voyage +wage +wagon +wait +walk +wall +walnut +want +warfare +warm +warrior +wash +wasp +waste +water +wave +way +wealth +weapon +wear +weasel +weather +web +wedding +weekend +weird +welcome +west +wet +whale +what +wheat +wheel +when +where +whip +whisper +wide +width +wife +wild +will +win +window +wine +wing +wink +winner +winter +wire +wisdom +wise +wish +witness +wolf +woman +wonder +wood +wool +word +work +world +worry +worth +wrap +wreck +wrestle +wrist +write +wrong +yard +year +yellow +you +young +youth +zebra +zero +zone +zoo From 2dd241b5f20bd3eeec0a3567d98cdc72a6d2d0d7 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Mon, 13 Sep 2021 16:19:12 +0300 Subject: [PATCH 02/32] Ensure path exists, add logs --- erdpy/cli_wallet.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index 8fa29a42..66d6f41e 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, List -from erdpy import cli_shared, wallet +from erdpy import cli_shared, wallet, utils from erdpy.accounts import Account, Address from erdpy.wallet import pem @@ -27,7 +27,7 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: "Create a new wallet" ) sub.add_argument("--output-path", - help="the output path and file name for the generated wallet files", type=str, default="wallet") + help="the output path and base file name for the generated wallet files (default: %(default)s)", type=str, default="./wallet") sub.add_argument("--with-json", help="whether to create a json key file", action="store_true", default=False) sub.add_argument("--with-pem", @@ -93,15 +93,22 @@ def new_wallet(args: Any): mnemonic = generate_mnemonic() print(f"Mnemonic: {mnemonic}") seed, pubkey = wallet.derive_keys(mnemonic, account_index=args.index) - base_path = Path(args.output_path) if args.with_pem: - pem_file = base_path.with_suffix(".pem") + pem_file = prepare_file(args.output_path, ".pem") address = Address(pubkey) pem.write(pem_file, seed, pubkey, name=address.bech32()) + logger.info(f"Pem wallet generated: {pem_file}") if args.with_json: - json_file = base_path.with_suffix(".json") + json_file = prepare_file(args.output_path, ".json") password = getpass.getpass("Enter a new password:") save_to_key_file(json_file, seed, pubkey, password) + logger.info(f"Json wallet generated: {json_file}") + + +def prepare_file(output_path: str, suffix: str) -> Path: + base_path = Path(output_path) + utils.ensure_folder(base_path.parent) + return base_path.with_suffix(suffix) def generate_pem(args: Any): From 9afc6d61bb91ac976971326a23713beab69ca62f Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Mon, 13 Sep 2021 16:19:13 +0300 Subject: [PATCH 03/32] Uniquify paths --- erdpy/cli_wallet.py | 3 ++- erdpy/utils.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index 66d6f41e..4def6d8e 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -108,7 +108,8 @@ def new_wallet(args: Any): def prepare_file(output_path: str, suffix: str) -> Path: base_path = Path(output_path) utils.ensure_folder(base_path.parent) - return base_path.with_suffix(suffix) + file_path = base_path.with_suffix(suffix) + return utils.uniquify(file_path) def generate_pem(args: Any): diff --git a/erdpy/utils.py b/erdpy/utils.py index e3092818..82b6a683 100644 --- a/erdpy/utils.py +++ b/erdpy/utils.py @@ -67,6 +67,16 @@ def ensure_folder(folder: Union[str, Path]): pathlib.Path(folder).mkdir(parents=True, exist_ok=True) +def uniquify(path: Path) -> Path: + '''Generates the next available non-already-existing filename, by adding a _1, _2, _3, etc. suffix before the extension if necessary''' + i = 1 + stem = path.stem + while path.exists(): + path = path.with_name(f"{stem}_{i}").with_suffix(path.suffix) + i += 1 + return path + + def read_lines(file: str): with open(file) as f: lines = f.readlines() From 3813c7a1df74ad4d6af9845ee1ae38fdd4f83588 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Mon, 13 Sep 2021 18:39:40 +0300 Subject: [PATCH 04/32] Move output path, remove index option --- erdpy/cli_wallet.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index 4def6d8e..a3a4ef40 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -26,14 +26,12 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: "new", "Create a new wallet" ) - sub.add_argument("--output-path", - help="the output path and base file name for the generated wallet files (default: %(default)s)", type=str, default="./wallet") sub.add_argument("--with-json", help="whether to create a json key file", action="store_true", default=False) sub.add_argument("--with-pem", - help="whether to create a json key file", action="store_true", default=False) - sub.add_argument("--index", - help="the account index", type=int, default=0) + help="whether to create a pem key file", action="store_true", default=False) + sub.add_argument("--output-path", + help="the output path and base file name for the generated wallet files (default: %(default)s)", type=str, default="./wallet") sub.set_defaults(func=new_wallet) sub = cli_shared.add_command_subparser( @@ -92,7 +90,7 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: def new_wallet(args: Any): mnemonic = generate_mnemonic() print(f"Mnemonic: {mnemonic}") - seed, pubkey = wallet.derive_keys(mnemonic, account_index=args.index) + seed, pubkey = wallet.derive_keys(mnemonic) if args.with_pem: pem_file = prepare_file(args.output_path, ".pem") address = Address(pubkey) From 3417e35abe61487dc407357069e07aa9c73d7547 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Tue, 14 Sep 2021 18:16:09 +0300 Subject: [PATCH 05/32] update bip39 mnemonic generation to use checksum --- erdpy/wallet/core.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index c865b056..db53dca3 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -3,6 +3,7 @@ import secrets import struct from importlib.resources import open_text +from typing import List import nacl.signing @@ -11,7 +12,13 @@ BIP32_SEED_MODIFIER = b'ed25519 seed' ELROND_DERIVATION_PATH = [44, 508, 0, 0] HARDENED_OFFSET = 0x80000000 +BITS_PER_BYTE = 8 BIP39_WORD_COUNT = 2048 +BIP39_ENTROPY_BITS = 256 +BIP39_ENTROPY_BYTES = BIP39_ENTROPY_BITS // 8 +BIP39_CHECKSUM_BITS = BIP39_ENTROPY_BITS // 32 +BIP39_TOTAL_INDICES_BITS = BIP39_ENTROPY_BITS + BIP39_CHECKSUM_BITS +BIP39_WORD_BITS = 11 BIP39_MNEMONIC_WORD_LENGTH = 24 @@ -33,13 +40,39 @@ def mnemonic_to_bip39seed(mnemonic, passphrase=""): return stretched[:64] +def bytes_to_binary_string(bytes: bytes, number_of_bits: int = None) -> str: + if number_of_bits is None: + number_of_bits = len(bytes) * BITS_PER_BYTE + bytes_int = int.from_bytes(bytes, "big") + return f"{bytes_int:0{number_of_bits}b}" + + +def split_to_fixed_size_slices(bits: str, chunk_size: int) -> List[str]: + return [bits[i:i + chunk_size] for i in range(0, len(bits), chunk_size)] + + # Word list from: # https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt def generate_mnemonic() -> str: with open_text("erdpy.wallet", "words.txt") as words_file: words = words_file.read().splitlines() assert len(words) == BIP39_WORD_COUNT - mnemonic_words = [secrets.choice(words) for _ in range(BIP39_MNEMONIC_WORD_LENGTH)] + + entropy_bytes = secrets.token_bytes(BIP39_ENTROPY_BYTES) + + checksum_bytes = hashlib.sha256(entropy_bytes).digest() + checksum_bits = bytes_to_binary_string(checksum_bytes) + + entropy_str_binary = bytes_to_binary_string(entropy_bytes, BIP39_ENTROPY_BITS) + indices_bits = entropy_str_binary + checksum_bits[:BIP39_CHECKSUM_BITS] + assert len(indices_bits) == BIP39_TOTAL_INDICES_BITS + assert BIP39_MNEMONIC_WORD_LENGTH * BIP39_WORD_BITS == BIP39_TOTAL_INDICES_BITS + + indices_bits = split_to_fixed_size_slices(indices_bits, BIP39_WORD_BITS) + indices_ints = [int(index_bits, base=2) for index_bits in indices_bits] + assert len(indices_ints) == BIP39_MNEMONIC_WORD_LENGTH + + mnemonic_words = [words[word_index] for word_index in indices_ints] mnemonic = " ".join(mnemonic_words) return mnemonic From a33a283197baa70335cc5819a3cc2b20b3ea7003 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Tue, 14 Sep 2021 18:17:35 +0300 Subject: [PATCH 06/32] unalias variable --- erdpy/wallet/core.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index db53dca3..0552449c 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -64,11 +64,11 @@ def generate_mnemonic() -> str: checksum_bits = bytes_to_binary_string(checksum_bytes) entropy_str_binary = bytes_to_binary_string(entropy_bytes, BIP39_ENTROPY_BITS) - indices_bits = entropy_str_binary + checksum_bits[:BIP39_CHECKSUM_BITS] - assert len(indices_bits) == BIP39_TOTAL_INDICES_BITS + bits_of_indices = entropy_str_binary + checksum_bits[:BIP39_CHECKSUM_BITS] + assert len(bits_of_indices) == BIP39_TOTAL_INDICES_BITS assert BIP39_MNEMONIC_WORD_LENGTH * BIP39_WORD_BITS == BIP39_TOTAL_INDICES_BITS - indices_bits = split_to_fixed_size_slices(indices_bits, BIP39_WORD_BITS) + indices_bits = split_to_fixed_size_slices(bits_of_indices, BIP39_WORD_BITS) indices_ints = [int(index_bits, base=2) for index_bits in indices_bits] assert len(indices_ints) == BIP39_MNEMONIC_WORD_LENGTH From 581db3391e17a962186bde38c5ec5d5e43eb8033 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Tue, 14 Sep 2021 18:23:13 +0300 Subject: [PATCH 07/32] Document bip39 algorithm source --- erdpy/wallet/core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 0552449c..26071423 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -53,6 +53,8 @@ def split_to_fixed_size_slices(bits: str, chunk_size: int) -> List[str]: # Word list from: # https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt +# BIP39 algorithm steps from: +# https://medium.com/coinmonks/mnemonic-generation-bip39-simply-explained-e9ac18db9477 def generate_mnemonic() -> str: with open_text("erdpy.wallet", "words.txt") as words_file: words = words_file.read().splitlines() From a3119a7dfff4c119027041129c96926f56cf690b Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 15:57:36 +0300 Subject: [PATCH 08/32] Update erdpy/wallet/core.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Camil Băncioiu --- erdpy/wallet/core.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 26071423..f94e8ca7 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -61,14 +61,14 @@ def generate_mnemonic() -> str: assert len(words) == BIP39_WORD_COUNT entropy_bytes = secrets.token_bytes(BIP39_ENTROPY_BYTES) - + entropy_bits = bytes_to_binary_string(entropy_bytes) + checksum_bytes = hashlib.sha256(entropy_bytes).digest() checksum_bits = bytes_to_binary_string(checksum_bytes) + init_checksum_bits = checksum_bits[:BIP39_CHECKSUM_BITS] - entropy_str_binary = bytes_to_binary_string(entropy_bytes, BIP39_ENTROPY_BITS) - bits_of_indices = entropy_str_binary + checksum_bits[:BIP39_CHECKSUM_BITS] - assert len(bits_of_indices) == BIP39_TOTAL_INDICES_BITS - assert BIP39_MNEMONIC_WORD_LENGTH * BIP39_WORD_BITS == BIP39_TOTAL_INDICES_BITS + entropy_with_checksum_bits = entropy_bits + init_checksum_bits + assert len(entropy_with_checksum_bits) == BIP39_TOTAL_INDICES_BITS indices_bits = split_to_fixed_size_slices(bits_of_indices, BIP39_WORD_BITS) indices_ints = [int(index_bits, base=2) for index_bits in indices_bits] From d10019ce9eec970d1e4e264e2b649cce10b98c72 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 15:57:43 +0300 Subject: [PATCH 09/32] Update erdpy/wallet/core.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Camil Băncioiu --- erdpy/wallet/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index f94e8ca7..ab7678cb 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -72,7 +72,7 @@ def generate_mnemonic() -> str: indices_bits = split_to_fixed_size_slices(bits_of_indices, BIP39_WORD_BITS) indices_ints = [int(index_bits, base=2) for index_bits in indices_bits] - assert len(indices_ints) == BIP39_MNEMONIC_WORD_LENGTH + assert len(indices_ints) == BIP39_MNEMONIC_WORD_COUNT mnemonic_words = [words[word_index] for word_index in indices_ints] mnemonic = " ".join(mnemonic_words) From bacc661bd9e0136f6ce2487d1b021a0d08161931 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 15:58:18 +0300 Subject: [PATCH 10/32] Update erdpy/wallet/core.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Camil Băncioiu --- erdpy/wallet/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index ab7678cb..514dd9d6 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -70,7 +70,7 @@ def generate_mnemonic() -> str: entropy_with_checksum_bits = entropy_bits + init_checksum_bits assert len(entropy_with_checksum_bits) == BIP39_TOTAL_INDICES_BITS - indices_bits = split_to_fixed_size_slices(bits_of_indices, BIP39_WORD_BITS) + indices_bits = split_to_fixed_size_slices(entropy_with_checksum_bits, BIP39_WORD_BITS) indices_ints = [int(index_bits, base=2) for index_bits in indices_bits] assert len(indices_ints) == BIP39_MNEMONIC_WORD_COUNT From 9daf7fbbb61ce7bfb751f080baa5615e7c8701c8 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 15:58:28 +0300 Subject: [PATCH 11/32] Update erdpy/wallet/core.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Camil Băncioiu --- erdpy/wallet/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 514dd9d6..247b683c 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -19,7 +19,7 @@ BIP39_CHECKSUM_BITS = BIP39_ENTROPY_BITS // 32 BIP39_TOTAL_INDICES_BITS = BIP39_ENTROPY_BITS + BIP39_CHECKSUM_BITS BIP39_WORD_BITS = 11 -BIP39_MNEMONIC_WORD_LENGTH = 24 +BIP39_MNEMONIC_WORD_COUNT = 24 def derive_keys(mnemonic, account_index=0): From e37defba3dcc4be74ed3e5fb8f0ac6dbb71cfb3b Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 16:00:44 +0300 Subject: [PATCH 12/32] change int to optional int --- erdpy/wallet/core.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 247b683c..6b62fe5d 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -3,7 +3,7 @@ import secrets import struct from importlib.resources import open_text -from typing import List +from typing import List, Optional import nacl.signing @@ -40,7 +40,7 @@ def mnemonic_to_bip39seed(mnemonic, passphrase=""): return stretched[:64] -def bytes_to_binary_string(bytes: bytes, number_of_bits: int = None) -> str: +def bytes_to_binary_string(bytes: bytes, number_of_bits: Optional[int] = None) -> str: if number_of_bits is None: number_of_bits = len(bytes) * BITS_PER_BYTE bytes_int = int.from_bytes(bytes, "big") @@ -62,7 +62,7 @@ def generate_mnemonic() -> str: entropy_bytes = secrets.token_bytes(BIP39_ENTROPY_BYTES) entropy_bits = bytes_to_binary_string(entropy_bytes) - + checksum_bytes = hashlib.sha256(entropy_bytes).digest() checksum_bits = bytes_to_binary_string(checksum_bytes) init_checksum_bits = checksum_bits[:BIP39_CHECKSUM_BITS] From da7b0ba9e6861be64907390cd1011122d567805e Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Fri, 17 Sep 2021 16:58:53 +0300 Subject: [PATCH 13/32] add tests --- erdpy/tests/test_wallet.py | 11 ++++++++++- erdpy/wallet/core.py | 5 ++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/erdpy/tests/test_wallet.py b/erdpy/tests/test_wallet.py index 643bfb09..d41ed4e8 100644 --- a/erdpy/tests/test_wallet.py +++ b/erdpy/tests/test_wallet.py @@ -12,6 +12,7 @@ from erdpy.transactions import Transaction from erdpy.wallet import (bip39seed_to_private_key, generate_pair, mnemonic_to_bip39seed, pem) +from erdpy.wallet.core import bytes_to_binary_string, split_to_fixed_size_slices logging.basicConfig(level=logging.INFO) @@ -124,7 +125,7 @@ def test_sign_transaction(self): transaction.chainID = "chainID" transaction.version = 1 transaction.sign(self.alice) - + self.assertEqual("83efd1bc35790ecc220b0ed6ddd1fcb44af6653dd74e37b3a49dcc1f002a1b98b6f79779192cca68bdfefd037bc81f4fa606628b751023122191f8c062362805", transaction.signature) def test_generate_pair_pem(self): @@ -170,3 +171,11 @@ def test_derive_private_key(self): self.assertEqual(mnemonic_seed, actual_mnemonic_seed.hex()) self.assertEqual(private_key, actual_private_key.hex()) self.assertEqual(public_key, actual_public_key.hex()) + + def test_bytes_to_binary_string(self): + self.assertEqual(bytes_to_binary_string(b"\xA7"), '10100111') + self.assertEqual(bytes_to_binary_string(b"\x0F"), '00001111') + self.assertEqual(bytes_to_binary_string(b"\x12\x34\x56\x78\x9a\xbc\xde\xff"), '0001001000110100010101100111100010011010101111001101111011111111') + + def test_split_to_fixed_size_slices(self): + self.assertEqual(split_to_fixed_size_slices('1234567890abcdef', 4), ['1234', '5678', '90ab', 'cdef']) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 6b62fe5d..85cc18c3 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -40,9 +40,8 @@ def mnemonic_to_bip39seed(mnemonic, passphrase=""): return stretched[:64] -def bytes_to_binary_string(bytes: bytes, number_of_bits: Optional[int] = None) -> str: - if number_of_bits is None: - number_of_bits = len(bytes) * BITS_PER_BYTE +def bytes_to_binary_string(bytes: bytes) -> str: + number_of_bits = len(bytes) * BITS_PER_BYTE bytes_int = int.from_bytes(bytes, "big") return f"{bytes_int:0{number_of_bits}b}" From 6c9ee0dfa66c561a079c45c6d1f5f59a1cb3afe0 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 11:41:08 +0300 Subject: [PATCH 14/32] rename: use `secret` instead of `private` or `seed` --- erdpy/CLI.md | 4 +- erdpy/accounts.py | 16 ++--- erdpy/cli_wallet.py | 14 ++--- erdpy/delegation/staking_provider.py | 4 +- erdpy/ide/static/app/models.js | 22 +++---- erdpy/ide/static/app/views.deployDialog.js | 10 ++-- erdpy/ide/static/app/views.runDialog.js | 14 ++--- erdpy/ide/views/_deployDialog.html | 9 +-- erdpy/ide/views/_runDialog.html | 6 +- erdpy/interfaces.py | 2 +- erdpy/tests/test_wallet.py | 68 +++++++++++----------- erdpy/validators/core.py | 4 +- erdpy/wallet/__init__.py | 4 +- erdpy/wallet/core.py | 10 ++-- erdpy/wallet/generator.py | 4 +- erdpy/wallet/keyfile.py | 18 +++--- erdpy/wallet/pem.py | 41 +++++++------ erdpy/wallet/signing.py | 8 +-- 18 files changed, 129 insertions(+), 129 deletions(-) diff --git a/erdpy/CLI.md b/erdpy/CLI.md index 44f2ba72..11210371 100644 --- a/erdpy/CLI.md +++ b/erdpy/CLI.md @@ -34,7 +34,7 @@ contract Build, deploy and interact with Smart Contracts tx Create and broadcast Transactions validator Stake, Unjail and other actions useful for Validators account Get Account data (nonce, balance) from the Network -wallet Derive private key from mnemonic, bech32 address helpers etc. +wallet Derive secret key from mnemonic, bech32 address helpers etc. network Get Network parameters, such as number of shards, chain identifier etc. cost Estimate cost of Transactions dispatcher Enqueue transactions, then bulk dispatch them @@ -701,7 +701,7 @@ optional arguments: $ erdpy wallet --help usage: erdpy wallet COMMAND [-h] ... -Derive private key from mnemonic, bech32 address helpers etc. +Derive secret key from mnemonic, bech32 address helpers etc. COMMANDS: {derive,bech32,pem-address,pem-address-hex} diff --git a/erdpy/accounts.py b/erdpy/accounts.py index 4131295b..da43c376 100644 --- a/erdpy/accounts.py +++ b/erdpy/accounts.py @@ -27,12 +27,12 @@ def generate_accounts(self, count): self.generate_account(i) def generate_account(self, name): - seed, pubkey = generate_pair() + secret_key, pubkey = generate_pair() address = Address(pubkey).bech32() pem_file = f"{name}_{address}.pem" pem_file = path.join(self.folder, pem_file) - pem.write(pem_file, seed, pubkey, name=f"{name}:{address}") + pem.write(pem_file, secret_key, pubkey, name=f"{name}:{address}") def get_all(self): accounts = [] @@ -59,13 +59,13 @@ def __init__(self, self.ledger = ledger if self.pem_file: - seed, pubkey = pem.parse(self.pem_file, self.pem_index) - self.private_key_seed = seed.hex() + secret_key, pubkey = pem.parse(self.pem_file, self.pem_index) + self.secret_key = secret_key.hex() self.address = Address(pubkey) elif key_file and pass_file: password = get_password(pass_file) - address_from_key_file, seed = load_from_key_file(key_file, password) - self.private_key_seed = seed.hex() + address_from_key_file, secret_key = load_from_key_file(key_file, password) + self.secret_key = secret_key.hex() self.address = Address(address_from_key_file) def sync_nonce(self, proxy: Any): @@ -73,10 +73,10 @@ def sync_nonce(self, proxy: Any): self.nonce = proxy.get_account_nonce(self.address) logger.info(f"Account.sync_nonce() done: {self.nonce}") - def get_seed(self) -> bytes: + def get_secret_key(self) -> bytes: if self.ledger: raise LedgerError("cannot get seed from a Ledger account") - return unhexlify(self.private_key_seed) + return unhexlify(self.secret_key) class Address(IAddress): diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index a3a4ef40..8f741961 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -16,7 +16,7 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: parser = cli_shared.add_group_subparser( subparsers, "wallet", - "Derive private key from mnemonic, bech32 address helpers etc." + "Derive secret key from mnemonic, bech32 address helpers etc." ) subparsers = parser.add_subparsers() @@ -90,16 +90,16 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: def new_wallet(args: Any): mnemonic = generate_mnemonic() print(f"Mnemonic: {mnemonic}") - seed, pubkey = wallet.derive_keys(mnemonic) + secret_key, pubkey = wallet.derive_keys(mnemonic) if args.with_pem: pem_file = prepare_file(args.output_path, ".pem") address = Address(pubkey) - pem.write(pem_file, seed, pubkey, name=address.bech32()) + pem.write(pem_file, secret_key, pubkey, name=address.bech32()) logger.info(f"Pem wallet generated: {pem_file}") if args.with_json: json_file = prepare_file(args.output_path, ".json") password = getpass.getpass("Enter a new password:") - save_to_key_file(json_file, seed, pubkey, password) + save_to_key_file(json_file, secret_key, pubkey, password) logger.info(f"Json wallet generated: {json_file}") @@ -115,14 +115,14 @@ def generate_pem(args: Any): mnemonic = args.mnemonic index = args.index - seed, pubkey = wallet.generate_pair() + secret_key, pubkey = wallet.generate_pair() if mnemonic: mnemonic = input("Enter mnemonic:\n") mnemonic = mnemonic.strip() - seed, pubkey = wallet.derive_keys(mnemonic, index) + secret_key, pubkey = wallet.derive_keys(mnemonic, index) address = Address(pubkey) - pem.write(pem_file, seed, pubkey, name=address.bech32()) + pem.write(pem_file, secret_key, pubkey, name=address.bech32()) logger.info(f"Created PEM file [{pem_file}] for [{address.bech32()}]") diff --git a/erdpy/delegation/staking_provider.py b/erdpy/delegation/staking_provider.py index 7edda223..9670a6a3 100644 --- a/erdpy/delegation/staking_provider.py +++ b/erdpy/delegation/staking_provider.py @@ -42,8 +42,8 @@ def prepare_args_for_add_nodes(args: Any): # get validator validator_pem = validator.get("pemFile") validator_pem = path.join(path.dirname(args.validators_file), validator_pem) - seed, bls_key = parse_validator_pem(validator_pem) - signed_message = sign_message_with_bls_key(account.address.pubkey().hex(), seed.decode('ascii')) + secret_key_bytes, bls_key = parse_validator_pem(validator_pem) + signed_message = sign_message_with_bls_key(account.address.pubkey().hex(), secret_key_bytes.decode('ascii')) add_nodes_data += f"@{bls_key}@{signed_message}" args.receiver = args.delegation_contract diff --git a/erdpy/ide/static/app/models.js b/erdpy/ide/static/app/models.js index 53712378..d6bca2e5 100644 --- a/erdpy/ide/static/app/models.js +++ b/erdpy/ide/static/app/models.js @@ -3,7 +3,7 @@ var SmartContract = Backbone.Model.extend({ initialize: function () { }, - + deploy: function (options) { var payload = options.toJSON(); payload.id = this.id; @@ -22,7 +22,7 @@ var SmartContract = Backbone.Model.extend({ app.talkToHead("queryWatchedVariables", payload); }, - addWatchedVariable: function(options) { + addWatchedVariable: function (options) { this.getWatchedVariables(options.onTestnet).push({ Name: "alice's balance", FunctionName: "do_balance", @@ -32,7 +32,7 @@ var SmartContract = Backbone.Model.extend({ this.setWatchedVariables(options); }, - updateWatchedVariable: function(options) { + updateWatchedVariable: function (options) { var index = options.index; var variable = this.getWatchedVariables(options.onTestnet)[index]; variable.Name = options.name; @@ -42,20 +42,20 @@ var SmartContract = Backbone.Model.extend({ this.setWatchedVariables(options); }, - deleteWatchedVariable: function(options) { + deleteWatchedVariable: function (options) { var variables = this.getWatchedVariables(options.onTestnet); variables.splice(options.index, 1); this.setWatchedVariables(options); }, - getWatchedVariables: function(onTestnet) { + getWatchedVariables: function (onTestnet) { var properties = onTestnet ? this.get("PropertiesOnTestnet") : this.get("PropertiesOnNodeDebug"); var variables = properties.WatchedVariables; return variables; }, - setWatchedVariables: function(options) { + setWatchedVariables: function (options) { var payload = options; payload.id = this.id; payload.variables = this.getWatchedVariables(options.onTestnet); @@ -68,8 +68,8 @@ var SmartContract = Backbone.Model.extend({ var SmartContractDeployOptions = Backbone.Model.extend({ validate: function (attrs, options) { if (attrs.onTestnet) { - if (!attrs.privateKey) { - return "When deploying on testnet, the private key is required."; + if (!attrs.secretKey) { + return "When deploying on testnet, the secret key is required."; } } else { @@ -87,8 +87,8 @@ var SmartContractRunOptions = Backbone.Model.extend({ } if (attrs.onTestnet) { - if (!attrs.privateKey) { - return "When running on testnet, the private key is required."; + if (!attrs.secretKey) { + return "When running on testnet, the secret key is required."; } } else { @@ -101,4 +101,4 @@ var SmartContractRunOptions = Backbone.Model.extend({ var SmartContractsCollection = Backbone.Collection.extend({ model: SmartContract -}); \ No newline at end of file +}); diff --git a/erdpy/ide/static/app/views.deployDialog.js b/erdpy/ide/static/app/views.deployDialog.js index 59222bf4..4b005f09 100644 --- a/erdpy/ide/static/app/views.deployDialog.js +++ b/erdpy/ide/static/app/views.deployDialog.js @@ -6,7 +6,7 @@ var DeployDialog = Backbone.View.extend({ "shown.bs.modal": "onBootstrapModalShown", "hidden.bs.modal": "onBootstrapModalHidden", "click .btn-submit": "onClickSubmit", - "change input[name='PrivateKeyFile']": "onChangePrivateKey" + "change input[name='SecretKeyFile']": "onChangeSecretKey" }, initialize: function (options) { @@ -49,13 +49,13 @@ var DeployDialog = Backbone.View.extend({ this.remove(); }, - onChangePrivateKey: function (event) { + onChangeSecretKey: function (event) { var self = this; var file = event.currentTarget.files[0]; var reader = new FileReader(); reader.onload = function (onloadEvent) { - self.privateKey = onloadEvent.target.result; + self.secretKey = onloadEvent.target.result; }; reader.readAsText(file); @@ -69,7 +69,7 @@ var DeployDialog = Backbone.View.extend({ var gasPrice = this.getGasPrice(); var deployOptions = new SmartContractDeployOptions({ - privateKey: this.privateKey, + secretKey: this.secretKey, senderAddress: senderAddress, initArgs: initArgs, value: value, @@ -117,4 +117,4 @@ var DeployDialog = Backbone.View.extend({ getGasPrice: function () { return Number(this.$el.find("[name='GasPrice']").val()); } -}); \ No newline at end of file +}); diff --git a/erdpy/ide/static/app/views.runDialog.js b/erdpy/ide/static/app/views.runDialog.js index 8a3d4213..5dd3d17e 100644 --- a/erdpy/ide/static/app/views.runDialog.js +++ b/erdpy/ide/static/app/views.runDialog.js @@ -6,7 +6,7 @@ var RunDialog = Backbone.View.extend({ "shown.bs.modal": "onBootstrapModalShown", "hidden.bs.modal": "onBootstrapModalHidden", "click .btn-submit": "onClickSubmit", - "change input[name='PrivateKeyFile']": "onChangePrivateKey" + "change input[name='SecretKeyFile']": "onChangeSecretKey" }, initialize: function (options) { @@ -49,13 +49,13 @@ var RunDialog = Backbone.View.extend({ this.remove(); }, - onChangePrivateKey: function (event) { + onChangeSecretKey: function (event) { var self = this; var file = event.currentTarget.files[0]; var reader = new FileReader(); reader.onload = function (onloadEvent) { - self.privateKey = onloadEvent.target.result; + self.secretKey = onloadEvent.target.result; }; reader.readAsText(file); @@ -70,7 +70,7 @@ var RunDialog = Backbone.View.extend({ var gasPrice = this.getGasPrice(); var runOptions = new SmartContractRunOptions({ - privateKey: this.privateKey, + secretKey: this.secretKey, senderAddress: senderAddress, functionName: functionName, functionArgs: functionArgs, @@ -90,11 +90,11 @@ var RunDialog = Backbone.View.extend({ } }, - clearValidationErrors: function() { + clearValidationErrors: function () { this.$el.find(".validation-errors-container").addClass("d-none").empty(); }, - displayValidationErrors: function(validationError) { + displayValidationErrors: function (validationError) { this.$el.find(".validation-errors-container").removeClass("d-none").text(validationError); }, @@ -123,4 +123,4 @@ var RunDialog = Backbone.View.extend({ getGasPrice: function () { return Number(this.$el.find("[name='GasPrice']").val()); } -}); \ No newline at end of file +}); diff --git a/erdpy/ide/views/_deployDialog.html b/erdpy/ide/views/_deployDialog.html index a065eb37..c3053fb6 100644 --- a/erdpy/ide/views/_deployDialog.html +++ b/erdpy/ide/views/_deployDialog.html @@ -9,8 +9,8 @@
[[ if (onTestnet) { ]]
- - + +
[[ } else { ]]
@@ -53,7 +53,8 @@ [[ if (contract.PropertiesOnTestnet.Address) { ]]
- +
[[ } ]] [[ } else { ]] @@ -79,4 +80,4 @@
- \ No newline at end of file + diff --git a/erdpy/ide/views/_runDialog.html b/erdpy/ide/views/_runDialog.html index 3557e452..b25d62af 100644 --- a/erdpy/ide/views/_runDialog.html +++ b/erdpy/ide/views/_runDialog.html @@ -12,8 +12,8 @@ [[ var properties = onTestnet ? contract.PropertiesOnTestnet : contract.PropertiesOnNodeDebug; ]] [[ if (onTestnet) { ]]
- - + +
[[ } else { ]]
@@ -76,4 +76,4 @@
- \ No newline at end of file + diff --git a/erdpy/interfaces.py b/erdpy/interfaces.py index dfe32366..8091644a 100644 --- a/erdpy/interfaces.py +++ b/erdpy/interfaces.py @@ -14,7 +14,7 @@ def pubkey(self) -> bytes: class IAccount: - def get_seed(self) -> bytes: + def get_secret_key(self) -> bytes: return bytes() diff --git a/erdpy/tests/test_wallet.py b/erdpy/tests/test_wallet.py index d41ed4e8..41ad140c 100644 --- a/erdpy/tests/test_wallet.py +++ b/erdpy/tests/test_wallet.py @@ -10,7 +10,7 @@ from erdpy.accounts import Account, Address from erdpy.tests.utils import MyTestCase from erdpy.transactions import Transaction -from erdpy.wallet import (bip39seed_to_private_key, generate_pair, +from erdpy.wallet import (bip39seed_to_secret_key, generate_pair, mnemonic_to_bip39seed, pem) from erdpy.wallet.core import bytes_to_binary_string, split_to_fixed_size_slices @@ -24,10 +24,10 @@ def setUp(self): self.multiple_bls_keys_file = self.testdata / 'multipleValidatorsKeys.pem' def test_nacl_playground_signing(self): - private_key_hex = "b8211b08edc8aca591bedf1b9aba47e4077e54ac7d4ceb2f1bc9e10c064d3e6c7a5679a427f6df7adf2310ddf5e570fd51e47e6b1511124d6b250b989b017588" - private_key_bytes = bytes.fromhex(private_key_hex) - private_key_seed_bytes = private_key_bytes[:32] - signing_key: Any = nacl.signing.SigningKey(private_key_seed_bytes) + secret_key_hex = "b8211b08edc8aca591bedf1b9aba47e4077e54ac7d4ceb2f1bc9e10c064d3e6c7a5679a427f6df7adf2310ddf5e570fd51e47e6b1511124d6b250b989b017588" + secret_key_bytes = bytes.fromhex(secret_key_hex) + secret_key_seed_bytes = secret_key_bytes[:32] + signing_key = nacl.signing.SigningKey(secret_key_seed_bytes) signed = signing_key.sign(b"test") signature = signed.signature signed_bytes_hex = signature.hex() @@ -46,54 +46,54 @@ def test_pem_get_pubkey(self): def test_pem_parse_multiple(self): pem_file = self.testdata.joinpath("walletKey.pem") - seed, address = pem.parse(pem_file, index=0) - self.assertEqual("1f4dd8b7d18b5d0785c9d0802ec14d553dba356812b85c7e3414373388472010", seed.hex()) + secret_key, address = pem.parse(pem_file, index=0) + self.assertEqual("1f4dd8b7d18b5d0785c9d0802ec14d553dba356812b85c7e3414373388472010", secret_key.hex()) self.assertEqual(Address("erd1sjsk3n2d0krq3pyxxtgf0q7j3t56sgusqaujj4n82l39t9h7jers6gslr4").hex(), address.hex()) - seed, address = pem.parse(pem_file, index=1) - self.assertEqual("2565dbbdb62301e4c7b12b8a41cd3b2fbd7ae687c8d9741937aa48cf246aeb25", seed.hex()) + secret_key, address = pem.parse(pem_file, index=1) + self.assertEqual("2565dbbdb62301e4c7b12b8a41cd3b2fbd7ae687c8d9741937aa48cf246aeb25", secret_key.hex()) self.assertEqual(Address("erd10536tc3s886yqxtln74u6mztuwl5gy9k9gp8fttxda0klgxg979srtg5wt").hex(), address.hex()) - seed, address = pem.parse(pem_file, index=2) - self.assertEqual("08de69d398f4a5ffdce0f1a8569704dbc8b58aaf7ba3e726134e32f1e8bf04ad", seed.hex()) + secret_key, address = pem.parse(pem_file, index=2) + self.assertEqual("08de69d398f4a5ffdce0f1a8569704dbc8b58aaf7ba3e726134e32f1e8bf04ad", secret_key.hex()) self.assertEqual(Address("erd1n230jlgfepdvf28vqt3zeawexg2jhvxqxjuqdfsss0xc62xcqcps9k54ag").hex(), address.hex()) - seed, address = pem.parse(pem_file, index=3) - self.assertEqual("4d9dcc1c09a6d00c4c9a389e662d9fe26e0bf4c859776d4d338b5a9c41fc12d4", seed.hex()) + secret_key, address = pem.parse(pem_file, index=3) + self.assertEqual("4d9dcc1c09a6d00c4c9a389e662d9fe26e0bf4c859776d4d338b5a9c41fc12d4", secret_key.hex()) self.assertEqual(Address("erd143907zxv0ujxr9q4mda7rmczn2xwhmqn7p9lfz666z8hd2lcks2szt5yql").hex(), address.hex()) def test_pem_parse(self): pem_file = self.devnet_wallets.joinpath("users", "alice.pem") - seed, address = pem.parse(pem_file) + secret_key, address = pem.parse(pem_file) - self.assertEqual("413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9", seed.hex()) + self.assertEqual("413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9", secret_key.hex()) self.assertEqual("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", address.hex()) def test_parse_validator_pem_default_index(self): pem_file = self.multiple_bls_keys_file - seed, bls_key = pem.parse_validator_pem(pem_file) + secret_key_bytes, bls_key = pem.parse_validator_pem(pem_file) - key_hex = bytes.hex(seed) + secret_key_hex = bytes.hex(secret_key_bytes) self.assertEqual( "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d", bls_key) self.assertEqual( "37633139626633613063353763646431666230386534363037636562616133363437643662393236316234363933663631653936653534623231386434343261", - key_hex) + secret_key_hex) def test_parse_validator_pem_n_index(self): pem_file = self.multiple_bls_keys_file - seed, bls_key = pem.parse_validator_pem(pem_file, 3) + secret_key_bytes, bls_key = pem.parse_validator_pem(pem_file, 3) - key_hex = bytes.hex(seed) + secret_key_hex = bytes.hex(secret_key_bytes) self.assertEqual( "12773304cb718250edd89770cedcbf675ccdb7fe2b30bd3185ca65ffa0d516879768ed03f92e41a6e5bc5340b78a9d02655e3b727c79730ead791fb68eaa02b84e1be92a816a9604a1ab9a6d3874b638487e2145239438a4bafac3889348d405", bls_key) self.assertEqual( "38656265623037643239366164323532393430306234303638376137343161313335663833353766373966333966636232383934613666393730336135383136", - key_hex) + secret_key_hex) def test_sign_transaction(self): # With data @@ -129,47 +129,47 @@ def test_sign_transaction(self): self.assertEqual("83efd1bc35790ecc220b0ed6ddd1fcb44af6653dd74e37b3a49dcc1f002a1b98b6f79779192cca68bdfefd037bc81f4fa606628b751023122191f8c062362805", transaction.signature) def test_generate_pair_pem(self): - seed, pubkey = generate_pair() + secret_key, pubkey = generate_pair() pem_file = Path(self.testdata_out, "foo.pem") - pem.write(pem_file, seed, pubkey) - parsed_seed, parsed_pubkey = pem.parse(pem_file) + pem.write(pem_file, secret_key, pubkey) + parsed_secret_key, parsed_pubkey = pem.parse(pem_file) - self.assertEqual(seed, parsed_seed) + self.assertEqual(secret_key, parsed_secret_key) self.assertEqual(pubkey, parsed_pubkey) - def test_derive_private_key(self): + def test_derive_secret_key(self): # password = "Password1!" # keystore_file = "erd1zzhmdm2uwv9l7d2ak72c4cv6gek5c797s7qdkfc3jthvrvnxc2jqdsnp9y.json" mnemonic = "emotion spare multiply lecture rude machine raise radio ability doll depend equip pass ghost cabin delay birth opera shoe force any slow fluid old" mnemonic_seed = "2c3afb9202816c0ad8cfffbfe60b086c3b0600e7e96eddb589ca6bfcb2826a073c823b1c73200f152bd768c47754d7bc1daa82f860024c9916f2eab04ac50da9" - private_key = "4d6fbfd1fa028afee050068f08c46b95754fd27a06f429b308ba326fff094349" + secret_key = "4d6fbfd1fa028afee050068f08c46b95754fd27a06f429b308ba326fff094349" public_key = "10afb6ed5c730bff355db7958ae19a466d4c78be8780db271192eec1b266c2a4" # address = "erd1zzhmdm2uwv9l7d2ak72c4cv6gek5c797s7qdkfc3jthvrvnxc2jqdsnp9y" actual_mnemonic_seed = mnemonic_to_bip39seed(mnemonic) - actual_private_key = bip39seed_to_private_key(actual_mnemonic_seed) - signing_key = nacl.signing.SigningKey(actual_private_key) + actual_secret_key = bip39seed_to_secret_key(actual_mnemonic_seed) + signing_key = nacl.signing.SigningKey(actual_secret_key) actual_public_key = bytes(signing_key.verify_key) self.assertEqual(mnemonic_seed, actual_mnemonic_seed.hex()) - self.assertEqual(private_key, actual_private_key.hex()) + self.assertEqual(secret_key, actual_secret_key.hex()) self.assertEqual(public_key, actual_public_key.hex()) # password = "Password1!" # keystore_file = "erd1l4qsjlxuq33dld8ujmqlq3qs45f5qlspy2gvwwamshv2jmfg4g3q77yr0p.json" mnemonic = "real reveal sausage puppy artefact chapter original enough cinnamon run pledge awake fall double antenna admit keep melody celery since hood hurry achieve fee" mnemonic_seed = "9a8a5cfe7e4e7cfea54431aa80b9179985bfbf0af29ce75aff9bc4f5766ec2f5fb308486bb702e7465467a94792d16fd66f9307a95c1912526d08b21b6cc41b8" - private_key = "33306aa0bf13a02057ece15e07dc8e9cfff2b77147d5a007d205d782fc90e362" + secret_key = "33306aa0bf13a02057ece15e07dc8e9cfff2b77147d5a007d205d782fc90e362" public_key = "fd41097cdc0462dfb4fc96c1f04410ad13407e012290c73bbb85d8a96d28aa22" # address = "erd1l4qsjlxuq33dld8ujmqlq3qs45f5qlspy2gvwwamshv2jmfg4g3q77yr0p" actual_mnemonic_seed = mnemonic_to_bip39seed(mnemonic) - actual_private_key = bip39seed_to_private_key(actual_mnemonic_seed) - signing_key: Any = nacl.signing.SigningKey(actual_private_key) + actual_secret_key = bip39seed_to_secret_key(actual_mnemonic_seed) + signing_key: Any = nacl.signing.SigningKey(actual_secret_key) actual_public_key = bytes(signing_key.verify_key) self.assertEqual(mnemonic_seed, actual_mnemonic_seed.hex()) - self.assertEqual(private_key, actual_private_key.hex()) + self.assertEqual(secret_key, actual_secret_key.hex()) self.assertEqual(public_key, actual_public_key.hex()) def test_bytes_to_binary_string(self): diff --git a/erdpy/validators/core.py b/erdpy/validators/core.py index 42095391..8e9ce178 100644 --- a/erdpy/validators/core.py +++ b/erdpy/validators/core.py @@ -37,8 +37,8 @@ def prepare_args_for_stake(args: Any): # get validator validator_pem = validator.get("pemFile") validator_pem = path.join(path.dirname(args.validators_file), validator_pem) - seed, bls_key = parse_validator_pem(validator_pem) - signed_message = sign_message_with_bls_key(account.address.pubkey().hex(), seed.decode('ascii')) + secret_key_bytes, bls_key = parse_validator_pem(validator_pem) + signed_message = sign_message_with_bls_key(account.address.pubkey().hex(), secret_key_bytes.decode('ascii')) stake_data += f"@{bls_key}@{signed_message}" if reward_address: diff --git a/erdpy/wallet/__init__.py b/erdpy/wallet/__init__.py index 6193038a..48967585 100644 --- a/erdpy/wallet/__init__.py +++ b/erdpy/wallet/__init__.py @@ -1,5 +1,5 @@ -from erdpy.wallet.core import derive_keys, mnemonic_to_bip39seed, bip39seed_to_private_key +from erdpy.wallet.core import derive_keys, mnemonic_to_bip39seed, bip39seed_to_secret_key from erdpy.wallet.generator import generate_pair -__all__ = ["derive_keys", "mnemonic_to_bip39seed", "generate_pair", "bip39seed_to_private_key"] +__all__ = ["derive_keys", "mnemonic_to_bip39seed", "generate_pair", "bip39seed_to_secret_key"] diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 85cc18c3..684bd0c3 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -23,10 +23,10 @@ def derive_keys(mnemonic, account_index=0): - seed = mnemonic_to_bip39seed(mnemonic) - private_key = bip39seed_to_private_key(seed, account_index) - public_key = bytes(nacl.signing.SigningKey(private_key).verify_key) - return private_key, public_key + bip39seed = mnemonic_to_bip39seed(mnemonic) + secret_key = bip39seed_to_secret_key(bip39seed, account_index) + public_key = bytes(nacl.signing.SigningKey(secret_key).verify_key) + return secret_key, public_key # References: @@ -88,7 +88,7 @@ def bip39seed_to_master_key(seed): # Reference: https://github.com/alepop/ed25519-hd-key -def bip39seed_to_private_key(seed, account_index=0): +def bip39seed_to_secret_key(seed, account_index=0): key, chain_code = bip39seed_to_master_key(seed) for segment in ELROND_DERIVATION_PATH + [account_index]: diff --git a/erdpy/wallet/generator.py b/erdpy/wallet/generator.py index aee93a70..1ca78db3 100644 --- a/erdpy/wallet/generator.py +++ b/erdpy/wallet/generator.py @@ -15,6 +15,6 @@ def generate_pairs(): def generate_pair(): signing_key = nacl.signing.SigningKey.generate() - seed_bytes = bytes(signing_key) + secret_key = bytes(signing_key) pubkey_bytes = bytes(signing_key.verify_key) - return seed_bytes, pubkey_bytes + return secret_key, pubkey_bytes diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index 1e4af709..6a6086fc 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -36,7 +36,7 @@ def load_from_key_file(key_file_json, password): kdf = Scrypt(salt=salt, length=dklen, n=n, r=r, p=p, backend=backend) key = kdf.derive(bytes(password.encode())) - # decrypt the private key with half of the decryption key + # decrypt the secret key with half of the decryption key cipher_name = keystore['crypto']['cipher'] if cipher_name != 'aes-128-ctr': raise errors.UnknownCipher(name=cipher_name) @@ -48,7 +48,7 @@ def load_from_key_file(key_file_json, password): cipher = Cipher(algorithms.AES(decryption_key), modes.CTR(iv), backend=backend) decryptor = cipher.decryptor() plaintext = decryptor.update(ciphertext) + decryptor.finalize() - pemified_private_key = b2a_base64(hexlify(plaintext)) + pemified_secret_key = b2a_base64(hexlify(plaintext)) hmac_key = key[16:32] h = hmac.HMAC(hmac_key, hashes.SHA256(), backend=backend) @@ -59,23 +59,23 @@ def load_from_key_file(key_file_json, password): raise errors.InvalidKeystoreFilePassword() address_bech32 = keystore['bech32'] - private_key = ''.join([pemified_private_key[i:i + 64].decode() for i in range(0, len(pemified_private_key), 64)]) + secret_key = ''.join([pemified_secret_key[i:i + 64].decode() for i in range(0, len(pemified_secret_key), 64)]) - key_hex = base64.b64decode(private_key).decode() + key_hex = base64.b64decode(secret_key).decode() key_bytes = bytes.fromhex(key_hex) - seed = key_bytes[:32] + secret_key = key_bytes[:32] - return address_bech32, seed + return address_bech32, secret_key -def save_to_key_file(json_path: Path, seed: str, pubkey: str, password: str) -> None: +def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: str) -> None: address = accounts.Address(pubkey) address_hex = address.hex() address_bech32 = address.bech32() - pvt_key = seed + pubkey + pvt_key = secret_key + pubkey backend = default_backend() @@ -85,7 +85,7 @@ def save_to_key_file(json_path: Path, seed: str, pubkey: str, password: str) -> kdf = Scrypt(salt=salt, length=32, n=4096, r=8, p=1, backend=backend) key = kdf.derive(bytes(password.encode())) - # encrypt the private key with half of the encryption key + # encrypt the secret key with half of the encryption key iv = os.urandom(16) encryption_key = key[0:16] diff --git a/erdpy/wallet/pem.py b/erdpy/wallet/pem.py index 449df248..31214cfc 100644 --- a/erdpy/wallet/pem.py +++ b/erdpy/wallet/pem.py @@ -26,9 +26,9 @@ def parse(pem_file: Union[str, Path], index: int = 0) -> Tuple[bytes, bytes]: key_hex = base64.b64decode(key_base64).decode() key_bytes = bytes.fromhex(key_hex) - seed = key_bytes[:32] + secret_key = key_bytes[:32] pubkey = key_bytes[32:] - return seed, pubkey + return secret_key, pubkey def parse_all(pem_file: Union[str, Path]) -> List[Tuple[bytes, bytes]]: @@ -45,10 +45,10 @@ def parse_all(pem_file: Union[str, Path]) -> List[Tuple[bytes, bytes]]: for key_base64 in keys: key_hex = base64.b64decode(key_base64).decode() key_bytes = bytes.fromhex(key_hex) - seed = key_bytes[:32] + secret_key = key_bytes[:32] pubkey = key_bytes[32:] - result.append((seed, pubkey)) + result.append((secret_key, pubkey)) return result @@ -59,14 +59,13 @@ def parse_validator_pem(pem_file, index: int = 0): lines = utils.read_lines(pem_file) bls_keys = read_bls_keys(lines) - private_keys = read_validators_private_keys(lines) + secret_keys = read_validators_secret_keys(lines) - private_key = private_keys[index] - key_bytes = get_bytes_from_private_key(private_key) + secret_key = secret_keys[index] + secret_key_bytes = get_bytes_from_secret_key(secret_key) bls_key = bls_keys[index] - seed = key_bytes - return seed, bls_key + return secret_key_bytes, bls_key def read_bls_keys(lines): @@ -85,26 +84,26 @@ def read_bls_keys(lines): return bls_keys -def read_validators_private_keys(lines): - private_keys = [] +def read_validators_secret_keys(lines): + secret_keys = [] - private_keys_lines = [list(key_lines) for is_next_key, key_lines in - itertools.groupby(lines, lambda line: "-----" in line) if not is_next_key] - for key_list in private_keys_lines: - private_keys.append(key_list[0] + key_list[1]) + secret_keys_lines = [list(key_lines) for is_next_key, key_lines in + itertools.groupby(lines, lambda line: "-----" in line) if not is_next_key] + for key_list in secret_keys_lines: + secret_keys.append(key_list[0] + key_list[1]) - return private_keys + return secret_keys -def get_bytes_from_private_key(private_key): - key_base64 = private_key +def get_bytes_from_secret_key(secret_key): + key_base64 = secret_key key_hex = base64.b64decode(key_base64).hex() key_bytes = bytes.fromhex(key_hex) return key_bytes -def write(pem_file: Union[str, Path], seed: bytes, pubkey: bytes, name: str = ""): +def write(pem_file: Union[str, Path], secret_key: bytes, pubkey: bytes, name: str = ""): pem_file = path.expanduser(pem_file) if not name: @@ -113,9 +112,9 @@ def write(pem_file: Union[str, Path], seed: bytes, pubkey: bytes, name: str = "" header = f"-----BEGIN PRIVATE KEY for {name}-----" footer = f"-----END PRIVATE KEY for {name}-----" - seed_hex = seed.hex() + secret_key_hex = secret_key.hex() pubkey_hex = pubkey.hex() - combined = seed_hex + pubkey_hex + combined = secret_key_hex + pubkey_hex combined_bytes = combined.encode() key_base64 = base64.b64encode(combined_bytes).decode() diff --git a/erdpy/wallet/signing.py b/erdpy/wallet/signing.py index 7f34721b..cbc48668 100644 --- a/erdpy/wallet/signing.py +++ b/erdpy/wallet/signing.py @@ -12,8 +12,8 @@ def sign_transaction(transaction: ITransaction, account: IAccount) -> str: - seed: bytes = account.get_seed() - signing_key: Any = nacl.signing.SigningKey(seed) + secret_key: bytes = account.get_secret_key() + signing_key: Any = nacl.signing.SigningKey(secret_key) data_json = transaction.serialize() signed = signing_key.sign(data_json) @@ -36,8 +36,8 @@ def sign_message_with_bls_key(message, seed): def sign_message(message: bytes, account: IAccount) -> str: - seed: bytes = account.get_seed() - signing_key: Any = nacl.signing.SigningKey(seed) + secret_key: bytes = account.get_secret_key() + signing_key: Any = nacl.signing.SigningKey(secret_key) signed = signing_key.sign(message) signature = signed.signature From 39d60ccd685998eeed6f9c5bbdaa5409b9fbdfd3 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 11:47:45 +0300 Subject: [PATCH 15/32] remove extra key concatenation --- erdpy/wallet/keyfile.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index 6a6086fc..0da7d79d 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -75,8 +75,6 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st address_bech32 = address.bech32() - pvt_key = secret_key + pubkey - backend = default_backend() # derive the encryption key @@ -91,7 +89,7 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st encryption_key = key[0:16] cipher = Cipher(algorithms.AES(encryption_key), modes.CTR(iv), backend=backend) encryptor = cipher.encryptor() - ciphertext = encryptor.update(pvt_key) + encryptor.finalize() + ciphertext = encryptor.update(secret_key) + encryptor.finalize() hmac_key = key[16:32] h = hmac.HMAC(hmac_key, hashes.SHA256(), backend=default_backend()) From d9b3b02f711d4dbd25859c24fe63842ee8a33179 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 15:58:59 +0300 Subject: [PATCH 16/32] add todo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Camil Băncioiu --- erdpy/wallet/pem.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erdpy/wallet/pem.py b/erdpy/wallet/pem.py index 31214cfc..7a3db41a 100644 --- a/erdpy/wallet/pem.py +++ b/erdpy/wallet/pem.py @@ -84,6 +84,7 @@ def read_bls_keys(lines): return bls_keys +# TODO rewrite using generators or simplify the list comprehension within def read_validators_secret_keys(lines): secret_keys = [] From d5915eb68a648d81aacef8f2c91938659ac0f767 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 16:05:44 +0300 Subject: [PATCH 17/32] split code in the `save_to_key_file` function --- erdpy/wallet/keyfile.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index 0da7d79d..d86de629 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -2,6 +2,7 @@ import os from binascii import b2a_base64, hexlify, unhexlify from pathlib import Path +from typing import Any import erdpy.accounts as accounts from json import load, dump from uuid import uuid4 @@ -98,7 +99,14 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st uid = str(uuid4()) - json = { + json = format_key_json(uid, address_hex, address_bech32, iv, ciphertext, salt, mac) + + with open(json_path, 'w') as json_file: + dump(json, json_file, indent=4) + + +def format_key_json(uid: str, address_hex: str, address_bech32: str, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: + return { 'version': 4, 'id': uid, 'address': address_hex, @@ -121,9 +129,6 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st } } - with open(json_path, 'w') as json_file: - dump(json, json_file, indent=4) - def get_password(pass_file): with open(pass_file) as pass_f: From 666c41fed4524233667b34fa55de7a3faa7c2824 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 16:08:49 +0300 Subject: [PATCH 18/32] refactor addres parameters --- erdpy/wallet/keyfile.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index d86de629..a4c95a89 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -72,9 +72,6 @@ def load_from_key_file(key_file_json, password): def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: str) -> None: address = accounts.Address(pubkey) - address_hex = address.hex() - - address_bech32 = address.bech32() backend = default_backend() @@ -99,18 +96,18 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st uid = str(uuid4()) - json = format_key_json(uid, address_hex, address_bech32, iv, ciphertext, salt, mac) + json = format_key_json(uid, address, iv, ciphertext, salt, mac) with open(json_path, 'w') as json_file: dump(json, json_file, indent=4) -def format_key_json(uid: str, address_hex: str, address_bech32: str, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: +def format_key_json(uid: str, address: accounts.Address, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: return { 'version': 4, 'id': uid, - 'address': address_hex, - 'bech32': address_bech32, + 'address': address.hex(), + 'bech32': address.bech32(), 'crypto': { 'cipher': 'aes-128-ctr', 'cipherparams': { From e13c2540bbf5aff903bd5a17a25b0056334a2c23 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Thu, 21 Oct 2021 16:23:37 +0300 Subject: [PATCH 19/32] fix compilation, refactor cyphertext generation --- erdpy/wallet/keyfile.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index a4c95a89..01567583 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -71,23 +71,16 @@ def load_from_key_file(key_file_json, password): def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: str) -> None: - address = accounts.Address(pubkey) - backend = default_backend() # derive the encryption key - salt = os.urandom(32) kdf = Scrypt(salt=salt, length=32, n=4096, r=8, p=1, backend=backend) key = kdf.derive(bytes(password.encode())) # encrypt the secret key with half of the encryption key - iv = os.urandom(16) - encryption_key = key[0:16] - cipher = Cipher(algorithms.AES(encryption_key), modes.CTR(iv), backend=backend) - encryptor = cipher.encryptor() - ciphertext = encryptor.update(secret_key) + encryptor.finalize() + ciphertext = make_cyphertext(backend, key, iv, secret_key) hmac_key = key[16:32] h = hmac.HMAC(hmac_key, hashes.SHA256(), backend=default_backend()) @@ -96,13 +89,22 @@ def save_to_key_file(json_path: Path, secret_key: str, pubkey: str, password: st uid = str(uuid4()) - json = format_key_json(uid, address, iv, ciphertext, salt, mac) + json = format_key_json(uid, pubkey, iv, ciphertext, salt, mac) with open(json_path, 'w') as json_file: dump(json, json_file, indent=4) -def format_key_json(uid: str, address: accounts.Address, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: +def make_cyphertext(backend: Any, key: bytes, iv: bytes, secret_key: str): + encryption_key = key[0:16] + cipher = Cipher(algorithms.AES(encryption_key), modes.CTR(iv), backend=backend) + encryptor = cipher.encryptor() + return encryptor.update(secret_key) + encryptor.finalize() + + +def format_key_json(uid: str, pubkey: str, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: + address = accounts.Address(pubkey) + return { 'version': 4, 'id': uid, From a2dd134cfe8ca7c0b0fcbb3528e71bf68869e482 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Tue, 26 Oct 2021 16:29:34 +0300 Subject: [PATCH 20/32] rename words.txt to bip39words.txt --- erdpy/wallet/{words.txt => bip39words.txt} | 0 erdpy/wallet/core.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename erdpy/wallet/{words.txt => bip39words.txt} (100%) diff --git a/erdpy/wallet/words.txt b/erdpy/wallet/bip39words.txt similarity index 100% rename from erdpy/wallet/words.txt rename to erdpy/wallet/bip39words.txt diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 684bd0c3..5bed6c68 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -55,7 +55,7 @@ def split_to_fixed_size_slices(bits: str, chunk_size: int) -> List[str]: # BIP39 algorithm steps from: # https://medium.com/coinmonks/mnemonic-generation-bip39-simply-explained-e9ac18db9477 def generate_mnemonic() -> str: - with open_text("erdpy.wallet", "words.txt") as words_file: + with open_text("erdpy.wallet", "bip39words.txt") as words_file: words = words_file.read().splitlines() assert len(words) == BIP39_WORD_COUNT From dadcbae4cc146432bfc3c567346e22f961551dcd Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Tue, 26 Oct 2021 16:56:15 +0300 Subject: [PATCH 21/32] add generate_mnemonic tests --- erdpy/tests/test_wallet.py | 16 +++++++++++++++- erdpy/wallet/core.py | 12 ++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/erdpy/tests/test_wallet.py b/erdpy/tests/test_wallet.py index 41ad140c..e2bc1a3a 100644 --- a/erdpy/tests/test_wallet.py +++ b/erdpy/tests/test_wallet.py @@ -12,7 +12,7 @@ from erdpy.transactions import Transaction from erdpy.wallet import (bip39seed_to_secret_key, generate_pair, mnemonic_to_bip39seed, pem) -from erdpy.wallet.core import bytes_to_binary_string, split_to_fixed_size_slices +from erdpy.wallet.core import bytes_to_binary_string, generate_mnemonic_from_entropy, split_to_fixed_size_slices logging.basicConfig(level=logging.INFO) @@ -179,3 +179,17 @@ def test_bytes_to_binary_string(self): def test_split_to_fixed_size_slices(self): self.assertEqual(split_to_fixed_size_slices('1234567890abcdef', 4), ['1234', '5678', '90ab', 'cdef']) + + def test_generate_mnemonic_from_entropy(self): + self.assertEqual( + generate_mnemonic_from_entropy(bytes.fromhex('e4708a379dd31b94aff5e64b17fb10d43956a5ae8764602d8e1f2e4ebc4b9296')), + 'tongue lounge mistake desert coyote ski save rubber enrich save service position nice fan ring uncle gasp hockey march frame type chair engage stove' + ) + self.assertEqual( + generate_mnemonic_from_entropy(bytes.fromhex('a2c450adc68a627bfe9a822361433dee844b344a8d8502ca602ff0f006b1feab')), + 'people card clock minimum plate digital whip expect casino anxiety sorry tackle dwarf olive clay radar actress fantasy armor tiger about flight wide ladder' + ) + self.assertEqual( + generate_mnemonic_from_entropy(bytes.fromhex('8b1897060e4b24bb7c07491159c6c234238be0412973af4e39effc57756cb490')), + 'mention seven screen broken rather frozen useless truck bacon soda rack hair december usual again common quantum impact know weather jar rent spoil angry' + ) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index 5bed6c68..dc0d9909 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -50,16 +50,24 @@ def split_to_fixed_size_slices(bits: str, chunk_size: int) -> List[str]: return [bits[i:i + chunk_size] for i in range(0, len(bits), chunk_size)] +def generate_mnemonic() -> str: + entropy_bytes = secrets.token_bytes(BIP39_ENTROPY_BYTES) + return generate_mnemonic_from_entropy(entropy_bytes) + + # Word list from: # https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt # BIP39 algorithm steps from: # https://medium.com/coinmonks/mnemonic-generation-bip39-simply-explained-e9ac18db9477 -def generate_mnemonic() -> str: +# Javascript implementations: +# https://github.com/ElrondNetwork/elrond-sdk-erdjs/blob/main/src/walletcore/mnemonic.ts +# https://github.com/bitcoinjs/bip39/blob/5faee2c17b2195f30b03cb125df68c20d7dd584b/src/index.js#L108 +def generate_mnemonic_from_entropy(entropy_bytes: bytes) -> str: with open_text("erdpy.wallet", "bip39words.txt") as words_file: words = words_file.read().splitlines() assert len(words) == BIP39_WORD_COUNT - entropy_bytes = secrets.token_bytes(BIP39_ENTROPY_BYTES) + assert len(entropy_bytes) == BIP39_ENTROPY_BYTES entropy_bits = bytes_to_binary_string(entropy_bytes) checksum_bytes = hashlib.sha256(entropy_bytes).digest() From 5f451ae6bbb9837b2869e74a386774b60048f5bc Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Wed, 27 Oct 2021 10:49:40 +0300 Subject: [PATCH 22/32] add link to erdjs implementation --- erdpy/wallet/keyfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erdpy/wallet/keyfile.py b/erdpy/wallet/keyfile.py index 01567583..493c3c6d 100644 --- a/erdpy/wallet/keyfile.py +++ b/erdpy/wallet/keyfile.py @@ -102,6 +102,8 @@ def make_cyphertext(backend: Any, key: bytes, iv: bytes, secret_key: str): return encryptor.update(secret_key) + encryptor.finalize() +# erdjs implementation: +# https://github.com/ElrondNetwork/elrond-sdk-erdjs/blob/main/src/walletcore/userWallet.ts def format_key_json(uid: str, pubkey: str, iv: bytes, ciphertext: bytes, salt: bytes, mac: bytes) -> Any: address = accounts.Address(pubkey) From 876ef7ca498b1dfb4bd6fa371a19aff623fd5f36 Mon Sep 17 00:00:00 2001 From: Claudiu-Marcel Bruda Date: Wed, 27 Oct 2021 10:51:54 +0300 Subject: [PATCH 23/32] shorten pem and json arguments --- erdpy/cli_wallet.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index 8f741961..924b8516 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -26,9 +26,9 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: "new", "Create a new wallet" ) - sub.add_argument("--with-json", + sub.add_argument("--json", help="whether to create a json key file", action="store_true", default=False) - sub.add_argument("--with-pem", + sub.add_argument("--pem", help="whether to create a pem key file", action="store_true", default=False) sub.add_argument("--output-path", help="the output path and base file name for the generated wallet files (default: %(default)s)", type=str, default="./wallet") @@ -91,12 +91,12 @@ def new_wallet(args: Any): mnemonic = generate_mnemonic() print(f"Mnemonic: {mnemonic}") secret_key, pubkey = wallet.derive_keys(mnemonic) - if args.with_pem: + if args.pem: pem_file = prepare_file(args.output_path, ".pem") address = Address(pubkey) pem.write(pem_file, secret_key, pubkey, name=address.bech32()) logger.info(f"Pem wallet generated: {pem_file}") - if args.with_json: + if args.json: json_file = prepare_file(args.output_path, ".json") password = getpass.getpass("Enter a new password:") save_to_key_file(json_file, secret_key, pubkey, password) From 4e82f29a8628f0cab3970590c1cc6e041892712c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Sat, 30 Oct 2021 18:18:48 +0300 Subject: [PATCH 24/32] Replace arwentools with vmtools where appropriate --- erdpy/CLI.md | 4 ++-- erdpy/config.py | 6 +++--- erdpy/constants.py | 4 ++-- erdpy/contracts.py | 2 +- erdpy/dependencies/install.py | 4 ++-- erdpy/dependencies/modules.py | 7 ++----- erdpy/projects/core.py | 2 +- erdpy/projects/project_base.py | 6 +++--- erdpy/scope.py | 2 +- erdpy/testnet/config.py | 6 +++--- erdpy/testnet/setup.py | 22 ++++++---------------- erdpy/tests/test_cli_deps.sh | 4 ++-- 12 files changed, 28 insertions(+), 41 deletions(-) diff --git a/erdpy/CLI.md b/erdpy/CLI.md index 11210371..61b2be6e 100644 --- a/erdpy/CLI.md +++ b/erdpy/CLI.md @@ -1185,7 +1185,7 @@ usage: erdpy deps install [-h] ... Install dependencies or elrond-sdk modules. positional arguments: - {llvm,clang,cpp,arwentools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} + {llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} the dependency to install optional arguments: @@ -1204,7 +1204,7 @@ usage: erdpy deps check [-h] ... Check whether a dependency is installed. positional arguments: - {llvm,clang,cpp,arwentools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} + {llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} the dependency to check optional arguments: diff --git a/erdpy/config.py b/erdpy/config.py index 02c8f878..101584c7 100644 --- a/erdpy/config.py +++ b/erdpy/config.py @@ -148,10 +148,10 @@ def get_defaults() -> Dict[str, Any]: "proxy": "https://testnet-gateway.elrond.com", "chainID": "T", "txVersion": "1", - "dependencies.arwentools.tag": "latest", + "dependencies.vmtools.tag": "latest", "dependencies.elrond_wasm_rs.tag": "latest", - "dependencies.arwentools.urlTemplate.linux": "https://github.com/ElrondNetwork/arwen-wasm-vm/archive/{TAG}.tar.gz", - "dependencies.arwentools.urlTemplate.osx": "https://github.com/ElrondNetwork/arwen-wasm-vm/archive/{TAG}.tar.gz", + "dependencies.vmtools.urlTemplate.linux": "https://github.com/ElrondNetwork/wasm-vm/archive/{TAG}.tar.gz", + "dependencies.vmtools.urlTemplate.osx": "https://github.com/ElrondNetwork/wasm-vm/archive/{TAG}.tar.gz", "dependencies.llvm.tag": "v9-19feb", "dependencies.llvm.urlTemplate.linux": "https://ide.elrond.com/vendor-llvm/{TAG}/linux-amd64.tar.gz?t=19feb", "dependencies.llvm.urlTemplate.osx": "https://ide.elrond.com/vendor-llvm/{TAG}/darwin-amd64.tar.gz?t=19feb", diff --git a/erdpy/constants.py b/erdpy/constants.py index a8825d59..599aa321 100644 --- a/erdpy/constants.py +++ b/erdpy/constants.py @@ -1,5 +1,5 @@ VM_TYPE_SYSTEM = "0001" -VM_TYPE_ARWEN = "0500" +VM_TYPE_WASM_VM = "0500" SC_HEX_PUBKEY_PREFIX = "0" * 16 SC_HEX_PUBKEY_PREFIX_SYSTEM = SC_HEX_PUBKEY_PREFIX + VM_TYPE_SYSTEM + "0" * 30 -SC_HEX_PUBKEY_PREFIX_ARWEN = SC_HEX_PUBKEY_PREFIX + VM_TYPE_ARWEN +SC_HEX_PUBKEY_PREFIX_WASM_VM = SC_HEX_PUBKEY_PREFIX + VM_TYPE_WASM_VM diff --git a/erdpy/contracts.py b/erdpy/contracts.py index 90bed1d9..39d09d1e 100644 --- a/erdpy/contracts.py +++ b/erdpy/contracts.py @@ -52,7 +52,7 @@ def deploy(self, owner: Account, arguments: List[Any], gas_price: int, gas_limit return tx def prepare_deploy_transaction_data(self, arguments: List[Any]): - tx_data = f"{self.bytecode}@{constants.VM_TYPE_ARWEN}@{self.metadata.to_hex()}" + tx_data = f"{self.bytecode}@{constants.VM_TYPE_WASM_VM}@{self.metadata.to_hex()}" for arg in arguments: tx_data += f"@{_prepare_argument(arg)}" diff --git a/erdpy/dependencies/install.py b/erdpy/dependencies/install.py index aebe12e8..2f10a6ed 100644 --- a/erdpy/dependencies/install.py +++ b/erdpy/dependencies/install.py @@ -3,7 +3,7 @@ from typing import Dict, List from erdpy import config, errors -from erdpy.dependencies.modules import (ArwenToolsModule, DependencyModule, +from erdpy.dependencies.modules import (VMToolsModule, DependencyModule, GolangModule, MclSignerModule, NodejsModule, Rust, StandaloneModule) @@ -47,7 +47,7 @@ def get_deps_dict() -> Dict[str, DependencyModule]: def get_all_deps() -> List[DependencyModule]: return [ StandaloneModule(key="llvm", aliases=["clang", "cpp"]), - ArwenToolsModule(key="arwentools"), + VMToolsModule(key="vmtools"), Rust(key="rust"), NodejsModule(key="nodejs", aliases=[]), StandaloneModule(key="elrond_go", repo_name="elrond-go", organisation="ElrondNetwork"), diff --git a/erdpy/dependencies/modules.py b/erdpy/dependencies/modules.py index 7e0ff379..fa172f21 100644 --- a/erdpy/dependencies/modules.py +++ b/erdpy/dependencies/modules.py @@ -143,22 +143,19 @@ def _get_archive_path(self, tag: str) -> Path: return archive -class ArwenToolsModule(StandaloneModule): +class VMToolsModule(StandaloneModule): def __init__(self, key: str, aliases: List[str] = None): if aliases is None: aliases = list() super().__init__(key, aliases) - self.repo_name = 'arwen-wasm-vm' + self.repo_name = 'wasm-vm' self.organisation = 'ElrondNetwork' def _post_install(self, tag: str): dependencies.install_module('golang') - self.build_binary(tag, 'arwendebug') self.build_binary(tag, 'test') - - self.make_binary_symlink_in_parent_folder(tag, 'arwendebug', 'arwendebug') self.make_binary_symlink_in_parent_folder(tag, 'test', 'mandos-test') self.copy_libwasmer_in_parent_directory(tag) diff --git a/erdpy/projects/core.py b/erdpy/projects/core.py index 0c16dac5..8add3b2e 100644 --- a/erdpy/projects/core.py +++ b/erdpy/projects/core.py @@ -58,7 +58,7 @@ def run_tests(args: Any): logger.info("run_tests.project: %s", project) - dependencies.install_module("arwentools") + dependencies.install_module("vmtools") guards.is_directory(project) project = load_project(project) diff --git a/erdpy/projects/project_base.py b/erdpy/projects/project_base.py index 59e48732..a75df035 100644 --- a/erdpy/projects/project_base.py +++ b/erdpy/projects/project_base.py @@ -97,9 +97,9 @@ def default_config(self): return dict() def run_tests(self, tests_directory: str, wildcard: str = ""): - arwentools = cast(StandaloneModule, dependencies.get_module_by_key("arwentools")) - tool_env = arwentools.get_env() - tool = path.join(arwentools.get_parent_directory(), "mandos-test") + vmtools = cast(StandaloneModule, dependencies.get_module_by_key("vmtools")) + tool_env = vmtools.get_env() + tool = path.join(vmtools.get_parent_directory(), "mandos-test") test_folder = path.join(self.directory, tests_directory) if not wildcard: diff --git a/erdpy/scope.py b/erdpy/scope.py index 91f95342..096749ab 100644 --- a/erdpy/scope.py +++ b/erdpy/scope.py @@ -25,7 +25,7 @@ def initialize(): testnet_config = TestnetConfiguration.from_file(testnet_toml) proxy = f"http://localhost:{testnet_config.proxy_port()}" except FileNotFoundError: - logger.warn("components of the testnet may be missing") + pass def get_chain_id(): diff --git a/erdpy/testnet/config.py b/erdpy/testnet/config.py index 2242343f..07c2e0bd 100644 --- a/erdpy/testnet/config.py +++ b/erdpy/testnet/config.py @@ -296,8 +296,8 @@ def proxy_port(self): def loglevel(self) -> str: return self.features.get("loglevel", "") - def arwen_binary(self) -> bool: - return self.features.get("arwen_binary", False) + def wasm_vm_binary(self) -> bool: + return self.features.get("wasm_vm_binary", False) @classmethod def default(cls): @@ -305,7 +305,7 @@ def default(cls): config['features'] = { 'loglevel': '*:DEBUG', 'proxy': True, - 'arwen_binary': False + 'wasm_vm_binary': False } config['folders'] = { 'elrond_go': diff --git a/erdpy/testnet/setup.py b/erdpy/testnet/setup.py index 7f3d080e..d8c35fee 100644 --- a/erdpy/testnet/setup.py +++ b/erdpy/testnet/setup.py @@ -246,22 +246,17 @@ def build_binaries(testnet_config: TestnetConfiguration): node_folder = testnet_config.node_source() / "cmd" / "node" myprocess.run_process(['go', 'build'], cwd=node_folder, env=golang_env) - arwen_binary = testnet_config.arwen_binary() - logger.info(f"Arwen Binary: {arwen_binary}") - if arwen_binary: - logger.info("Building arwen...") - env = dict(golang_env) - env["ARWEN_PATH"] = str(node_folder) - node_folder_root = testnet_config.node_source() - myprocess.run_process(['make', 'arwen'], cwd=node_folder_root, env=env) + wasm_vm_binary = testnet_config.wasm_vm_binary() + if wasm_vm_binary: + logger.warn("WASM VM does not require building anymore. Skipping...") logger.info("Building proxy...") proxy_folder = testnet_config.proxy_source() / "cmd" / "proxy" myprocess.run_process(['go', 'build'], cwd=proxy_folder, env=golang_env) # Now copy the binaries to the testnet folder - arwen_version = _get_arwen_version(testnet_config) - libwasmer_path = path.join(golang.get_gopath(), f"pkg/mod/github.com/!elrond!network/arwen-wasm-vm@{arwen_version}/wasmer/libwasmer_darwin_amd64.dylib") + wasm_vm_version = _get_wasm_vm_version(testnet_config) + libwasmer_path = path.join(golang.get_gopath(), f"pkg/mod/github.com/!elrond!network/arwen-wasm-vm@{wasm_vm_version}/wasmer/libwasmer_darwin_amd64.dylib") shutil.copy(seednode_folder / "seednode", testnet_config.seednode_folder()) if workstation.get_platform() == "osx": @@ -269,11 +264,6 @@ def build_binaries(testnet_config: TestnetConfiguration): for destination in testnet_config.all_nodes_folders(): shutil.copy(node_folder / "node", destination) - if arwen_binary: - try: - shutil.copy(node_folder / "arwen", destination) - except FileNotFoundError: - logger.warn("Could not copy the arwen binary!") if workstation.get_platform() == "osx": shutil.copy(libwasmer_path, destination) @@ -283,7 +273,7 @@ def build_binaries(testnet_config: TestnetConfiguration): shutil.copy(libwasmer_path, testnet_config.proxy_folder()) -def _get_arwen_version(testnet_config: TestnetConfiguration): +def _get_wasm_vm_version(testnet_config: TestnetConfiguration): go_mod = testnet_config.node_source() / "go.mod" lines = utils.read_lines(str(go_mod)) line = next(line for line in lines if "github.com/ElrondNetwork/arwen-wasm-vm" in line) diff --git a/erdpy/tests/test_cli_deps.sh b/erdpy/tests/test_cli_deps.sh index 6dd9bbc9..7a1c024f 100644 --- a/erdpy/tests/test_cli_deps.sh +++ b/erdpy/tests/test_cli_deps.sh @@ -7,11 +7,11 @@ testAll() { ${ERDPY} --verbose deps install rust ${ERDPY} --verbose deps install clang - ${ERDPY} --verbose deps install arwentools --overwrite + ${ERDPY} --verbose deps install vmtools --overwrite ${ERDPY} --verbose deps check rust ${ERDPY} --verbose deps check clang - ${ERDPY} --verbose deps check arwentools + ${ERDPY} --verbose deps check vmtools set +x } From cb5049669d1e5ea227eefac3313f6d57b229d66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Sat, 30 Oct 2021 18:40:08 +0300 Subject: [PATCH 25/32] Exclude non-repos from 'erdpy deps install all' --- erdpy/dependencies/install.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erdpy/dependencies/install.py b/erdpy/dependencies/install.py index 2f10a6ed..fd142aa2 100644 --- a/erdpy/dependencies/install.py +++ b/erdpy/dependencies/install.py @@ -12,7 +12,7 @@ def install_module(key: str, tag: str = "", overwrite: bool = False): if key == 'all': - modules = get_all_deps() + modules = get_all_deps_installable_via_cli() else: modules = [get_module_by_key(key)] @@ -57,6 +57,16 @@ def get_all_deps() -> List[DependencyModule]: ] +def get_all_deps_installable_via_cli() -> List[DependencyModule]: + return [ + VMToolsModule(key="vmtools"), + StandaloneModule(key="elrond_go", repo_name="elrond-go", organisation="ElrondNetwork"), + StandaloneModule(key="elrond_proxy_go", repo_name="elrond-proxy-go", organisation="ElrondNetwork"), + MclSignerModule(key="mcl_signer") + ] + + + def get_golang() -> GolangModule: golang = get_module_by_key('golang') assert isinstance(golang, GolangModule) From 8096ce36474265b15a01dd60109904d25c362593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 11:41:48 +0200 Subject: [PATCH 26/32] Add support for Rust contract meta crates; more conversion to pathlib.Path; method renaming --- erdpy/projects/project_base.py | 25 +++++----- erdpy/projects/project_clang.py | 7 +-- erdpy/projects/project_rust.py | 81 +++++++++++++++++++++------------ erdpy/utils.py | 2 +- 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/erdpy/projects/project_base.py b/erdpy/projects/project_base.py index a75df035..ab4c84fb 100644 --- a/erdpy/projects/project_base.py +++ b/erdpy/projects/project_base.py @@ -26,7 +26,7 @@ def build(self, options: Union[Dict[str, Any], None] = None) -> Path: return self._do_after_build() def clean(self): - utils.remove_folder(self._get_output_folder()) + utils.remove_folder(self.get_output_folder()) def _ensure_dependencies_installed(self): module_keys = self.get_dependencies() @@ -42,36 +42,35 @@ def perform_build(self) -> None: def get_file_wasm(self): return self.find_file_in_output("*.wasm") - def find_file_globally(self, pattern): - folder = self.directory - return self.find_file_in_folder(folder, pattern) + def find_file_globally(self, pattern: str) -> Path: + return self.find_file_in_folder(self.path, pattern) - def find_file_in_output(self, pattern): - folder = path.join(self.directory, "output") + def find_file_in_output(self, pattern: str) -> Path: + folder = self.path / 'output' return self.find_file_in_folder(folder, pattern) - def find_file_in_folder(self, folder, pattern): - files = list(Path(folder).rglob(pattern)) + def find_file_in_folder(self, folder: Path, pattern: str) -> Path: + files = list(folder.rglob(pattern)) if len(files) == 0: raise errors.KnownError(f"No file matches pattern [{pattern}].") if len(files) > 1: logger.warning(f"More files match pattern [{pattern}]. Will pick first:\n{files}") - file = path.join(folder, files[0]) + file = folder / files[0] return Path(file).resolve() def _do_after_build(self) -> Path: raise NotImplementedError() - def _copy_to_output(self, source: str, destination: str = None) -> Path: - output_folder = self._get_output_folder() + def _copy_to_output(self, source: Path, destination: str = None) -> Path: + output_folder = self.get_output_folder() utils.ensure_folder(output_folder) destination = path.join(output_folder, destination) if destination else output_folder - output_wasm_file = shutil.copy(source, destination) + output_wasm_file = shutil.copy(str(source), destination) return Path(output_wasm_file) - def _get_output_folder(self): + def get_output_folder(self): return path.join(self.directory, "output") def get_bytecode(self): diff --git a/erdpy/projects/project_clang.py b/erdpy/projects/project_clang.py index 01647c94..10327a66 100644 --- a/erdpy/projects/project_clang.py +++ b/erdpy/projects/project_clang.py @@ -1,9 +1,10 @@ import logging -import os import subprocess from os import path from pathlib import Path +from typing import List + from erdpy import dependencies, errors, myprocess, utils from erdpy.projects.project_base import Project @@ -135,9 +136,9 @@ def ensure_source_files(self): self.config['source_files'] = source_files - def get_exported_functions(self): + def get_exported_functions(self) -> List[str]: file_export = self.find_file_globally('*.export') - lines = utils.read_lines(file_export) + lines = utils.read_lines(str(file_export)) return lines def default_config(self): diff --git a/erdpy/projects/project_rust.py b/erdpy/projects/project_rust.py index d742207b..8b6bd2a7 100644 --- a/erdpy/projects/project_rust.py +++ b/erdpy/projects/project_rust.py @@ -14,25 +14,34 @@ class ProjectRust(Project): def __init__(self, directory): super().__init__(directory) - self.cargo_file = self._get_cargo_file() + self.cargo_file = self.get_cargo_file() def clean(self): super().clean() utils.remove_folder(path.join(self.directory, "wasm", "target")) - def _get_cargo_file(self): - cargo_path = path.join(self.directory, "Cargo.toml") + def get_cargo_file(self): + cargo_path = self.path / 'Cargo.toml' return CargoFile(cargo_path) + def get_meta_folder(self): + return self.path / 'meta' + def perform_build(self): + meta = self.has_meta() try: + if meta: + self.run_meta() self.run_cargo() - self._generate_abi() + + # ABI generated separately for backwards compatibility + if not meta: + self.generate_abi() except subprocess.CalledProcessError as err: raise errors.BuildError(err.output) def run_cargo(self): - env = self._get_env() + env = self.get_env() args = [ "cargo", @@ -40,66 +49,82 @@ def run_cargo(self): "--target=wasm32-unknown-unknown", "--release", "--out-dir", - self._get_output_folder(), + self.get_output_folder(), "-Z" "unstable-options" ] - self._decorate_cargo_args(args) + self.decorate_cargo_args(args) if not self.options.get("wasm_symbols"): env["RUSTFLAGS"] = "-C link-arg=-s" - cwd = path.join(self.directory, "wasm") - return_code = myprocess.run_process_async(args, env=env, cwd=cwd) + cwd = self.path / 'wasm' + return_code = myprocess.run_process_async(args, env=env, cwd=str(cwd)) + if return_code != 0: + raise errors.BuildError(f"error code = {return_code}, see output") + + def run_meta(self): + cwd = self.get_meta_folder() + env = self.get_env() + + args = [ + "cargo", + "build", + ] + + return_code = myprocess.run_process_async(args, env=env, cwd=str(cwd)) if return_code != 0: raise errors.BuildError(f"error code = {return_code}, see output") - def _decorate_cargo_args(self, args): + def decorate_cargo_args(self, args): target_dir = self.options.get("cargo_target_dir") if target_dir: args.extend(["--target-dir", target_dir]) - def _generate_abi(self): - if not self._has_abi(): + def generate_abi(self): + if not self.has_abi(): return args = [ "cargo", "run" ] - self._decorate_cargo_args(args) + self.decorate_cargo_args(args) - env = self._get_env() + env = self.get_env() cwd = path.join(self.directory, "abi") - sink = myprocess.FileOutputSink(self._get_abi_filepath()) + sink = myprocess.FileOutputSink(self.get_abi_filepath()) return_code = myprocess.run_process_async(args, env=env, cwd=cwd, stdout_sink=sink) if return_code != 0: raise errors.BuildError(f"error code = {return_code}, see output") - utils.prettify_json_file(self._get_abi_filepath()) + utils.prettify_json_file(self.get_abi_filepath()) + + def has_meta(self): + return self.get_meta_folder().exists() - def _has_abi(self): - return (self._get_abi_folder() / "Cargo.toml").exists() + def has_abi(self): + return (self.get_abi_folder() / "Cargo.toml").exists() - def _get_abi_filepath(self): - return self._get_abi_folder() / "abi.json" + def get_abi_filepath(self): + return self.get_abi_folder() / "abi.json" - def _get_abi_folder(self): + def get_abi_folder(self): return Path(self.directory, "abi") def _do_after_build(self) -> Path: original_name = self.cargo_file.package_name wasm_base_name = self.cargo_file.package_name.replace("-", "_") - wasm_file = Path(self._get_output_folder(), f"{wasm_base_name}_wasm.wasm").resolve() + wasm_file = Path(self.get_output_folder(), f"{wasm_base_name}_wasm.wasm").resolve() wasm_file_renamed = self.options.get("wasm_name") if not wasm_file_renamed: wasm_file_renamed = f"{original_name}.wasm" - wasm_file_renamed_path = Path(self._get_output_folder(), wasm_file_renamed) + wasm_file_renamed_path = Path(self.get_output_folder(), wasm_file_renamed) shutil.move(wasm_file, wasm_file_renamed_path) - if self._has_abi(): - abi_file = self._get_abi_filepath() - abi_file_renamed = Path(self._get_output_folder(), f"{original_name}.abi.json") + if self.has_abi(): + abi_file = self.get_abi_filepath() + abi_file_renamed = Path(self.get_output_folder(), f"{original_name}.abi.json") shutil.move(abi_file, abi_file_renamed) return wasm_file_renamed_path @@ -107,14 +132,14 @@ def _do_after_build(self) -> Path: def get_dependencies(self): return ["rust"] - def _get_env(self): + def get_env(self): return dependencies.get_module_by_key("rust").get_env() class CargoFile: data: Dict[str, Any] - def __init__(self, path): + def __init__(self, path: Path): self.data = {} self.path = path diff --git a/erdpy/utils.py b/erdpy/utils.py index 5c86eed3..5e98521e 100644 --- a/erdpy/utils.py +++ b/erdpy/utils.py @@ -79,7 +79,7 @@ def uniquify(path: Path) -> Path: return path -def read_lines(file: str): +def read_lines(file: str) -> List[str]: with open(file) as f: lines = f.readlines() lines = [line.strip() for line in lines] From b083d835d022f354c0d5b6c490db261047bd6c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:09:11 +0200 Subject: [PATCH 27/32] Update erdpy/projects/project_rust.py Co-authored-by: Andrei Marinica --- erdpy/projects/project_rust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/projects/project_rust.py b/erdpy/projects/project_rust.py index 8b6bd2a7..1e809070 100644 --- a/erdpy/projects/project_rust.py +++ b/erdpy/projects/project_rust.py @@ -101,7 +101,7 @@ def generate_abi(self): utils.prettify_json_file(self.get_abi_filepath()) def has_meta(self): - return self.get_meta_folder().exists() + return (self.get_meta_folder() / "Cargo.toml").exists() def has_abi(self): return (self.get_abi_folder() / "Cargo.toml").exists() From 2e582b2d78c0fa9d1cece2ddb1ca0e38e08305a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:12:17 +0200 Subject: [PATCH 28/32] Add comment --- erdpy/projects/project_rust.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erdpy/projects/project_rust.py b/erdpy/projects/project_rust.py index 8b6bd2a7..84172bc2 100644 --- a/erdpy/projects/project_rust.py +++ b/erdpy/projects/project_rust.py @@ -31,6 +31,8 @@ def perform_build(self): meta = self.has_meta() try: if meta: + # The meta crate allows contract developers to add extra + # preparation steps before building. self.run_meta() self.run_cargo() From 4af320878cc1a291f6d8bff7601870d849530c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:14:36 +0200 Subject: [PATCH 29/32] Regenerate CLI.md --- erdpy/CLI.md.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/CLI.md.sh b/erdpy/CLI.md.sh index 498cbc46..1d868b8b 100755 --- a/erdpy/CLI.md.sh +++ b/erdpy/CLI.md.sh @@ -67,7 +67,7 @@ generate() { group "Account" "account" command "Account.Get" "account get" command "Account.GetTransactions" "account get-transactions" - + group "Wallet" "wallet" command "Wallet.Derive" "wallet derive" command "Wallet.Bech32" "wallet bech32" From 6836d49d0a3abc79adbae6460713e56378d08139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:29:49 +0200 Subject: [PATCH 30/32] Update erdpy/projects/project_rust.py Co-authored-by: Andrei Marinica --- erdpy/projects/project_rust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erdpy/projects/project_rust.py b/erdpy/projects/project_rust.py index 1e809070..30181709 100644 --- a/erdpy/projects/project_rust.py +++ b/erdpy/projects/project_rust.py @@ -69,7 +69,7 @@ def run_meta(self): args = [ "cargo", - "build", + "run", ] return_code = myprocess.run_process_async(args, env=env, cwd=str(cwd)) From f20a5ba297631ceb78b87930593df8e919f99c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:30:50 +0200 Subject: [PATCH 31/32] Regenerate CLI.md --- erdpy/CLI.md | 668 +++++++++++++++++++++++++----------------------- erdpy/CLI.md.sh | 1 + 2 files changed, 345 insertions(+), 324 deletions(-) diff --git a/erdpy/CLI.md b/erdpy/CLI.md index 61b2be6e..7f7537f5 100644 --- a/erdpy/CLI.md +++ b/erdpy/CLI.md @@ -20,7 +20,7 @@ https://docs.elrond.com/tools/erdpy. COMMAND GROUPS: - {contract,tx,validator,account,wallet,network,cost,dispatcher,blockatlas,deps,config,hyperblock,testnet,data,staking-provider,dns} + {contract,tx,validator,account,ledger,wallet,network,cost,dispatcher,blockatlas,deps,config,hyperblock,testnet,data,staking-provider,dns} TOP-LEVEL OPTIONS: -h, --help show this help message and exit @@ -32,8 +32,9 @@ COMMAND GROUPS summary ---------------------- contract Build, deploy and interact with Smart Contracts tx Create and broadcast Transactions -validator Stake, Unjail and other actions useful for Validators +validator Stake, UnStake, UnBond, Unjail and other actions useful for Validators account Get Account data (nonce, balance) from the Network +ledger Get Ledger App addresses and version wallet Derive secret key from mnemonic, bech32 address helpers etc. network Get Network parameters, such as number of shards, chain identifier etc. cost Estimate cost of Transactions @@ -46,7 +47,6 @@ testnet Set up, start and control local testnets data Data manipulation omnitool staking-provider Staking provider omnitool dns Operations related to the Domain Name Service -ledger Get Ledger App address and version ``` ## Group **Contract** @@ -126,6 +126,10 @@ optional arguments: --debug set debug flag (default: False) --no-optimization bypass optimizations (for clang) (default: False) --cargo-target-dir CARGO_TARGET_DIR for rust projects, forward the parameter to Cargo + --wasm-symbols for rust projects, does not strip the symbols from the wasm output. Useful for + analysing the bytecode. Creates larger wasm files. Avoid in production (default: + False) + --wasm-name WASM_NAME for rust projects, optionally specify the name of the wasm bytecode output file ``` ### Contract.Clean @@ -154,32 +158,37 @@ usage: erdpy contract deploy [-h] ... Deploy a Smart Contract. optional arguments: - -h, --help show this help message and exit - --project PROJECT 🗀 the project directory (default: current directory) - --bytecode BYTECODE the WASM file - --metadata-not-upgradeable ‼ mark the contract as NOT upgradeable (default: upgradeable) - --metadata-payable ‼ mark the contract as payable (default: not payable) - --outfile OUTFILE where to save the output (default: stdout) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. - --arguments 42 0x64 1000 0xabba - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) + -h, --help show this help message and exit + --project PROJECT 🗀 the project directory (default: current directory) + --bytecode BYTECODE the file containing the WASM bytecode + --metadata-not-upgradeable ‼ mark the contract as NOT upgradeable (default: upgradeable) + --metadata-payable ‼ mark the contract as payable (default: not payable) + --outfile OUTFILE where to save the output (default: stdout) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. + --arguments 42 0x64 1000 0xabba + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) ``` ### Contract.Call @@ -192,33 +201,38 @@ usage: erdpy contract call [-h] ... Interact with a Smart Contract (execute function). positional arguments: - contract 🖄 the address of the Smart Contract + contract 🖄 the address of the Smart Contract optional arguments: - -h, --help show this help message and exit - --outfile OUTFILE where to save the output (default: stdout) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --function FUNCTION the function to call - --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. - --arguments 42 0x64 1000 0xabba - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --relay whether to relay the transaction (default: False) + -h, --help show this help message and exit + --outfile OUTFILE where to save the output (default: stdout) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --function FUNCTION the function to call + --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. + --arguments 42 0x64 1000 0xabba + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --relay whether to relay the transaction (default: False) ``` ### Contract.Upgrade @@ -231,35 +245,40 @@ usage: erdpy contract upgrade [-h] ... Upgrade a previously-deployed Smart Contract positional arguments: - contract 🖄 the address of the Smart Contract + contract 🖄 the address of the Smart Contract optional arguments: - -h, --help show this help message and exit - --outfile OUTFILE where to save the output (default: stdout) - --project PROJECT 🗀 the project directory (default: current directory) - --bytecode BYTECODE the WASM file - --metadata-not-upgradeable ‼ mark the contract as NOT upgradeable (default: upgradeable) - --metadata-payable ‼ mark the contract as payable (default: not payable) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. - --arguments 42 0x64 1000 0xabba - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) + -h, --help show this help message and exit + --outfile OUTFILE where to save the output (default: stdout) + --project PROJECT 🗀 the project directory (default: current directory) + --bytecode BYTECODE the file containing the WASM bytecode + --metadata-not-upgradeable ‼ mark the contract as NOT upgradeable (default: upgradeable) + --metadata-payable ‼ mark the contract as payable (default: not payable) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. + --arguments 42 0x64 1000 0xabba + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) ``` ### Contract.Query @@ -276,7 +295,7 @@ positional arguments: optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --function FUNCTION the function to call --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba @@ -315,31 +334,36 @@ usage: erdpy tx new [-h] ... Create a new transaction optional arguments: - -h, --help show this help message and exit - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --receiver RECEIVER 🖄 the address of the receiver - --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --value VALUE the value to transfer (default: 0) - --data DATA the payload, or 'memo' of the transaction (default: ) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --data-file DATA_FILE a file containing transaction data - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --relay whether to relay the transaction (default: False) - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + -h, --help show this help message and exit + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --receiver RECEIVER 🖄 the address of the receiver + --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --value VALUE the value to transfer (default: 0) + --data DATA the payload, or 'memo' of the transaction (default: ) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --data-file DATA_FILE a file containing transaction data + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --relay whether to relay the transaction (default: False) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set ``` ### Transactions.Send @@ -355,7 +379,7 @@ optional arguments: -h, --help show this help message and exit --infile INFILE input file (a previously saved transaction) --outfile OUTFILE where to save the output (the hash) (default: stdout) - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) ``` ### Transactions.Get @@ -372,7 +396,7 @@ optional arguments: --hash HASH the hash --sender SENDER the sender address --with-results will also return the results of transaction - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --omit-fields OMIT_FIELDS omit fields in the output payload (default: []) ``` @@ -403,7 +427,7 @@ Get hyperblock optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --key KEY the hash or the nonce of the hyperblock ``` @@ -414,10 +438,10 @@ optional arguments: $ erdpy validator --help usage: erdpy validator COMMAND [-h] ... -Stake, Unjail and other actions useful for Validators +Stake, UnStake, UnBond, Unjail and other actions useful for Validators COMMANDS: - {stake,unstake,unjail,unbond,change-reward-address,claim} + {stake,unstake,unjail,unbond,change-reward-address,claim,unstake-nodes,unstake-tokens,unbond-nodes,unbond-tokens,clean-registered-data,restake-unstaked-nodes} OPTIONS: -h, --help show this help message and exit @@ -428,9 +452,15 @@ COMMANDS summary stake Stake value into the Network unstake Unstake value unjail Unjail a Validator Node -unbond Unbond +unbond Unbond tokens for a bls key change-reward-address Change the reward address claim Claim rewards +unstake-nodes Unstake-nodes will unstake nodes for provided bls keys +unstake-tokens This command will un-stake the given amount (if value is greater than the existing topUp value, it will unStake one or several nodes) +unbond-nodes It will unBond nodes +unbond-tokens It will unBond tokens, if provided value is bigger that topUp value will unBond nodes +clean-registered-data Deletes duplicated keys from registered data +restake-unstaked-nodes It will reStake UnStaked nodes ``` ### Validator.Stake @@ -443,29 +473,32 @@ usage: erdpy validator stake [-h] ... Stake value into the Network optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --reward-address REWARD_ADDRESS the reward address - --validators-file VALIDATORS_FILE a JSON file describing the Nodes + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --reward-address REWARD_ADDRESS the reward address + --validators-file VALIDATORS_FILE a JSON file describing the Nodes + --top-up Stake value for top up ``` ### Validator.Unstake @@ -478,28 +511,30 @@ usage: erdpy validator unstake [-h] ... Unstake value optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) ``` ### Validator.Unjail @@ -512,28 +547,30 @@ usage: erdpy validator unjail [-h] ... Unjail a Validator Node optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) ``` ### Validator.Unbond @@ -543,31 +580,33 @@ optional arguments: $ erdpy validator unbond --help usage: erdpy validator unbond [-h] ... -Unbond +Unbond tokens for a bls key optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --nodes-public-keys NODES_PUBLIC_KEYS the public keys of the nodes as CSV (addrA,addrB) ``` ### Validator.ChangeRewardAddress @@ -580,28 +619,30 @@ usage: erdpy validator change-reward-address [-h] ... Change the reward address optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) - --reward-address REWARD_ADDRESS the new reward address + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + --reward-address REWARD_ADDRESS the new reward address ``` ### Validator.Claim @@ -614,27 +655,29 @@ usage: erdpy validator claim [-h] ... Claim rewards optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --nonce NONCE # the nonce for the transaction - --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: False) - --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) - --gas-limit GAS_LIMIT ⛽ the gas limit - --estimate-gas ⛽ whether to estimate the gas limit (default: 0) - --value VALUE the value to transfer (default: 0) - --chain CHAIN the chain identifier (default: T) - --version VERSION the transaction version (default: 1) - --send ✓ whether to broadcast the transaction (default: False) - --simulate whether to simulate the transaction (default: False) - --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --nonce NONCE # the nonce for the transaction + --recall-nonce ⭮ whether to recall the nonce when creating the transaction (default: + False) + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --estimate-gas ⛽ whether to estimate the gas limit (default: 0) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier (default: T) + --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --outfile OUTFILE where to save the output (signed transaction, hash) (default: stdout) ``` ## Group **Account** @@ -670,7 +713,7 @@ Query account details (nonce, balance etc.) optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --address ADDRESS 🖄 the address to query --balance whether to only fetch the balance --nonce whether to only fetch the nonce @@ -689,7 +732,7 @@ Query account transactions optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --outfile OUTFILE where to save the output (default: stdout) --address ADDRESS 🖄 the address to query @@ -704,7 +747,7 @@ usage: erdpy wallet COMMAND [-h] ... Derive secret key from mnemonic, bech32 address helpers etc. COMMANDS: - {derive,bech32,pem-address,pem-address-hex} + {new,derive,bech32,pem-address,pem-address-hex} OPTIONS: -h, --help show this help message and exit @@ -712,11 +755,28 @@ OPTIONS: ---------------- COMMANDS summary ---------------- +new Create a new wallet derive Derive a PEM file from a mnemonic or generate a new PEM file (for tests only!) bech32 Helper for encoding and decoding bech32 addresses pem-address Get the public address out of a PEM file as bech32 pem-address-hex Get the public address out of a PEM file as hex +``` +### Wallet.New + + +``` +$ erdpy wallet new --help +usage: erdpy wallet new [-h] ... + +Create a new wallet + +optional arguments: + -h, --help show this help message and exit + --json whether to create a json key file + --pem whether to create a pem key file + --output-path OUTPUT_PATH the output path and base file name for the generated wallet files (default: ./wallet) + ``` ### Wallet.Derive @@ -860,7 +920,7 @@ Get the number of shards. optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) ``` ### Network.BlockNonce @@ -874,7 +934,7 @@ Get the latest block nonce, by shard. optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --shard SHARD the shard ID (use 4294967295 for metachain) ``` @@ -889,7 +949,7 @@ Get the chain identifier. optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) ``` ## Group **Cost** @@ -927,7 +987,7 @@ Query minimum gas price optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) ``` ### Cost.TxTransfer @@ -941,7 +1001,7 @@ Query cost of regular transaction (transfer) optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --data DATA a transaction payload, required to estimate the cost ``` @@ -956,9 +1016,9 @@ Query cost of Smart Contract deploy transaction optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --project PROJECT 🗀 the project directory (default: current directory) - --bytecode BYTECODE the WASM file + --bytecode BYTECODE the file containing the WASM bytecode --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba @@ -977,7 +1037,7 @@ positional arguments: optional arguments: -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) --function FUNCTION the function to call --arguments ARGUMENTS [ARGUMENTS ...] arguments for the contract transaction, as numbers or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba @@ -1026,6 +1086,7 @@ optional arguments: --data DATA the payload, or 'memo' of the transaction (default: ) --chain CHAIN the chain identifier (default: T) --version VERSION the transaction version (default: 1) + --options OPTIONS the transaction options (default: 0) ``` ### Dispatcher.Dispatch @@ -1038,16 +1099,16 @@ usage: erdpy dispatcher dispatch [-h] ... Dispatch queued transactions optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender ``` ### Dispatcher.DispatchContinuously @@ -1060,17 +1121,17 @@ usage: erdpy dispatcher dispatch-continuously [-h] ... Continuously dispatch queued transactions optional arguments: - -h, --help show this help message and exit - --proxy PROXY 🖧 the URL of the proxy (default: https://testnet-gateway.elrond.com) - --pem PEM 🔑 the PEM file, if keyfile or ledger are not provided - --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) - --keyfile KEYFILE 🔑 a JSON keyfile, if PEM of ledger not provided - --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided - --ledger 🔐 bool flag for signing transaction using ledger - --ledger-account-index 🔐 the index of the account (only applicable if --ledger is set) - --ledger-address-index 🔐 the index of the address (only applicable if --ledger is set) - --sender-username SENDER_USERNAME 🖄 the username of the sender - --interval INTERVAL the interval to retrieve transactions from the queue, in seconds + -h, --help show this help message and exit + --proxy PROXY 🔗 the URL of the proxy (default: https://testnet-api.elrond.com) + --pem PEM 🔑 the PEM file, if keyfile not provided + --pem-index PEM_INDEX 🔑 the index in the PEM file (default: 0) + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE 🔑 a file containing keyfile's password, if keyfile provided + --ledger 🔐 bool flag for signing transaction using ledger + --ledger-account-index LEDGER_ACCOUNT_INDEX 🔐 the index of the account when using Ledger + --ledger-address-index LEDGER_ADDRESS_INDEX 🔐 the index of the address when using Ledger + --sender-username SENDER_USERNAME 🖄 the username of the sender + --interval INTERVAL the interval to retrieve transactions from the queue, in seconds ``` ### Dispatcher.Clean @@ -1185,7 +1246,7 @@ usage: erdpy deps install [-h] ... Install dependencies or elrond-sdk modules. positional arguments: - {llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} + {all,llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} the dependency to install optional arguments: @@ -1204,7 +1265,7 @@ usage: erdpy deps check [-h] ... Check whether a dependency is installed. positional arguments: - {llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} + {all,llvm,clang,cpp,vmtools,rust,nodejs,elrond_go,elrond_proxy_go,golang,mcl_signer} the dependency to check optional arguments: @@ -1222,7 +1283,7 @@ usage: erdpy config COMMAND [-h] ... Configure elrond-sdk (default values etc.) COMMANDS: - {dump,get,set,new,switch,list} + {dump,get,set,delete,new,switch,list} OPTIONS: -h, --help show this help message and exit @@ -1233,6 +1294,7 @@ COMMANDS summary dump Dumps configuration. get Gets a configuration value. set Sets a configuration value. +delete Deletes a configuration value. new Creates a new configuration. switch Switch to a different config list List available configs @@ -1249,6 +1311,7 @@ Dumps configuration. optional arguments: -h, --help show this help message and exit + --defaults dump defaults instead of local config ``` ### Configuration.Get @@ -1401,46 +1464,3 @@ optional arguments: --use-global use the global storage (default: False) ``` - -## Group **Ledger** - - - -``` -usage: erdpy ledger COMMAND [-h] ... - -Get Ledger App addresses and version - -COMMANDS: - {addresses,version} - -OPTIONS: - -h, --help show this help message and exit - ----------------- -COMMANDS summary ----------------- -addresses Print multiple addresses for the Ledger device -version Print the Elrond App version -``` - -### Ledger.addresses -``` -usage: erdpy ledger addresses [-h] ... - -Get the addresses within Ledger - -optional arguments: - -h, --help show this help message and exit - --num-addresses NUM_ADDRESSES The number of addresses to fetch -``` - -### Ledger.version -``` -usage: erdpy ledger version [-h] ... - -Get the version of the Elrond App for Ledger - -optional arguments: - -h, --help show this help message and exit -``` diff --git a/erdpy/CLI.md.sh b/erdpy/CLI.md.sh index 1d868b8b..1afbc44c 100755 --- a/erdpy/CLI.md.sh +++ b/erdpy/CLI.md.sh @@ -69,6 +69,7 @@ generate() { command "Account.GetTransactions" "account get-transactions" group "Wallet" "wallet" + command "Wallet.New" "wallet new" command "Wallet.Derive" "wallet derive" command "Wallet.Bech32" "wallet bech32" From 8e93a3528d652f3b0eb1b4316b091f25020a4e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camil=20B=C4=83ncioiu?= Date: Mon, 1 Nov 2021 12:52:30 +0200 Subject: [PATCH 32/32] Prepare version 1.0.21; minor fixes --- erdpy/CHANGELOG.md | 7 +++++++ erdpy/CLI.md | 9 +++++---- erdpy/CLI.md.sh | 2 ++ erdpy/_version.py | 2 +- erdpy/cli_wallet.py | 4 ++-- erdpy/wallet/core.py | 2 +- erdpy/wallet/generator.py | 4 ---- setup.py | 2 +- 8 files changed, 19 insertions(+), 13 deletions(-) diff --git a/erdpy/CHANGELOG.md b/erdpy/CHANGELOG.md index aba81a1e..7dcf2610 100644 --- a/erdpy/CHANGELOG.md +++ b/erdpy/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes will be documented in this file. Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +## [1.0.21] - 01.11.2021 + - New command `erdpy wallet new`, which generates a new wallet mnemonic and optionally saves it to JSON or PEM + - Add support for Rust contract `meta` crates + - Update reference to the renamed VM repository (VM dependency is now named `vmtools`) + - Change `erdpy deps install all` to avoid installing / overwriting non-repository dependencies, e.g. Rust, LLVM, Go + - Update help strings and `CLI.md` + ## [1.0.20] - 26.10.2021 - Bugfix by [phanletrunghieu](https://github.com/phanletrunghieu): use $PATH in `erdpy-up` - Bugfix by [x2ocoder](https://github.com/x2ocoder): add missing `enable_epochs` configurations diff --git a/erdpy/CLI.md b/erdpy/CLI.md index 7f7537f5..b5a6f2fc 100644 --- a/erdpy/CLI.md +++ b/erdpy/CLI.md @@ -35,7 +35,7 @@ tx Create and broadcast Transactions validator Stake, UnStake, UnBond, Unjail and other actions useful for Validators account Get Account data (nonce, balance) from the Network ledger Get Ledger App addresses and version -wallet Derive secret key from mnemonic, bech32 address helpers etc. +wallet Create wallet, derive secret key from mnemonic, bech32 address helpers etc. network Get Network parameters, such as number of shards, chain identifier etc. cost Estimate cost of Transactions dispatcher Enqueue transactions, then bulk dispatch them @@ -744,7 +744,7 @@ optional arguments: $ erdpy wallet --help usage: erdpy wallet COMMAND [-h] ... -Derive secret key from mnemonic, bech32 address helpers etc. +Create wallet, derive secret key from mnemonic, bech32 address helpers etc. COMMANDS: {new,derive,bech32,pem-address,pem-address-hex} @@ -755,7 +755,7 @@ OPTIONS: ---------------- COMMANDS summary ---------------- -new Create a new wallet +new Create a new wallet and print its mnemonic; optionally save as password-protected JSON (recommended) or PEM (not recommended) derive Derive a PEM file from a mnemonic or generate a new PEM file (for tests only!) bech32 Helper for encoding and decoding bech32 addresses pem-address Get the public address out of a PEM file as bech32 @@ -769,7 +769,8 @@ pem-address-hex Get the public address out of a PEM file as hex $ erdpy wallet new --help usage: erdpy wallet new [-h] ... -Create a new wallet +Create a new wallet and print its mnemonic; optionally save as password-protected JSON (recommended) or PEM (not +recommended) optional arguments: -h, --help show this help message and exit diff --git a/erdpy/CLI.md.sh b/erdpy/CLI.md.sh index 1afbc44c..a5a767ff 100755 --- a/erdpy/CLI.md.sh +++ b/erdpy/CLI.md.sh @@ -118,3 +118,5 @@ generate() { command "Data.Store" "data store" command "Data.Load" "data load" } + +generate diff --git a/erdpy/_version.py b/erdpy/_version.py index 6e3c058c..c916e680 100644 --- a/erdpy/_version.py +++ b/erdpy/_version.py @@ -1 +1 @@ -__version__ = "1.0.20" +__version__ = "1.0.21" diff --git a/erdpy/cli_wallet.py b/erdpy/cli_wallet.py index 924b8516..7ef7f202 100644 --- a/erdpy/cli_wallet.py +++ b/erdpy/cli_wallet.py @@ -16,7 +16,7 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: parser = cli_shared.add_group_subparser( subparsers, "wallet", - "Derive secret key from mnemonic, bech32 address helpers etc." + "Create wallet, derive secret key from mnemonic, bech32 address helpers etc." ) subparsers = parser.add_subparsers() @@ -24,7 +24,7 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: subparsers, "wallet", "new", - "Create a new wallet" + "Create a new wallet and print its mnemonic; optionally save as password-protected JSON (recommended) or PEM (not recommended)" ) sub.add_argument("--json", help="whether to create a json key file", action="store_true", default=False) diff --git a/erdpy/wallet/core.py b/erdpy/wallet/core.py index dc0d9909..ce85e86d 100644 --- a/erdpy/wallet/core.py +++ b/erdpy/wallet/core.py @@ -3,7 +3,7 @@ import secrets import struct from importlib.resources import open_text -from typing import List, Optional +from typing import List import nacl.signing diff --git a/erdpy/wallet/generator.py b/erdpy/wallet/generator.py index 1ca78db3..80e1f58a 100644 --- a/erdpy/wallet/generator.py +++ b/erdpy/wallet/generator.py @@ -1,10 +1,6 @@ import logging import nacl.encoding import nacl.signing -import base64 -from os import path - -from erdpy import utils, guards logger = logging.getLogger("wallet.generator") diff --git a/setup.py b/setup.py index eb4a7185..fec684a8 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ with open("README.md", "r") as fh: long_description = "https://github.com/ElrondNetwork/elrond-sdk-erdpy" -VERSION = "1.0.20" +VERSION = "1.0.21" try: with open('./erdpy/_version.py', 'wt') as versionfile: