diff --git a/aptos-move/framework/aptos-framework/doc/account.md b/aptos-move/framework/aptos-framework/doc/account.md index 39fb5d4e0421d..6b42e56fb8636 100644 --- a/aptos-move/framework/aptos-framework/doc/account.md +++ b/aptos-move/framework/aptos-framework/doc/account.md @@ -348,10 +348,6 @@ Second, this struct is signed by the new public key that the account owner wants knowledge of this new public key's associated secret key. These two signatures cannot be replayed in another context because they include the TXN's unique sequence number. -Note that the challenge message to sign includes the RotationProofChallenge type info prepended to the -relevant bytes, such that serializing then signing only the below four struct fields will lead to rotation -failure. For the verification implementation, see aptos_stdlib::ed25519::signature_verify_strict_t(). -
struct RotationProofChallenge has copy, drop
 
diff --git a/aptos-move/framework/aptos-framework/sources/account.move b/aptos-move/framework/aptos-framework/sources/account.move index 87e1381b7e892..f91e8df743e5e 100644 --- a/aptos-move/framework/aptos-framework/sources/account.move +++ b/aptos-move/framework/aptos-framework/sources/account.move @@ -68,10 +68,6 @@ module aptos_framework::account { /// Second, this struct is signed by the new public key that the account owner wants to rotate to, which proves /// knowledge of this new public key's associated secret key. These two signatures cannot be replayed in another /// context because they include the TXN's unique sequence number. - /// - /// Note that the challenge message to sign includes the `RotationProofChallenge` type info prepended to the - /// relevant bytes, such that serializing then signing only the below four struct fields will lead to rotation - /// failure. For the verification implementation, see `aptos_stdlib::ed25519::signature_verify_strict_t()`. struct RotationProofChallenge has copy, drop { sequence_number: u64, // the sequence number of the account whose key is being rotated originator: address, // the address of the account whose key is being rotated diff --git a/developer-docs-site/docs/tutorials/first-multisig.md b/developer-docs-site/docs/tutorials/first-multisig.md index e5b6acc84a6e0..a0ff2210cf639 100644 --- a/developer-docs-site/docs/tutorials/first-multisig.md +++ b/developer-docs-site/docs/tutorials/first-multisig.md @@ -354,1847 +354,6 @@ Bob's balance: 20000200 Chad's balance: 30000100 ``` -## Step 9: Expedite execution with AMEE - -The above code snippets demonstrate concepts relevant to multisig operations, but are impractical for realistic workflows: -all of the private keys are stored in memory on the same machine, the function calls do not generalize to other multisig operations, etc. -As a result, there is a significant amount of overhead required to implement a bespoke solution that ports the above concepts to one's particular use case, which almost necessarily involves signers coordinating across space and time through an off-chain social consensus strategy (e.g. Have enough signatories signed yet? How do we compile their signatures?) - -To expedite this process, the Python SDK thus provides the Aptos Multisig Execution Expeditor (AMEE), a command-line tool that facilitates general multisig workflows through straightforward data structures and function calls. - -To use AMEE, navigate to the Python SDK package directory: - -```zsh -cd /aptos-core/ecosystem/python/sdk/aptos_sdk -``` - -Then call up the help menu from the command line: - -```python title=Command -:!: static/sdks/python/examples/multisig.sh help -``` - -```zsh title=Output -usage: amee.py [-h] {keyfile,k,metafile,m,publish,p,rotate,r,script,s} ... - -Aptos Multisig Execution Expeditor (AMEE): A collection of tools designed to expedite multisig account execution. - -positional arguments: - {keyfile,k,metafile,m,publish,p,rotate,r,script,s} - keyfile (k) Single-signer keyfile operations. - metafile (m) Multisig metafile operations. - publish (p) Move package publication. - rotate (r) Authentication key rotation operations. - script (s) Move script invocation. - -optional arguments: - -h, --help show this help message and exit -``` - -AMEE offers a rich collection of useful subcommands, and to access their all of their help menus recursively simply call the `multisig.sh` shell script file with the `menus` argument (still from inside the `aptos_sdk` directory): - -```zsh title=Command -sh ../examples/multisig.sh menus -``` - -:::tip -This shell script file will be used for several other examples throughout the remainder of this tutorial, so try running it now! -::: - -```zsh title=Output - - - -... - -usage: amee.py keyfile [-h] {change-password,c,extract,e,fund,f,generate,g,verify,v} ... - -Assorted single-signer keyfile operations. - -positional arguments: - {change-password,c,extract,e,fund,f,generate,g,verify,v} - change-password (c) - Change keyfile password. - extract (e) Extract Aptos account store from keyfile. - fund (f) Fund on devnet faucet. - generate (g) Generate new keyfile. - verify (v) Verify keyfile password. - -options: - -h, --help show this help message and exit - - - - - -usage: amee.py keyfile change-password [-h] [-u] keyfile - -Change password for a single-singer keyfile. - -positional arguments: - keyfile Relative path to keyfile. - -options: - -h, --help show this help message and exit - -u, --use-test-password - Flag to use test password. - -... - - - -``` - -### Step 9.1 Keyfiles - -Unlike the `aptos` CLI which stores private keys in plain text on disk, AMEE encrypts single-signer private keys in a [JSON](https://docs.python.org/3/library/json.html) keyfile format with password protection: - -```zsh title=Command -:!: static/sdks/python/examples/multisig.sh generate_keyfile -``` - -This initiates a hidden password prompt and creates a new file on disk: - -```zsh title=Output -Enter new password for encrypting private key: -Re-enter password: -Keyfile now at the_aptos_foundation.keyfile: -{ - "filetype": "Keyfile", - "signatory": "The Aptos Foundation", - "public_key": "0x7d1bed984fd185595059f94cbe95ed3e4ce9b49bd3c53bace8102813cfdc4adc", - "authentication_key": "0x682b1a757af92532d184aab6d6ca7fa92b8229c38118c1729187ed1fb2106b15", - "encrypted_private_key": "0x674141414141426a377157643961486e544875424b4e43546831586454654855376956734656465039335a336266544f4f4d7157785354544a5671387932364d69494c364f724e44447143766871626b35564b36306e4362726a33566356536330636965524d5f777656466c5a394273314f78714151384c6d352d764b6666344443716978365a35397a4a65", - "salt": "0x5e323ba1f941152c38be4b05a04e24dd" -} -``` - -This keyfile can be decrypted using the password to produce an unprotected account store (via `aptos_sdk.account.Account.store()`), which may be useful when trying to fund via the testnet faucet. Note here the abbreviation of `keyfile` to `k`: - -```zsh title=Command -:!: static/sdks/python/examples/multisig.sh extract_keyfile -``` - -```zsh title=Output -Enter password for encrypted private key: -New account store at the_aptos_foundation.account_store: -{"account_address": "0x682b1a757af92532d184aab6d6ca7fa92b8229c38118c1729187ed1fb2106b15", "private_key": "0x4ae3985bd49571cf67b42a391d72956a95cfb9aa634fd05c019a96a6eccd399d"} -``` - -Similarly, AMEE can generate keyfiles from an unprotected account store format. Note here the abbreviation of `generate` to `g` and the optional `outfile` positional argument: - -:::tip -AMEE supports abbreviations for all commands and subcommands! -::: - -```zsh title=Command -:!: static/sdks/python/examples/multisig.sh generate_from_store -``` - -```zsh title=Output -Enter new password for encrypting private key: -Re-enter password: -Keyfile now at from_store.keyfile: -{ - "filetype": "Keyfile", - "signatory": "The Aptos Foundation", - "public_key": "0x7d1bed984fd185595059f94cbe95ed3e4ce9b49bd3c53bace8102813cfdc4adc", - "authentication_key": "0x682b1a757af92532d184aab6d6ca7fa92b8229c38118c1729187ed1fb2106b15", - "encrypted_private_key": "0x674141414141426a3771576861794330645a4949575051494f4f5a45647847426b5659723638506a464d666a5768486549357375437834696747514b6373466a683741732d78616e4958426e326a717066683071376c486c76364159646761765a514e2d715669664a50776e7a6c655f4436546d57762d426e3471765f5f6e45664e737530336f7a7a75702d", - "salt": "0x0656247cc0c7d571058a9b9ad7d6858b" -} -``` - -To change the password on a keyfile: - - -```zsh title=Command -:!: static/sdks/python/examples/multisig.sh change_password -``` - -```zsh title=Output -Enter password for encrypted private key: -Enter new password for encrypting private key: -Re-enter password: -Keyfile now at from_store.keyfile: -{ - "filetype": "Keyfile", - "signatory": "The Aptos Foundation", - "public_key": "0x7d1bed984fd185595059f94cbe95ed3e4ce9b49bd3c53bace8102813cfdc4adc", - "authentication_key": "0x682b1a757af92532d184aab6d6ca7fa92b8229c38118c1729187ed1fb2106b15", - "encrypted_private_key": "0x674141414141426a3771576c48575570445a56707149732d6153785773753630696a656565315a5f684f365469696f523276705946565f2d7077556c49466c3656625468303731486c3654744a456e6575693443596d417065454f4f687435435a316f4b55444762536c43584b5067534e466664455135615f414a614270757a4637445a5554555870533149", - "salt": "0xd831bcda8cfac7b94a2065c7c829eac3" -} -``` - -Now verify the new password: - -```zsh title=Command -:!: static/sdks/python/examples/multisig.sh verify_password -``` - -```zsh title=Output -Enter password for encrypted private key: -Keyfile password verified for The Aptos Foundation -Public key: 0x7d1bed984fd185595059f94cbe95ed3e4ce9b49bd3c53bace8102813cfdc4adc -Authentication key: 0x682b1a757af92532d184aab6d6ca7fa92b8229c38118c1729187ed1fb2106b15 -``` - -Note that all of these commands can be run in a scripted fashion simply by calling the `multisig.sh` shell script with the `keyfiles` argument. - -```zsh title=Command -sh ../examples/multisig.sh keyfiles -``` - -:::tip -Try running the shell script yourself, then experiment with variations on the commands! -::: - -### Step 9.2 Metafiles - -AMEE manages multisig account metadata through metafiles, which assimilate information from multiple single-signer keyfiles. - -The below demo script, also in `multisig.sh`, demonstrates assorted metafile operations: - -| Command | Use | -|------------------------|------------------------------------------------------------------| -| `metafile incorporate` | Incorporate multiple signers into a multisig metafile | -| `metafile threshold` | Modify the threshold, outputting a new metafile | -| `metafile append` | Append a new signatory or signatories, outputting a new metafile | -| `metafile remove` | Remove a signatory or signatories, outputting a new metafile | - -```zsh title=Command -sh ../examples/multisig.sh keyfiles -``` - -The first part of the demo generates a vanity account for both Ace and Bee, via the `--vanity-prefix` argument, which mines an account having a matching authentication key prefix. Note also the use of the `--use-test-password` command to reduce password inputs for the demo process: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_ace_bee -``` - -Here, each keyfile's authentication key begins with the specified vanity prefix: - -```zsh title=Output -=== Generate vanity account for Ace === - - -Mining vanity address... -Using test password. -Keyfile now at ace.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Ace", - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a", - "authentication_key": "0xace34c150c214397f17f3374bb9bca9d56ae9ad80c5cc26e5e3104ba2e72132a", - "encrypted_private_key": "0x674141414141426a37753267476d4e49386b636d6577514b3172355f356c6c49426b545861715859667268646e343137337a4d524d52454f487a4766725078686d576834346b6344754231455338525a6d344b36692d684941376c7346326c7a33364a6f4a6b3472315f62564d424e54483062354737675275476d5a41315a6d33773044376863536a4c424b", - "salt": "0x0248e25cfe88b9f00bfb1948df6791f9" -} - - -=== Generate vanity account for Bee === - - -Mining vanity address... -Using test password. -Keyfile now at bee.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Bee", - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6", - "authentication_key": "0xbeea9f7d3365f1c95348b803297081458eb77babc4c059518e3453b398653349", - "encrypted_private_key": "0x674141414141426a377532674659654e366c34566e77457077705065626566583167697a66434c635138496e594875334b70586c37437034566f4d6d686943376937483255366c314f5a46674d4e5a6c3852442d7267796d4c345376443444645249572d4a497353796d2d78743451355a5f6a376e4a546e554e4277483978626a6f59515346755f73373750", - "salt": "0x16312e818976ccf60dae4006f0161c12" -} - -``` - -Next, Ace and Bee are incorporated into a 1-of-2 multisig via `metafile incorporate`: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_incorporate -``` - -```zsh title=Output -=== Incorporate Ace and Bee into 1-of-2 multisig === - - -Multisig metafile now at ace_and_bee.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Ace and Bee", - "address": null, - "threshold": 1, - "n_signatories": 2, - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e601", - "authentication_key": "0x9e6413fac20e0d493c78b6a7744d71c8ad772796e7dcd3f78bf5d647d6a31afe", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a", - "authentication_key": "0xace34c150c214397f17f3374bb9bca9d56ae9ad80c5cc26e5e3104ba2e72132a" - }, - { - "signatory": "Bee", - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6", - "authentication_key": "0xbeea9f7d3365f1c95348b803297081458eb77babc4c059518e3453b398653349" - } - ] -} -``` - -The `metafile threshold` command is used to increase the threshold to two signatures: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_threshold -``` - -```zsh title=Output -=== Increase threshold to two signatures === - - -Multisig metafile now at ace_and_bee_increased.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Ace and Bee increased", - "address": null, - "threshold": 2, - "n_signatories": 2, - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e602", - "authentication_key": "0x7a66bb589973c243e91251bdf26e43b47b7e0297e713ab48428d0b489b9618f8", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a", - "authentication_key": "0xace34c150c214397f17f3374bb9bca9d56ae9ad80c5cc26e5e3104ba2e72132a" - }, - { - "signatory": "Bee", - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6", - "authentication_key": "0xbeea9f7d3365f1c95348b803297081458eb77babc4c059518e3453b398653349" - } - ] -} -``` - -Now Cad and Dee have vanity accounts generated as well: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_cad_dee -``` - -```zsh title=Output -=== Generate vanity account for Cad === - - -Mining vanity address... -Using test password. -Keyfile now at cad.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Cad", - "public_key": "0x774ffbf31e70681a795a61d5c8e47fa05e5088925ffa27d7eeb8e16d8bd1d5bb", - "authentication_key": "0xcad97c90570bdecf8737d3317604291f6c4cdd6f4651924c79eded5c9c4d0da7", - "encrypted_private_key": "0x674141414141426a37753269346d665469474f3873507459687531424470516831675a6b4c4541595936444f4b42694e567a444f346a38457764536955745144424a7a7454535f594777425764373238414d527a43455f39444270727a767a4d70676c544236665141574141674a4d777a4c32543056357453474b34724765395254536a7a33456774656434", - "salt": "0xdef251c71a113c7ddbbafc2881f297ed" -} - - -=== Generate vanity account for Dee === - - -Mining vanity address... -Using test password. -Keyfile now at dee.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Dee", - "public_key": "0x159481f2929ba902f4640815ca27662843e2090438ea0db630e4addb150741a7", - "authentication_key": "0xdeee312ec51d2f30f4291fa3105d907237b2550afcb9e608192f1b44af5cd747", - "encrypted_private_key": "0x674141414141426a377532695a416d6335623373304a4c456165784a44655955414830456f5a78737a6e704165677072356d474332435467756c675a70343566372d32704b716e314d3744737456326375716133502d4a7647363758773152686270656a583033746775515758564f4e326c744361486c56345a4c4f466b7878556b55356b4b536e47636764", - "salt": "0x027b97dac9ab2f60f847e51dd71ddf35" -} - -``` - -Now Cad and Dee are appended to the first multisig metafile via `metafile append`: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_append -``` - -```zsh title=Output - -=== Append Cad and Dee to 3-of-4 multisig === - - -Multisig metafile now at cad_and_dee_added.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Cad and Dee added", - "address": null, - "threshold": 3, - "n_signatories": 4, - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6774ffbf31e70681a795a61d5c8e47fa05e5088925ffa27d7eeb8e16d8bd1d5bb159481f2929ba902f4640815ca27662843e2090438ea0db630e4addb150741a703", - "authentication_key": "0x2fc0693aed20883859cb9a03e25c31943267d91d6062992e56c251496d793ec9", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x198fed1db594fc9df0b926cef3a17471e394b627506a2bba37e71c7b7186898a", - "authentication_key": "0xace34c150c214397f17f3374bb9bca9d56ae9ad80c5cc26e5e3104ba2e72132a" - }, - { - "signatory": "Bee", - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6", - "authentication_key": "0xbeea9f7d3365f1c95348b803297081458eb77babc4c059518e3453b398653349" - }, - { - "signatory": "Cad", - "public_key": "0x774ffbf31e70681a795a61d5c8e47fa05e5088925ffa27d7eeb8e16d8bd1d5bb", - "authentication_key": "0xcad97c90570bdecf8737d3317604291f6c4cdd6f4651924c79eded5c9c4d0da7" - }, - { - "signatory": "Dee", - "public_key": "0x159481f2929ba902f4640815ca27662843e2090438ea0db630e4addb150741a7", - "authentication_key": "0xdeee312ec51d2f30f4291fa3105d907237b2550afcb9e608192f1b44af5cd747" - } - ] -} - -``` - -Finally, Ace and Dee are removed from the resultant multisig via `metafile remove` to produce another 1-of-2 multisig: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh metafiles_remove -``` - -```zsh title=Output - -=== Remove Ace and Dee for 1-of-2 multisig === - - -Multisig metafile now at ace_and_dee_removed.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Ace and Dee removed", - "address": null, - "threshold": 1, - "n_signatories": 2, - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6774ffbf31e70681a795a61d5c8e47fa05e5088925ffa27d7eeb8e16d8bd1d5bb01", - "authentication_key": "0xeef31014c0e711722bf1b652188d0829d71d27aa05cfe25e31bdc38a0ebc5ffd", - "signatories": [ - { - "signatory": "Bee", - "public_key": "0x7bf9cbad4386d95c239f0b2b186a3b970e0c9bd0914eaaec00756abf5ea675e6", - "authentication_key": "0xbeea9f7d3365f1c95348b803297081458eb77babc4c059518e3453b398653349" - }, - { - "signatory": "Cad", - "public_key": "0x774ffbf31e70681a795a61d5c8e47fa05e5088925ffa27d7eeb8e16d8bd1d5bb", - "authentication_key": "0xcad97c90570bdecf8737d3317604291f6c4cdd6f4651924c79eded5c9c4d0da7" - } - ] -} -``` - -Thus far all AMEE operations have been conducted off-chain, because the relevant keyfile and metafile operations have simply involved public keys, private keys, and authentication keys. - -As such, all multisig metafiles have `"address": null`, since an on-chain account address has not yet been linked with any of the multisig accounts. - -### Step 9.3 Authentication key rotation - -In this section, the authentication key for Ace's vanity account will be rotated to a 1-of-2 multisig including Ace and Bee, then to a 2-of-2 multisig, and finally back to Ace as a single signer. -Here the demo script uses devnet to automatically fund Ace's account from the faucet, but note that Bee's account does not need to be funded, because only her *signature* is required throughout operations. - -In general, authentication key rotation can be used to "convert" a single-signer account to a multisig account, to modify signatories or the threshold of a multisig account, and to convert a multisig account back to a single-signer account. - -| Command | Use | -|------------------------------|------------------------------------------------------------------| -| `rotate challenge propose` | Propose a rotation proof challenge | -| `rotate challenge sign` | Sign a rotation proof challenge | -| `rotate transaction propose` | Propose key rotation transaction for multisig account | -| `rotate transaction sign` | Sign key rotation transaction for multisig account | -| `rotate execute single` | Execute key rotation transaction from single-signer account | -| `rotate execute multisig` | Execute key rotation transaction from multisig account | - -:::tip -The next few demos use the Aptos devnet, which has historically been reset each Thursday. -Make sure devnet is live when you try running the examples! -::: - -```zsh title=Command -sh ../examples/multisig.sh rotate -``` - -First, generate a vanity account for Ace and Bee, funding Ace since his account will need to pay for authentication key rotation transactions: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_prep_accounts -``` - -Note that the `keyfile fund` command is used to wrap a call to the `aptos` CLI: - -
-Output - -```zsh -=== Generate vanity account for Ace === - - -Mining vanity address... -Using test password. -Keyfile now at ace.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "encrypted_private_key": "0x674141414141426a37762d5074594a4e397066647776426b59666a7043616a52736a51516f785279496359356e41336a646a6d4852652d5657534a5f554b4c774e4e716a713976416d7334423941526858493763614865444c735039685f47484a3530717557374e6e4e31794c6364625a347436747a4b4b4858576d4a4c384e6b386b556779553279586565", - "salt": "0x3b98be7c51cfd4aa511d2e7050c714af" -} - - -=== Generate vanity account for Bee === - - -Mining vanity address... -Using test password. -Keyfile now at bee.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3", - "encrypted_private_key": "0x674141414141426a37762d515752725870697532417937533431445a495779357934625f38624a7948536761326c3433543944484967756e5978483259615369446f394331493969567a6f54475767395930614c4a49537a4d74574f5042466e6533375143587a73517a3843373848576a626b47715a59754a587742616b6d6367455f554d79726b46625242", - "salt": "0x6b659b567324ce0883483240bfa77241" -} - - -=== Fund Ace on devnet === - - -Running aptos CLI command: aptos account fund-with-faucet --account 0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a --faucet-url https://faucet.devnet.aptoslabs.com --url https://fullnode.devnet.aptoslabs.com/v1 -New balance: 100000000 -``` - -
- -Next incorporate Ace and Bee into a multisig account, proposing a rotation proof challenge for rotation to the multisig account: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_convert_multisig -``` - -Here, since the multisig account has a threshold of 1, only Ace needs to sign the rotation proof challenge. -Then he can initiate the authentication key rotation transaction from his account: - -
-Output - -```zsh -=== Incorporate to 1-of-2 multisig === - - -Multisig metafile now at initial.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Initial", - "address": null, - "threshold": 1, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "authentication_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} - - -=== Propose rotation challenge for rotating to multisig === - - -Rotation proof challenge proposal now at initial.challenge_proposal: -{ - "filetype": "Rotation proof challenge proposal", - "description": "Initial", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "from_is_single_signer": true, - "to_is_single_signer": false, - "sequence_number": 0, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" -} - - -=== Have Ace sign challenge proposal === - - -Using test password. -Rotation proof challenge signature now at ace_initial.challenge_signature: -{ - "filetype": "Rotation proof challenge signature", - "description": "Ace initial", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Initial", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "from_is_single_signer": true, - "to_is_single_signer": false, - "sequence_number": 0, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x4e5fcde82936f9160c37234945e0dfb4ba8c4424242b4589e054136bcecc2c65f02f021fcd412a168825edd8d3ab69eb4dd2ccecba59328ffd6061af88a8af05" -} - - -=== Have Ace execute rotation from single-signer account === - - -Using test password. -Transaction successful: 0xc4e0c3e2b3d3d2195cbc98c068b0619f5bb0020af8db1cac375eab5efce3b1a4 -Updating address in multisig metafile. -Multisig metafile now at initial.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Initial", - "address": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "threshold": 1, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "authentication_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} -``` - -
- -Note that after the successful rotation transaction, the `"address"` field of the multisig metafile has been updated to the vanity address starting with `0xace...`. - -Now, propose a threshold increase to 2 signatories: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_increase_propose -``` - -In this case, Ace and Bee both need to sign the rotation proof challenge since the account is rotating to a 2-of-2 multisig: - -
-Output - -```zsh -=== Increase metafile threshold to two signatures === - - -Multisig metafile now at increased.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Increased", - "address": null, - "threshold": 2, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "authentication_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} - - -=== Propose rotation challenge for increasing threshold === - - -Rotation proof challenge proposal now at increase.challenge_proposal: -{ - "filetype": "Rotation proof challenge proposal", - "description": "Increase", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "from_is_single_signer": false, - "to_is_single_signer": false, - "sequence_number": 1, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" -} - - -=== Have Ace sign challenge proposal === - - -Using test password. -Rotation proof challenge signature now at ace_increase.challenge_signature: -{ - "filetype": "Rotation proof challenge signature", - "description": "Ace increase", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Increase", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "from_is_single_signer": false, - "to_is_single_signer": false, - "sequence_number": 1, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x9e889c195507116c757336398e549d47216fa15612b4d36d06d3c7ad4107f87e7745a21874c8a7da2e78b299669170f574254731ace5dd2f7b9263d322f7d60e" -} - - -=== Have Bee sign challenge proposal === - - -Using test password. -Rotation proof challenge signature now at bee_increase.challenge_signature: -{ - "filetype": "Rotation proof challenge signature", - "description": "Bee increase", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Increase", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "from_is_single_signer": false, - "to_is_single_signer": false, - "sequence_number": 1, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xd8e2c539b8004979c4091ae0318e8c3441629133e3158d9de25a6c74bd6fba0c442757f4390f8f2207af23043604bb87c59c209db680e6186e0b848fcea46a0c" -} -``` - -
- -Now that the rotation proof challenge has been signed, the rotation transaction can be proposed. -Note that even though Ace and Bee both needed to sign the challenge (since the account to rotate to requires two signatures), only one of them needs to sign the transaction proposal (since the account undergoing rotation is originally 1-of-2). -Here, only Bee signs the transaction proposal, then the transaction can be executed. - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_increase_execute -``` - -
-Output - -```zsh -=== Propose rotation transaction === - - -Rotation transaction proposal now at increase.rotation_transaction_proposal: -{ - "filetype": "Rotation transaction proposal", - "description": "Increase", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Increase", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "from_is_single_signer": false, - "to_is_single_signer": false, - "sequence_number": 1, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "challenge_from_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x9e889c195507116c757336398e549d47216fa15612b4d36d06d3c7ad4107f87e7745a21874c8a7da2e78b299669170f574254731ace5dd2f7b9263d322f7d60e" - } - ], - "challenge_to_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x9e889c195507116c757336398e549d47216fa15612b4d36d06d3c7ad4107f87e7745a21874c8a7da2e78b299669170f574254731ace5dd2f7b9263d322f7d60e" - }, - { - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xd8e2c539b8004979c4091ae0318e8c3441629133e3158d9de25a6c74bd6fba0c442757f4390f8f2207af23043604bb87c59c209db680e6186e0b848fcea46a0c" - } - ] -} - - -=== Have Bee only sign rotation transaction proposal === - - -Using test password. -Rotation transaction signature now at bee_increase.rotation_transaction_signature: -{ - "filetype": "Rotation transaction signature", - "description": "Bee increase", - "transaction_proposal": { - "filetype": "Rotation transaction proposal", - "description": "Increase", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Increase", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "from_is_single_signer": false, - "to_is_single_signer": false, - "sequence_number": 1, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "challenge_from_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x9e889c195507116c757336398e549d47216fa15612b4d36d06d3c7ad4107f87e7745a21874c8a7da2e78b299669170f574254731ace5dd2f7b9263d322f7d60e" - } - ], - "challenge_to_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0x9e889c195507116c757336398e549d47216fa15612b4d36d06d3c7ad4107f87e7745a21874c8a7da2e78b299669170f574254731ace5dd2f7b9263d322f7d60e" - }, - { - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xd8e2c539b8004979c4091ae0318e8c3441629133e3158d9de25a6c74bd6fba0c442757f4390f8f2207af23043604bb87c59c209db680e6186e0b848fcea46a0c" - } - ] - }, - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xdd38f37d861d6bba653040e661295747744b3bfa952d266cb114114f68b2ae5b46af25483c20ec5a70f4774f6bb05d74be193d17970bf5e06e1282392e76070c" -} - - -=== Submit rotation transaction === - - -Transaction successful: 0x6e4675bdd5b4873c2d26797b39d44e0244182d2d11a979212b4e3d3f570cd0e1 -Updating address in multisig metafile. -Multisig metafile now at initial.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Initial", - "address": null, - "threshold": 1, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b01", - "authentication_key": "0x4256f6a9293fd19642a5042c99dc772cac5afe6f4c1f5727794feb5aa324ac77", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} -Updating address in multisig metafile. -Multisig metafile now at increased.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Increased", - "address": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "threshold": 2, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "authentication_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} -``` - -
- -Note that the `"address"` field of `initial.multisig` has been set to `null`, and `increased.multisig` now reflects the vanity address starting with `0xace...`. - -Next, propose a rotation proof challenge for rotating the account back to have Ace as a single signer: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_convert_single_propose -``` - -Here, Ace and Bee both need to sign the proposal since the account undergoing rotation is a 2-of-2 multisig: - -
-Output - -```zsh -=== Propose rotation challenge for rotating back to Ace === - -Rotation proof challenge proposal now at return.challenge_proposal: -{ - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" -} - - -=== Have Ace sign challenge proposal === - - -Using test password. -Rotation proof challenge signature now at ace_return.challenge_signature: -{ - "filetype": "Rotation proof challenge signature", - "description": "Ace return", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" -} - - -=== Have Bee sign challenge proposal === - - -Using test password. -Rotation proof challenge signature now at bee_return.challenge_signature: -{ - "filetype": "Rotation proof challenge signature", - "description": "Bee return", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xdbc73adcce8e942e11a5ae0d4f9db57ce7055a279b9a436d5ad98a458ace0f27fb95b52569b5b8f290a21e23bfbe3d6c2717217c92d1cdeeb2d7d68aed41660c" -} -``` - -
- -Now that both challenge signatures are available, a transaction from the multisig account can be proposed and executed: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh rotate_convert_single_execute -``` - -In this case, both Ace and Bee have to sign the transaction since the account undergoing rotation starts off as a 2-of-2 multisig: - -
-Output - -```zsh -=== Propose rotation transaction === - - -Rotation transaction proposal now at return.rotation_transaction_proposal: -{ - "filetype": "Rotation transaction proposal", - "description": "Return", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "challenge_from_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - }, - { - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xdbc73adcce8e942e11a5ae0d4f9db57ce7055a279b9a436d5ad98a458ace0f27fb95b52569b5b8f290a21e23bfbe3d6c2717217c92d1cdeeb2d7d68aed41660c" - } - ], - "challenge_to_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - } - ] -} - - -=== Have Ace sign rotation transaction proposal === - - -Using test password. -Rotation transaction signature now at ace_return.rotation_transaction_signature: -{ - "filetype": "Rotation transaction signature", - "description": "Ace return", - "transaction_proposal": { - "filetype": "Rotation transaction proposal", - "description": "Return", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "challenge_from_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - }, - { - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xdbc73adcce8e942e11a5ae0d4f9db57ce7055a279b9a436d5ad98a458ace0f27fb95b52569b5b8f290a21e23bfbe3d6c2717217c92d1cdeeb2d7d68aed41660c" - } - ], - "challenge_to_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - } - ] - }, - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xc0fe90d7274bfc9b1bea0e941dbbf4a11e28eabbefdd61b95e2e43ae4e2083eefa08f64c69938be5d58c1701f7850f3a1b493a7bf486799aaeba520d95c7f80e" -} - - -=== Have Bee sign rotation transaction proposal === - - -Using test password. -Rotation transaction signature now at bee_return.rotation_transaction_signature: -{ - "filetype": "Rotation transaction signature", - "description": "Bee return", - "transaction_proposal": { - "filetype": "Rotation transaction proposal", - "description": "Return", - "challenge_proposal": { - "filetype": "Rotation proof challenge proposal", - "description": "Return", - "from_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "from_is_single_signer": false, - "to_is_single_signer": true, - "sequence_number": 2, - "originator": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a", - "current_auth_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "new_public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "chain_id": 44, - "expiry": "2030-01-01T00:00:00" - }, - "challenge_from_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - }, - { - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xdbc73adcce8e942e11a5ae0d4f9db57ce7055a279b9a436d5ad98a458ace0f27fb95b52569b5b8f290a21e23bfbe3d6c2717217c92d1cdeeb2d7d68aed41660c" - } - ], - "challenge_to_signatures": [ - { - "signatory": { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - "signature": "0xdb3e1c896703eedcbad0854ccbf5d87287c61885ea7490ed1f70560f23f9faf7a3278f04cf01ed9714236ab7e4fd0637889691dea197520cb28d5da0fbc4f401" - } - ] - }, - "signatory": { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - }, - "signature": "0xafec5c906b5800848f6bede2fc313cf2a7565d298d4fcb43c1bb31040a2e405ed7a0e2941ef0650d6efa30702f51b97a4c1e02b5584a4b1fc20d07136c28a70f" -} - - -=== Submit rotation transaction === - - -Transaction successful: 0x1c91d97ef2d9bfb9a09a0dbd1c34d272fa957d2468301d65e5e9d07068291373 -Updating address in multisig metafile. -Multisig metafile now at increased.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Increased", - "address": null, - "threshold": 2, - "n_signatories": 2, - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf75bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b02", - "authentication_key": "0x3894d1a4d7b3a59e6b86c4fff71d6531315199fdb873f87a5b9fe30cf3b50315", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0x6691a5a2bc421a3b3049614a30c506b1ce0ecbc2a780fb843bf5cfba2b386bf7", - "authentication_key": "0xace3e630afa569ce67bcb98de667d6a8323f02c4d5f77cead0cc41bedc172f1a" - }, - { - "signatory": "Bee", - "public_key": "0x5bb9f4793e76a2320aba7151706ff2ed79cb0a5a8254312dbdb15c042165e04b", - "authentication_key": "0xbeec0429e5e8afdd98d39fb5fbfcd608e438ea87d9d0dd1d5ba8fe23c2db21a3" - } - ] -} - -``` - -
- -Note that after the rotation, the metafile has been updated with `"address": null` - -In practice, note that the consensus mechanism will probably entail something like the following: - -1. Ace and Bee independently generate single-signer keyfiles. -2. One of them, for example Ace, acts as a "scribe", so Bee sends her keyfile to Ace. -3. Ace uses the `metafile incorporate` command to generate a multisig metafile, and sends a copy to Bee for her records. -4. Ace then uses the appropriate `metafile` and `rotate` subcommands to propose rotation proof challenges, rotation transactions, etc. (note that Bee's private key is encrypted so this is not a security threat). -5. Ace sends proposals over to Bee, then Bee signs them and sends her signature files back to Ace. -6. Ace signs locally, then executes transactions using his and Bee's signature files. - -Theoretically this can be scaled to as many as 32 independent signatories, but note that higher numbers of signatories introduce logistical complexities (e.g. sending signature files back and forth in a group chat, or running shell commands with 32 arguments). - -### Step 9.4 Protocol governance - -In this section AMEE will be used to [publish and upgrade the same `UpgradeAndGovern` package as above](#step-8-perform-move-package-governance), then to invoke a different governance script, all under the authority of a 1-of-2 multisig account: - -| Command | Use | -|------------------------------|------------------------------------------------------------------| -| `publish propose` | Propose Move package publication | -| `publish sign` | Sign a Move package publication proposal | -| `publish execute` | Execute Move package publication from proposal signature file(s) | -| `script propose` | Propose Move script invocation | -| `script sign` | Sign a Move script invocation proposal | -| `script execute` | Execute Move script invocation from proposal signature file(s) | - -```zsh title=Command -sh ../examples/multisig.sh govern -``` - -As before, this example begins with a vanity account for both Ace and Bee: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh govern_prep_accounts -``` - -
-Output - -```zsh -=== Generate vanity account for Ace === - - -Mining vanity address... -Using test password. -Keyfile now at ace.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe", - "encrypted_private_key": "0x674141414141426a394272644a6b4f7a66584d7a46764168397370784e6e694e3455634a51514b4b615159517034776941647a68675547684c76316f7a5045474958726635487444656f695859746a32646464487165446d69454a494a72424c4249306b58654e48384e5836342d42694c713642325769756772394946622d635a56563244694d456e504c66", - "salt": "0x8e1eab26663623afb580ddbc51df6827" -} - - -=== Generate vanity account for Bee === - - -Mining vanity address... -Using test password. -Keyfile now at bee.keyfile: -{ - "filetype": "Keyfile", - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b", - "encrypted_private_key": "0x674141414141426a3942726550316a324c757a456d556f35727248506e77466c58697a3041713742744c384b41567a4931654a384c586576504e5438654b347964394470374a665166384a675a5533566f5279436d596d61577a2d7a76786d356d4762682d6b50322d594e5832664642326e4456346e6b7a4c574f42467358424f78505848534f4d4e574345", - "salt": "0xdd3379cc341a5e32701cba37b48d2aa5" -} -``` - -
- -Ace and Bee are then incorporated in a multisig, which is funded on devnet. -Note here that neither Ace nor Bee need to be funded, since the multisig account is linked with an on-chain account through direct funding, rather than through authentication key rotation. -Here, the multisig account address is identical to its authentication key, so the devnet faucet can simply be used to fund the corresponding address. -On testnet or mainnet, this process would probably entail sending `APT` to the account in question. - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh govern_prep_multisig -``` - -Note that the multisig metafile has `"address": null` before but not after the faucet funding operation: - -
-Output - -```zsh -=== Incorporate to 1-of-2 multisig === - - -Multisig metafile now at protocol.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": null, - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] -} - - -=== Fund multisig === - - -Running aptos CLI command: aptos account fund-with-faucet --account 0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e --faucet-url https://faucet.devnet.aptoslabs.com --url https://fullnode.devnet.aptoslabs.com/v1 -New balance: 100000000 -Updating address in multisig metafile. -Multisig metafile now at protocol.multisig: -{ - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] -} -``` - -
- -Next a Move package publication proposal is constructed, signed, and the package is published. Here, only Ace's signature is necessary because the multisig threshold is 1: - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh govern_publish -``` - -Note that the publication proposal includes information required to download and publish the package from GitHub: - -* GitHub user -* GitHub project -* Commit -* Path to package's `Move.toml` inside the repository -* Named address to substitute inside `Move.toml` -* Sequence to publish modules in - -:::tip -Modules should be listed from the bottom of the dependency hierarchy up, with modules that are used listed before the modules that use them, and modules that declare friends listed before the friends they declare. -::: - -For this example, the `Move.toml` file in question is as follows: - -```toml title="Move.toml" -:!: static/move-examples/upgrade_and_govern/v1_0_0/Move.toml manifest -``` - -Here, `Move.toml` contains the named address `upgrade_and_govern`, which is defined generically as `_`: -AMEE expects a named address of this format, corresponding to the multisig account address to publish under. - -Note that the repository is downloaded and recompiled before signing, and before transaction execution. -This is to ensure that all signatories, as well as the transaction submitter, are referring to the same transaction payload (as defined by the GitHub information from the proposal file): - -
-Output - - -```zsh -=== Propose publication === - - -Publication proposal now at genesis.publication_proposal: -{ - "filetype": "Publication proposal", - "description": "Genesis", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_0_0/Move.toml", - "named_address": "upgrade_and_govern", - "module_sequence": [ - "parameters" - ], - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 0, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" -} - - -=== Sign publication proposal === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp4i9z7k4h. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp4i9z7k4h/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_0_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Using test password. -Publication signature now at genesis.publication_signature: -{ - "filetype": "Publication signature", - "description": "Genesis", - "transaction_proposal": { - "filetype": "Publication proposal", - "description": "Genesis", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_0_0/Move.toml", - "named_address": "upgrade_and_govern", - "module_sequence": [ - "parameters" - ], - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 0, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - "signature": "0xff4a53e80ea1ab58c33284df07a601bdd21082cf2106804a4176c351203b973c03b2530a1a0224fa415bddebfd7b576fe7bc294284a031f041cb37718fcda90c" -} - - -=== Execute publication === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmpi7mexcok. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmpi7mexcok/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_0_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Transaction successful: 0x54a594684829b5c7d84c1b5756ac0b5bd62e5e35a6747cf617bc415a1be5104a -``` - -
- -Next, the package is upgraded to `v1.1.0`, which involves the same workflow albeit with a different manifest path and a new module to publish (`transfer.move` uses `parameters.move`, so it is listed second): - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh govern_upgrade -``` - -
-Output - -```zsh -=== Propose upgrade === - - -Publication proposal now at upgrade.publication_proposal: -{ - "filetype": "Publication proposal", - "description": "Upgrade", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml", - "named_address": "upgrade_and_govern", - "module_sequence": [ - "parameters", - "transfer" - ], - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 1, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" -} - - -=== Sign upgrade proposal === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmphpou29jf. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmphpou29jf/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_1_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Using test password. -Publication signature now at upgrade.publication_signature: -{ - "filetype": "Publication signature", - "description": "Upgrade", - "transaction_proposal": { - "filetype": "Publication proposal", - "description": "Upgrade", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml", - "named_address": "upgrade_and_govern", - "module_sequence": [ - "parameters", - "transfer" - ], - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 1, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - "signature": "0x999fe7b09ea10268c0178b3b20c8d23b6d12cdb1c0b7886ba7bcee200dc83a0472fe77c7f802e0cd36061fbb3258c73133622f4528ed0f1d242b7272156d1306" -} - - -=== Execute upgrade === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmpf2_geeeq. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmpf2_geeeq/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_1_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Transaction successful: 0x6aa9c7be0f42146d4c33257d7a82d913360b9f345d2247ee5ffb30ebeea81114 -``` - -
- -Lastly, the `set_only.move` governance script is invoked from the multisig account: - -```rust title=set_only.move -:!: static/move-examples/upgrade_and_govern/v1_1_0/scripts/set_only.move script -``` - -Note here that the main function in this script, `set_only`, accepts only a `&signer` as an argument, with constants like `PARAMETER_1` and `PARAMETER_2` defined inside the script. -AMEE expects scripts of this format, having only a single `&signer` argument in the main function call, such that all inner function arguments other than the governance signature can be easily inspected on GitHub. - -```zsh title="multisig.sh snippet" -:!: static/sdks/python/examples/multisig.sh govern_script -``` - -Note here that a script proposal is similar in form to a publication proposal, except for an additional `script_name` field (which specifies the name of the main function call), and no `module_sequence` field. -Similarly, the Move script in question is downloaded and recompiled during signing and submission, to ensure the same transaction payload: - -
-Output - -```zsh -=== Propose script invocation === - - -Script proposal now at invoke.script_proposal: -{ - "filetype": "Script proposal", - "description": "Invoke", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml", - "named_address": "upgrade_and_govern", - "script_name": "set_only", - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 2, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" -} - - -=== Sign invocation proposal === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp45hu664y. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp45hu664y/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_1_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Using test password. -Script signature now at invoke.script_signature: -{ - "filetype": "Script signature", - "description": "Invoke", - "transaction_proposal": { - "filetype": "Script proposal", - "description": "Invoke", - "github_user": "alnoki", - "github_project": "aptos-core", - "commit": "1c26076f5f", - "manifest_path": "aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml", - "named_address": "upgrade_and_govern", - "script_name": "set_only", - "multisig": { - "filetype": "Multisig metafile", - "multisig_name": "Protocol", - "address": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "threshold": 1, - "n_signatories": 2, - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4b1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e5601", - "authentication_key": "0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e", - "signatories": [ - { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - { - "signatory": "Bee", - "public_key": "0xb1966fd2d4d17c7963d485ac817b8a931b5be64e96ec65d5a6b575e6ff037e56", - "authentication_key": "0xbeec3b1787e9fcc0362fe28ea2c8c7e98b42ab9355e95fb440612d629756903b" - } - ] - }, - "sequence_number": 2, - "chain_id": 44, - "expiry": "2030-12-31T00:00:00" - }, - "signatory": { - "signatory": "Ace", - "public_key": "0xd956242c23a2a98a135e5685cc041b47b79866105d2cc91a507051a283fefae4", - "authentication_key": "0xaceb4c8b33e42978f775f3b95207a500b4f6a6866fa449f9c4bed3a70f2baabe" - }, - "signature": "0x2621d89dce35d188fde2f8cae70f80bac01a8d0c5de5230477003e6b39113122d56cf217a71b2b92292e26a23a2a8f8a80cc3d4660292eaa6cefce0bbc29b604" -} - - -=== Execute script invocation === - - -Extracting https://github.com/alnoki/aptos-core/archive/1c26076f5f.zip to temporary directory /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp7wigfph5. -Running aptos CLI command: aptos move compile --save-metadata --included-artifacts none --package-dir /var/folders/4c/rtts9qpj3yq0f5_f_gbl6cn40000gn/T/tmp7wigfph5/aptos-core-1c26076f5f29f3e554393df6f6fb4851422755b9/aptos-move/move-examples/upgrade_and_govern/v1_1_0 --named-addresses upgrade_and_govern=0x2ab4d591c6d9a56c80fd3efecc8dbf2b6e13d64e1b2f1c1ab5eeb9f691c7da6e - -Compiling, may take a little while to download git dependencies... -INCLUDING DEPENDENCY AptosFramework -INCLUDING DEPENDENCY AptosStdlib -INCLUDING DEPENDENCY MoveStdlib -BUILDING UpgradeAndGovern -Transaction successful: 0x75c783e1ed49539d1d6681ba0c5baf931f49958e0635622eca68fbe66badbc54 -``` - -
- -Again, in practice note that the consensus mechanism will probably entail something like the following, in the case of a 2-of-2 multisig (unlike a 1-of-2 in the above example): - -1. Ace and Bee independently generate single-signer keyfiles. -2. One of them, for example Bee, acts as a "scribe", so Ace sends his keyfile to Bee. -3. Bee uses the `metafile incorporate` command to generate a multisig metafile, and sends a copy to Ace for his records. -4. Bee then uses the appropriate `publish` and `script` subcommands to propose package publications, package upgrades, and script invocations from the multisig account. -5. Bee sends proposals over to Ace, then Ace reviews the corresponding package on GitHub before signing and sending a signature files back to Bee. -6. Bee signs locally, then executes transactions using her and Ace's signature files. - -Theoretically this can be scaled to as many as 32 independent signatories, but note that higher numbers of signatories introduce logistical complexities (e.g. sending signature files back and forth in a group chat, or running shell commands with 32 arguments). - --- Congratulations on completing the tutorial on K-of-N multi-signer authentication operations! diff --git a/developer-docs-site/scripts/additional_dict.txt b/developer-docs-site/scripts/additional_dict.txt index 3e75d2fc90ea0..fbe526defc21c 100644 --- a/developer-docs-site/scripts/additional_dict.txt +++ b/developer-docs-site/scripts/additional_dict.txt @@ -3,7 +3,6 @@ ABIs ACK AIP AIT -AMEE AN ANs API @@ -124,7 +123,6 @@ Integrators JPG JSON Jetbrains -Keyfiles Kubernetes kubernetes LLVM @@ -136,7 +134,6 @@ Mainnet Mainnnet ManagedCoin Merkle -Metafiles MiB Modularity Monterey @@ -317,9 +314,6 @@ IPFS isConnected json jsx -keyfile -keyfile's -keyfiles kickstart korean leaderboard @@ -337,8 +331,6 @@ mdash mempool mempools merkle -metafile -metafiles monorepo multisig namespace diff --git a/ecosystem/python/sdk/aptos_sdk/amee.py b/ecosystem/python/sdk/aptos_sdk/amee.py deleted file mode 100644 index 47dfcee49e1b8..0000000000000 --- a/ecosystem/python/sdk/aptos_sdk/amee.py +++ /dev/null @@ -1,2084 +0,0 @@ -"""Aptos Multisig Execution Expeditor (AMEE). - -See "Your First Multisig" tutorial. -""" - -import argparse -import base64 -import getpass -import json -import secrets -import subprocess -from contextlib import contextmanager -from datetime import datetime -from io import BytesIO, TextIOWrapper -from pathlib import Path -from tempfile import TemporaryDirectory -from typing import Any, Callable, Dict, List -from typing import Optional as Option -from typing import Tuple, Union -from zipfile import ZipFile - -import requests -import toml -from aptos_sdk.account import Account, RotationProofChallenge -from aptos_sdk.account_address import AccountAddress -from aptos_sdk.authenticator import (Authenticator, Ed25519Authenticator, - MultiEd25519Authenticator) -from aptos_sdk.bcs import Serializer -from aptos_sdk.client import ClientConfig, RestClient -from aptos_sdk.ed25519 import (MultiEd25519PublicKey, MultiEd25519Signature, - PublicKey, Signature) -from aptos_sdk.transactions import (EntryFunction, RawTransaction, Script, - SignedTransaction, TransactionArgument, - TransactionPayload) -from cryptography.exceptions import InvalidSignature -from cryptography.fernet import Fernet, InvalidToken -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC -from nacl.signing import VerifyKey - -# Constants >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -MAX_SIGNATORIES = 32 -"""Maximum number of signatories on a multisig account.""" - -MIN_PASSWORD_LENGTH = 4 -"""The minimum password length.""" - -MIN_SIGNATORIES = 2 -"""Minimum number of signatories on a multisig account.""" - -MIN_THRESHOLD = 1 -"""Minimum number of signatures required to for multisig transaction.""" - -NETWORK_URLS = { - "devnet": "https://fullnode.devnet.aptoslabs.com/v1", - "testnet": "https://fullnode.testnet.aptoslabs.com/v1", - "mainnet": "https://fullnode.mainnet.aptoslabs.com/v1", -} -"""Map from network name to API node URL.""" - -FAUCET_URL = "https://faucet.devnet.aptoslabs.com" -"""Devnet faucet URL.""" - -TEST_PASSWORD = "Aptos" -"""Test password for bypassing prompts.""" - -# Constants <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Aptos accounts >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def fund_address_from_faucet(address: str): - """Fund an account address using devnet faucet.""" - command = ( # Construct aptos CLI command. - f"aptos account fund-with-faucet --account {address} " - f"--faucet-url {FAUCET_URL} --url {NETWORK_URLS['devnet']}" - ) - # Print command to run. - print(f"Running aptos CLI command: {command}") - # Run command. - subprocess.run(command.split(), stdout=subprocess.PIPE, check=True) - balance = RestClient(NETWORK_URLS["devnet"]).account_balance( - AccountAddress(prefixed_hex_to_bytes(address)) - ) # Check balance. - assert balance != 0, "Funding failed." - print(f"New balance: {balance}") # Print user feedback. - - -def get_sequence_number(address: bytes, network: str) -> int: - """Return sequence number of account having address for network.""" - client = RestClient(NETWORK_URLS[network]) # Get network client. - # Return account sequence number. - return client.account_sequence_number(AccountAddress(address)) - - -# Aptos accounts <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# String operations >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def bytes_to_prefixed_hex(input_bytes: bytes) -> str: - """Convert bytes to hex string with 0x prefix.""" - return f"0x{input_bytes.hex()}" - - -def check_name(tokens: List[str]) -> str: - """Check list of tokens for valid name, return concatenated str.""" - name = " ".join(tokens) # Get name. - # Assert that name is not blank space. - assert len(name) != 0 and not name.isspace(), "Name may not be blank." - return name # Return name. - - -def get_github_zip_archive_url(user: str, project: str, commit: str) -> str: - """Return GitHub URL of a repository zip archive.""" - return f"https://github.com/{user}/{project}/archive/{commit}.zip" - - -def prefixed_hex_to_bytes(prefixed_hex: str) -> bytes: - """Convert hex string with 0x prefix to bytes.""" - return bytes.fromhex(prefixed_hex[2:]) - - -# String operations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# File operations >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def check_outfile_exists(path: Path): - """Verify desired outfile does not already exist.""" - assert not path.exists(), f"{path} already exists." - - -def get_file_path( - optional_path: Option[Path], name_tokens: List[str], extension: str -) -> Path: - """If no path provided, generate one from tokens and extension.""" - if optional_path is not None: # If optional path provided: - return optional_path # Use it as the path. - # Otherwise return a new path from tokens and extension. - return Path("_".join(name_tokens).casefold() + "." + extension) - - -def write_json_file(path: Path, data: Dict[str, str], check_if_exists: bool): - """Write JSON data to path, printing contents of new file and - optionally checking if the file already exists.""" - if check_if_exists: - check_outfile_exists(path) # Check if file exists. - # With file open for writing: - with open(path, "w", encoding="utf-8") as file: - # Dump JSON data to file. - json.dump(data, file, indent=4) - filetype = data["filetype"] # Get file type from data. - # With file open for reading: - with open(path, "r", encoding="utf-8") as file: - # Print contents of file. - print(f"{filetype} now at {path}: \n{file.read()}") - - -# File operations <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Password protection >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def check_keyfile_password( - path: Path, - use_test_password: bool, -) -> Tuple[Dict[Any, Any], Option[bytes]]: - """Check keyfile password, returning JSON data/private key bytes.""" - with open(path, "r", encoding="utf-8") as keyfile: # Open keyfile: - data = json.load(keyfile) # Load JSON data from keyfile. - salt = prefixed_hex_to_bytes(data["salt"]) # Get salt bytes. - encrypted_hex = data["encrypted_private_key"] # Get encrypted key. - # Convert encrypted private key hex to bytes. - encrypted_private_key = prefixed_hex_to_bytes(encrypted_hex) - if use_test_password: # If using test password: - print("Using test password.") # Print user notice. - password = TEST_PASSWORD # Set password to test password. - else: # Otherwise: - # Define password input prompt. - prompt = "Enter password for encrypted private key: " - password = getpass.getpass(prompt) # Get keyfile password. - # Generate Fernet encryption assistant from password and salt. - fernet = derive_password_protection_fernet(password, salt) - try: # Try decrypting private key. - private_key = fernet.decrypt(encrypted_private_key) - # If exception from attempting to decrypt private key: - except (InvalidSignature, InvalidToken): - print("Invalid password.") # Inform user. - private_key = None # Set private key to none. - return data, private_key # Return JSON data, private key. - - -def check_password_length(password: str): - """Verify password meets minimum length threshold.""" - assert ( - len(password) >= MIN_PASSWORD_LENGTH - ), f"Password should be at least {MIN_PASSWORD_LENGTH} characters." - - -def derive_password_protection_fernet(password: str, salt: bytes) -> Fernet: - """Derive Fernet encryption key assistant from password and salt. - - For password-protecting a private key on disk. - - References - ---------- - https://cryptography.io/en/latest/fernet - https://stackoverflow.com/a/55147077 (See "Fernet with password") - """ - key_derivation_function = PBKDF2HMAC( - algorithm=hashes.SHA256(), length=32, salt=salt, iterations=480_000 - ) # Create key derivation function from salt. - # Derive key from password. - derived_key = key_derivation_function.derive(password.encode()) - # Return Fernet encryption assistant. - return Fernet(base64.urlsafe_b64encode(derived_key)) - - -def encrypt_private_key( - private_key_bytes: bytes, - use_test_password: bool, -) -> Tuple[bytes, bytes]: - """Return encrypted private key and salt.""" - if use_test_password: # If using test password: - print("Using test password.") # Print user notice. - password = TEST_PASSWORD # Set password to test password. - else: # Otherwise: - # Define new password prompt. - message = "Enter new password for encrypting private key: " - password = getpass.getpass(message) # Get keyfile password. - check_password_length(password) # Check password length. - # Have user re-enter password. - check = getpass.getpass("Re-enter password: ") - # Assert passwords match. - assert password == check, "Passwords do not match." - salt = secrets.token_bytes(16) # Generate encryption salt. - # Generate Fernet encryption assistant from password and salt. - fernet = derive_password_protection_fernet(password, salt) - # Encrypt private key. - encrypted_private_key = fernet.encrypt(private_key_bytes) - return encrypted_private_key, salt # Return key, salt. - - -# Password protection <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Multisig metafiles >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def metafile_check_update( - metafile_json: Dict[Any, Any], - name_tokens: List[str], - threshold: int, - keyfiles: Option[List[TextIOWrapper]], - outfile: Path, -): - """Check multisig metafile data and update fields as needed for - inputs, including optional keyfiles for signatories to append.""" - # Get signatories list. - signatories = metafile_json["signatories"] - # Get signatory names list. - signatory_names = [signatory["signatory"] for signatory in signatories] - public_keys = [ # Get signatory public keys list. - PublicKey(VerifyKey(prefixed_hex_to_bytes(signatory["public_key"]))) - for signatory in signatories - ] - if keyfiles is not None: # If keyfiles to append: - for keyfile in keyfiles: # Loop over keyfiles. - signatory = json.load(keyfile) # Load signatory data. - # Get signatory name. - signatory_name = signatory["signatory"] - assert ( # Assert signatory name not reused. - not signatory_name in signatory_names - ), f"{signatory_name} already in multisig." - signatory_names.append(signatory_name) # Append name. - # Get signatory's public key as bytes. - public_key_bytes = prefixed_hex_to_bytes(signatory["public_key"]) - # Append public key to list of public keys. - public_keys.append(PublicKey(VerifyKey(public_key_bytes))) - # Append signatory public data to list of signatories. - signatories.append(get_public_signatory_fields(signatory)) - # Get new number of signatories on multisig. - n_signatories = len(signatories) - # Check number of signatories and threshold. - check_signatories_threshold(n_signatories, threshold) - # Initialize multisig public key. - multisig_public_key = MultiEd25519PublicKey(public_keys, threshold) - # Get public key as prefixed hex. - public_key_hex = bytes_to_prefixed_hex(multisig_public_key.to_bytes()) - # Get authentication key as prefixed hex. - auth_key_hex = bytes_to_prefixed_hex(multisig_public_key.auth_key()) - write_json_file( # Write JSON to multisig metafile outfile. - path=get_file_path(outfile, name_tokens, "multisig"), - data={ - "filetype": "Multisig metafile", - "multisig_name": check_name(name_tokens), - "address": None, - "threshold": threshold, - "n_signatories": n_signatories, - "public_key": public_key_hex, - "authentication_key": auth_key_hex, - "signatories": signatories, - }, - check_if_exists=True, - ) - - -def metafile_to_multisig_public_key(path: Path) -> MultiEd25519PublicKey: - """Get multisig public key instance from metafile at path.""" - # With metafile open: - with open(path, encoding="utf-8") as metafile: - data = json.load(metafile) # Load JSON data. - keys = [] # Init empty public keys list. - for signatory in data["signatories"]: # Loop over signatories: - # Get public key bytes. - public_key_bytes = prefixed_hex_to_bytes(signatory["public_key"]) - # Append public key to list - keys.append(PublicKey(VerifyKey(public_key_bytes))) - # Return multisig public key instance. - return MultiEd25519PublicKey(keys, data["threshold"]) - - -def update_multisig_address(path: Path, address_prefixed_hex: str): - """Update the address for a multisig metafile.""" - print("Updating address in multisig metafile.") - # With multisig metafile open: - with open(path, "r", encoding="utf-8") as metafile: - data = json.load(metafile) # Load JSON data from metafile. - # Update address field. - data["address"] = address_prefixed_hex - # Overwrite JSON data in file. - write_json_file(path=path, data=data, check_if_exists=False) - - -# Multisig metafiles <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Authentication key rotation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def construct_raw_rotation_transaction( - from_scheme: int, - from_public_key_bytes: bytes, - to_scheme: int, - to_public_key_bytes: bytes, - cap_rotate_key: bytes, - cap_update_table: bytes, - sender_prefixed_hex: str, - sequence_number: int, - expiry: datetime, - chain_id: int, -) -> RawTransaction: - """Return a raw authentication key rotation transaction.""" - payload = EntryFunction.natural( - module="0x1::account", - function="rotate_authentication_key", - ty_args=[], - args=[ - TransactionArgument(from_scheme, Serializer.u8), - TransactionArgument(from_public_key_bytes, Serializer.to_bytes), - TransactionArgument(to_scheme, Serializer.u8), - TransactionArgument(to_public_key_bytes, Serializer.to_bytes), - TransactionArgument(cap_rotate_key, Serializer.to_bytes), - TransactionArgument(cap_update_table, Serializer.to_bytes), - ], - ) # Construct entry function payload. - return construct_raw_transaction( # Return raw transaction. - sender_prefixed_hex=sender_prefixed_hex, - sequence_number=sequence_number, - payload=payload, - expiry=expiry, - chain_id=chain_id, - ) - - -def extract_challenge_proposal_data( - signature_files: List[TextIOWrapper], - proposal: Option[Dict[str, Any]], - signatures_manifest=List[Dict[str, Any]], -) -> Dict[str, Any]: - """Extract from signature files challenge proposal data and append - to ongoing signatures manifest.""" - for file in signature_files: # Loop over signature files. - signature_data = json.load(file) # Load data for file. - if proposal is None: # If challenge proposal undefined: - # Initialize it to that from first signature file. - proposal = signature_data["challenge_proposal"] - else: # If challenge proposal already defined: - assert ( # Assert it is same across all signature files. - signature_data["challenge_proposal"] == proposal - ), "Signature proposal mismatch." - signatures_manifest.append( - { # Append signature data. - "signatory": signature_data["signatory"], - "signature": signature_data["signature"], - } - ) - return proposal # Return proposal. - - -def get_rotation_challenge_bcs(proposal_data: Dict[str, str]) -> bytes: - """Convert challenge proposal data map to BCS serialization.""" - # Get proposal fields as bytes. - (originator_address_bytes, current_auth_key_bytes, new_pubkey_bytes) = ( - prefixed_hex_to_bytes(proposal_data["originator"]), - prefixed_hex_to_bytes(proposal_data["current_auth_key"]), - prefixed_hex_to_bytes(proposal_data["new_public_key"]), - ) - rotation_proof_challenge = RotationProofChallenge( - sequence_number=int(proposal_data["sequence_number"]), - originator=AccountAddress(originator_address_bytes), - current_auth_key=AccountAddress(current_auth_key_bytes), - new_public_key=new_pubkey_bytes, - ) # Declare a rotation proof challenge. - serializer = Serializer() # Init BCS serializer. - # Serialize rotation proof challenge. - rotation_proof_challenge.serialize(serializer) - return serializer.output() # Return BCS. - - -def get_rotation_transaction(proposal: Dict[str, Any]) -> RawTransaction: - """Convert a multisig authentication key rotation transaction to a - raw transaction""" - # Get rotation proof challenge proposal. - challenge_proposal = proposal["challenge_proposal"] - from_public_key_bytes = prefixed_hex_to_bytes( - challenge_proposal["from_public_key"] - ) # Get from public key bytes. - cap_rotate_key = MultiEd25519Signature( - MultiEd25519PublicKey.from_bytes(from_public_key_bytes), - signature_json_to_map(proposal["challenge_from_signatures"]), - ).to_bytes() # Get key rotation capability signature. - to_public_key_bytes = prefixed_hex_to_bytes( - challenge_proposal["new_public_key"] - ) # Get public key bytes for to account. - # If account to rotate to is a single signer: - if challenge_proposal["to_is_single_signer"]: - to_scheme = Authenticator.ED25519 # Scheme is single-signer. - cap_update_table = prefixed_hex_to_bytes( - proposal["challenge_to_signatures"][0]["signature"] - ) # Update table capability signature is only one provided. - else: # If account to rotate to is a multisig: - to_scheme = Authenticator.MULTI_ED25519 # Scheme is multisig. - cap_update_table = MultiEd25519Signature( - MultiEd25519PublicKey.from_bytes(to_public_key_bytes), - signature_json_to_map(proposal["challenge_to_signatures"]), - ).to_bytes() # Get table update capability signature. - return construct_raw_rotation_transaction( - from_scheme=Authenticator.MULTI_ED25519, - from_public_key_bytes=from_public_key_bytes, - to_scheme=to_scheme, - to_public_key_bytes=to_public_key_bytes, - cap_rotate_key=cap_rotate_key, - cap_update_table=cap_update_table, - sender_prefixed_hex=challenge_proposal["originator"], - sequence_number=challenge_proposal["sequence_number"], - expiry=datetime.fromisoformat(challenge_proposal["expiry"]), - chain_id=challenge_proposal["chain_id"], - ) # Construct raw rotation transaction. - - -# Authentication key rotation <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Transaction construction >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def construct_raw_transaction( - sender_prefixed_hex: str, - sequence_number: int, - payload: Dict[str, Any], - expiry: datetime, - chain_id: int, -) -> RawTransaction: - """Return a raw transaction for given payload and metadata, using - default gas config values.""" - return RawTransaction( # Return raw transaction. - sender=AccountAddress(prefixed_hex_to_bytes(sender_prefixed_hex)), - sequence_number=sequence_number, - payload=TransactionPayload(payload), - max_gas_amount=ClientConfig.max_gas_amount, - gas_unit_price=ClientConfig.gas_unit_price, - expiration_timestamps_secs=int(expiry.timestamp()), - chain_id=chain_id, - ) - - -@contextmanager -def download_and_compile(proposal: Dict[str, Any]): - """Download from GitHub and compile in a temporary directory the - package specified in a transaction proposal, yielding the package's - build path.""" - zip_url = get_github_zip_archive_url( - user=proposal["github_user"], - project=proposal["github_project"], - commit=proposal["commit"], - ) # Get URL for ZIP archive of project. - # Request to download Git ZIP archive. - response = requests.get(url=zip_url, stream=True) - # Assert successful response. - assert response.ok, f"Repo download failure: {response.text}" - with TemporaryDirectory() as temp_dir: # For temporary directory: - # Print ZIP file extraction notice. - print(f"Extracting {zip_url} to temporary directory {temp_dir}.") - # Extract ZIP file contents to temp dir. - ZipFile(BytesIO(response.content)).extractall(path=temp_dir) - # Get unzipped project directory, the only element in temp dir. - project_dir = Path(list(Path(temp_dir).glob("*"))[0]) - # Get manifest path. - manifest_path = project_dir / Path(proposal["manifest_path"]) - # With manifest file open: - with open(manifest_path, mode="r", encoding="utf-8") as manifest: - manifest_data = toml.load(manifest) # Load manifest data. - # Get package name from manifest. - package_name = manifest_data["package"]["name"] - # Get multisig address. - multisig_address = proposal["multisig"]["address"] - # Get named address for build command. - named_address = proposal["named_address"] - command = ( # Get aptos CLI build command. - f"aptos move compile --save-metadata --included-artifacts none " - f"--package-dir {manifest_path.parent} " - f"--named-addresses {named_address}={multisig_address}" - ) - # Print aptos CLI build command to run. - print(f"Running aptos CLI command: {command}\n") - # Run aptos CLI build command. - subprocess.run(command.split(), stdout=subprocess.PIPE, check=True) - # Get path for package build files. - build_path = manifest_path.parent / Path("build") / Path(package_name) - yield build_path # Yield build path. - - -def get_proposal_transaction( - payload: Union[EntryFunction, Script], - proposal: Dict[str, Any], -) -> RawTransaction: - """Return raw transaction for a payload derived from a transaction - proposal. - - Does not support rotation transaction proposals.""" - return construct_raw_transaction( # Return raw transaction. - sender_prefixed_hex=proposal["multisig"]["address"], - sequence_number=proposal["sequence_number"], - payload=payload, - expiry=datetime.fromisoformat(proposal["expiry"]), - chain_id=proposal["chain_id"], - ) - - -def get_publication_transaction(proposal: Dict[str, Any]) -> RawTransaction: - """Convert a multisig publication transaction proposal to a raw - transaction.""" - # Download and compile package from proposal, get build path: - with download_and_compile(proposal) as build_path: - # Open package metadata build file: - with open(build_path / Path("package-metadata.bcs"), "rb") as file: - package_metadata = file.read() # Read in contents. - # Get bytecode modules path. - modules_path = build_path / Path("bytecode_modules") - # Get list of bytecode module paths. - module_paths = [m for m in modules_path.iterdir() if m.is_file()] - module_paths.sort( - key=lambda path: proposal["module_sequence"].index(path.stem) - ) # Sort module paths according to proposal's module sequence. - modules = [] # Initialize empty modules list. - for module_path in module_paths: # Loop over module paths: - with open(module_path, "rb") as module: # With module open: - modules.append(module.read()) # Extract bytecode. - payload = EntryFunction.natural( # Construct payload. - module="0x1::code", - function="publish_package_txn", - ty_args=[], - args=[ - TransactionArgument(package_metadata, Serializer.to_bytes), - TransactionArgument( - modules, - Serializer.sequence_serializer(Serializer.to_bytes), - ), - ], - ) - # Return raw transaction for proposal payload. - return get_proposal_transaction(payload, proposal) - - -def get_script_transaction(proposal: Dict[str, Any]) -> RawTransaction: - """Convert a script invocation transaction proposal to a raw - transaction.""" - # Download and compile package from proposal, get build path: - with download_and_compile(proposal) as build_path: - script_path = build_path / Path( - f"bytecode_scripts/{proposal['script_name']}.mv" - ) # Get path of script bytecode. - # With script bytecode file open: - with open(script_path, "rb") as file: - script_code = file.read() # Read in contents. - # Construct script payload. - payload = Script(code=script_code, ty_args=[], args=[]) - # Return raw transaction for proposal payload. - return get_proposal_transaction(payload, proposal) - - -# Transaction construction <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Transaction signing >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def check_signatories_threshold(n_signatories: int, threshold: int): - """Verify the number of signatories and threshold on a multisig.""" - assert MIN_SIGNATORIES <= n_signatories <= MAX_SIGNATORIES, ( - f"Number of signatories must be between {MIN_SIGNATORIES} and " - f"{MAX_SIGNATORIES} (inclusive)." - ) # Assert valid number of signatories. - assert MIN_THRESHOLD <= threshold <= n_signatories, ( - f"Signature threshold must be greater than {MIN_THRESHOLD} and less " - f"than the number of signatories." - ) # Assert valid signature threshold. - - -def get_public_signatory_fields(data: Dict[str, Any]) -> Dict[str, Any]: - """Extract public fields from signatory keyfile JSON data.""" - return dict( - (field, data[field]) - for field in ["signatory", "public_key", "authentication_key"] - ) - - -def index_proposal_signatures( - signature_files: List[TextIOWrapper], proposal_type: str -) -> Tuple[List[Tuple[PublicKey, Signature]], Dict[str, Any]]: - """Index a list of proposal signatures into a multisig signature - map, extracting the proposal.""" - # Initialize signature map for multisig signature. - signature_map = [] - proposal = None # Initialize proposal. - for file in signature_files: # Loop over signature files: - signature_data = json.load(file) # Load data for file. - if proposal is None: # If proposal undefined: - # Initialize it to that from first signature file. - proposal = signature_data[proposal_type] - else: # If proposal already defined: - assert ( # Assert it is same across all signature files. - signature_data[proposal_type] == proposal - ), "Signature proposal mismatch." - # Get public key hex for signatory. - public_key_hex = signature_data["signatory"]["public_key"] - # Get public key class instance. - pubkey = PublicKey(VerifyKey(prefixed_hex_to_bytes(public_key_hex))) - # Get signature. - sig = Signature(prefixed_hex_to_bytes(signature_data["signature"])) - # Append public key and signature to signatures map. - signature_map.append((pubkey, sig)) - # Return signature map and proposal. - return signature_map, proposal - - -def sign_raw_transaction( - keyfile: Path, - raw_transaction: RawTransaction, - optional_outfile_path: Option[Path], - name_tokens: List[str], - proposal: Dict[str, Any], - filetype: str, - use_test_password: bool, -): - """Sign a raw transaction and store in an outfile.""" - keyfile_data, private_key_bytes = check_keyfile_password( - keyfile, use_test_password - ) # Check password, get keyfile data and private key bytes. - if private_key_bytes is None: # If can't decrypt private key: - return # Return. - # Create Aptos-style account for single signer. - account = Account.load_key(bytes_to_prefixed_hex(private_key_bytes)) - # Sign raw transaction. - signature = account.sign(raw_transaction.keyed()) - write_json_file( # Write JSON to signature file. - path=get_file_path( - optional_path=optional_outfile_path, - name_tokens=name_tokens, - extension="_".join(filetype.split()).casefold(), - ), - data={ - "filetype": filetype, - "description": check_name(name_tokens), - "transaction_proposal": proposal, - "signatory": get_public_signatory_fields(keyfile_data), - "signature": bytes_to_prefixed_hex(signature.signature), - }, - check_if_exists=True, - ) - - -def signature_json_to_map( - manifest: List[Dict[str, Any]] -) -> List[Tuple[PublicKey, Signature]]: - """Convert a JSON signature manifest to a classed signature map.""" - to_bytes = prefixed_hex_to_bytes # Shorten func name for brevity. - return [ # Return list comprehension. - ( - PublicKey(VerifyKey(to_bytes(entry["signatory"]["public_key"]))), - Signature(to_bytes(entry["signature"])), - ) - for entry in manifest - ] - - -# Transaction signing <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Transaction submission >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - -def assert_successful_transaction( - network: str, - raw_transaction: RawTransaction, - public_key: Union[PublicKey, MultiEd25519PublicKey], - signature: Union[Signature, MultiEd25519Signature], -): - """Submit a signed BCS transaction, asserting that it succeeds.""" - # Get REST client for network. - client = RestClient(NETWORK_URLS[network]) - auth_inner = ( - Ed25519Authenticator - if isinstance(public_key, PublicKey) - else MultiEd25519Authenticator - ) # Get inner authenticator structure. - # Get authenticator. - authenticator = Authenticator(auth_inner(public_key, signature)) - # Get signed transaction. - signed_transaction = SignedTransaction(raw_transaction, authenticator) - # Submit transaction, storing its hash. - tx_hash = client.submit_bcs_transaction(signed_transaction) - # Wait for transaction to succeed (asserts success). - client.wait_for_transaction(tx_hash) - print(f"Transaction successful: {tx_hash}") - - -def execute_transaction_from_signatures( - signature_files: Option[List[TextIOWrapper]], - proposal_indexer_func: Callable[[Dict[str, Any]], RawTransaction], - network: str, - is_rotation_transaction=False, -) -> Dict[str, Any]: - """Execute multisig transaction indicated by proposal signature - files, returning proposal. - - If transaction is a rotation transaction, transaction does not - contain an embedded multisig metafile. Hence in this case the - multisig public key is extracted from the challenge proposal. - - Otherwise, the public key of the multisig account is found in the - multisig metafile embedded in the transaction proposal. - """ - signature_map, proposal = index_proposal_signatures( - signature_files, "transaction_proposal" - ) # Index signatures into signature map, transaction proposal. - if is_rotation_transaction: # If rotation transaction: - # Public key is in challenge proposal. - public_key_hex = proposal["challenge_proposal"]["from_public_key"] - else: # If not rotation transaction: - # Public key is in embedded multisig metafile. - public_key_hex = proposal["multisig"]["public_key"] - # Get public key bytes. - public_key_bytes = prefixed_hex_to_bytes(public_key_hex) - # Get public key class instance. - public_key = MultiEd25519PublicKey.from_bytes(public_key_bytes) - # Get a raw transaction to sign from the transaction proposal. - raw_transaction = proposal_indexer_func(proposal) - assert_successful_transaction( # Assert transaction succeeds. - network=network, - raw_transaction=raw_transaction, - public_key=public_key, - signature=MultiEd25519Signature(public_key, signature_map), - ) - return proposal # Return proposal from signature files. - - -# Transaction submission <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# AMEE commands >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -# AMEE parser. -parser = argparse.ArgumentParser( - description="""Aptos Multisig Execution Expeditor (AMEE): A collection of - tools designed to expedite multisig account execution.""", -) -subparsers = parser.add_subparsers(required=True) - -# Network parent parser. -network_parser = argparse.ArgumentParser(add_help=False) -network_parser.add_argument( - "-n", - "--network", - choices=["devnet", "testnet", "mainnet"], - default="devnet", - help="Network to use, defaults to devnet.", -) - -# Use test password parent parser. -use_test_password_parser = argparse.ArgumentParser(add_help=False) -use_test_password_parser.add_argument( - "-u", "--use-test-password", action="store_true", help="Use test password." -) - - -# Keyfile subcommand parser. -parser_keyfile = subparsers.add_parser( - name="keyfile", - aliases=["k"], - description="Assorted single-signer keyfile operations.", - help="Single-signer keyfile operations.", -) -subparsers_keyfile = parser_keyfile.add_subparsers(required=True) - - -def keyfile_change_password(args): - """Change password for a single-signer keyfile.""" - data, private_key_bytes = check_keyfile_password( - args.keyfile, args.use_test_password - ) # Check password, get keyfile data and private key bytes. - if private_key_bytes is not None: # If able to decrypt private key: - encrypted_bytes, salt = encrypt_private_key( - private_key_bytes, args.use_test_password - ) # Encrypt private key. - # Get encrypted private key hex. - encrypted_private_key_hex = bytes_to_prefixed_hex(encrypted_bytes) - # Update JSON with encrypted private key. - data["encrypted_private_key"] = encrypted_private_key_hex - # Update JSON with new salt. - data["salt"] = bytes_to_prefixed_hex(salt) - # Write JSON to keyfile, skipping check for if file exists. - write_json_file(args.keyfile, data, False) - - -# Keyfile change password subcommand parser. -parser_keyfile_change_password = subparsers_keyfile.add_parser( - name="change-password", - aliases=["c"], - description="Change password for a single-singer keyfile.", - help="Change keyfile password.", - parents=[use_test_password_parser], -) -parser_keyfile_change_password.set_defaults(func=keyfile_change_password) -parser_keyfile_change_password.add_argument( - "keyfile", type=Path, help="Relative path to keyfile." -) - - -def keyfile_extract(args): - """Extract private key from keyfile, store via - aptos_sdk.account.Account.store""" - check_outfile_exists(args.account_store) # Check if path exists. - _, private_key_bytes = check_keyfile_password( - args.keyfile, args.use_test_password - ) # Try loading private key bytes. - # If able to successfully decrypt: - if private_key_bytes is not None: - # Load account. - account = Account.load_key(private_key_bytes.hex()) - # Store Aptos account file. - account.store(f"{args.account_store}") - # Open new Aptos account store: - with open(args.account_store, "r", encoding="utf-8") as outfile: - # Print contents of new account store. - print(f"New account store at {args.account_store}:") - print(f"{outfile.read()}") - - -# Keyfile extract subcommand parser. -parser_keyfile_extract = subparsers_keyfile.add_parser( - name="extract", - aliases=["e"], - description="""Generate an `aptos_sdk.account.Account` from a single-signer - keyfile then store on disk via `aptos_sdk.account.Account.store`.""", - help="Extract Aptos account store from keyfile.", - parents=[use_test_password_parser], -) -parser_keyfile_extract.set_defaults(func=keyfile_extract) -parser_keyfile_extract.add_argument( - "keyfile", type=Path, help="Relative path to keyfile to extract from." -) -parser_keyfile_extract.add_argument( - "account_store", - metavar="account-store", - type=Path, - help="Relative path to account file to store in.", -) - - -def keyfile_fund(args): - """Fund account linked to keyfile using devnet faucet, assuming - account address matches authentication key.""" - data = json.load(args.keyfile) # Load JSON data from keyfile. - address = data["authentication_key"] # Get address. - fund_address_from_faucet(address) # Fund from faucet. - - -# Keyfile fund subcommand parser. -parser_keyfile_fund = subparsers_keyfile.add_parser( - name="fund", - aliases=["f"], - description="Fund account linked to keyfile using devnet faucet.", - help="Fund on devnet faucet.", -) -parser_keyfile_fund.set_defaults(func=keyfile_fund) -parser_keyfile_fund.add_argument( - "keyfile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to keyfile.", -) - - -def keyfile_generate(args): - """Generate a keyfile for a single signer.""" - signatory = check_name(args.signatory) - if args.account_store is None: # If no account store supplied: - account = Account.generate() # Generate new account. - # If vanity prefix supplied: - if args.vanity_prefix is not None: - to_check = args.vanity_prefix # Define prefix to check. - # Get number of characters in vanity prefix. - n_chars = len(to_check) - if n_chars % 2 == 1: # If odd number of hex characters: - # Append 0 to make valid hexstring. - to_check = args.vanity_prefix + "0" - # Check that hex can be converted to bytes. - prefixed_hex_to_bytes(to_check) - print("Mining vanity address...") # Print feedback message. - len_prefix = len(args.vanity_prefix) # Get prefix length. - # While account address does not have prefix: - while account.address().hex()[0:len_prefix] != args.vanity_prefix: - account = Account.generate() # Generate another. - else: # If account store path supplied: - # Generate an account from it. - account = Account.load(f"{args.account_store}") - # Get private key bytes. - private_key_bytes = account.private_key.key.encode() - encrypted_private_key_bytes, salt = encrypt_private_key( - private_key_bytes, args.use_test_password - ) # Encrypt private key. - # Get encrypted private key hex. - key_hex = bytes_to_prefixed_hex(encrypted_private_key_bytes) - write_json_file( # Write JSON to keyfile. - path=get_file_path(args.outfile, args.signatory, "keyfile"), - data={ - "filetype": "Keyfile", - "signatory": signatory, - "public_key": f"{account.public_key()}", - "authentication_key": account.auth_key(), - "encrypted_private_key": key_hex, - "salt": bytes_to_prefixed_hex(salt), - }, - check_if_exists=True, - ) - - -# Keyfile generate subcommand parser. -parser_keyfile_generate = subparsers_keyfile.add_parser( - name="generate", - aliases=["g"], - description="Generate a single-signer keyfile.", - help="Generate new keyfile.", - parents=[use_test_password_parser], -) -parser_keyfile_generate.set_defaults(func=keyfile_generate) -parser_keyfile_generate.add_argument( - "signatory", - type=str, - nargs="+", - help="""The name of the entity acting as a signatory. For example 'Aptos' - or 'The Aptos Foundation'.""", -) -parser_keyfile_generate.add_argument( - "-o", "--outfile", type=Path, help="Relative path to desired keyfile." -) -exclusive_group = parser_keyfile_generate.add_mutually_exclusive_group() -exclusive_group.add_argument( - "-a", - "--account-store", - type=Path, - help="""Relative path to Aptos account data generated via - `aptos_sdk.account.Account.store()`.""", -) -exclusive_group.add_argument( - "-v", - "--vanity-prefix", - type=str, - help="Vanity address prefix, for example 0xf00.", -) - - -def keyfile_verify(args): - """Verify password for single-signer keyfile generated via - keyfile_generate(), show public key and authentication key.""" - data, private_key_bytes = check_keyfile_password( - args.keyfile, args.use_test_password - ) # Load JSON data and try getting private key bytes. - if private_key_bytes is not None: # If able to decrypt private key: - # Print keyfile info. - print(f'Keyfile password verified for {data["signatory"]}') - print(f'Public key: {data["public_key"]}') - print(f'Authentication key: {data["authentication_key"]}') - - -# Keyfile verify subcommand parser. -parser_keyfile_verify = subparsers_keyfile.add_parser( - name="verify", - aliases=["v"], - description="Verify password for a single-signer keyfile.", - help="Verify keyfile password.", - parents=[use_test_password_parser], -) -parser_keyfile_verify.set_defaults(func=keyfile_verify) -parser_keyfile_verify.add_argument( - "keyfile", type=Path, help="Relative path to keyfile." -) - - -# Metafile subcommand parser. -parser_metafile = subparsers.add_parser( - name="metafile", - aliases=["m"], - description="Assorted multisig metafile operations.", - help="Multisig metafile operations.", -) -subparsers_metafile = parser_metafile.add_subparsers(required=True) - - -def metafile_append(args): - """Append signatory/signatories to a multisig metafile.""" - metafile_check_update( - metafile_json=json.load(args.metafile), - name_tokens=args.name, - threshold=args.threshold, - keyfiles=args.keyfiles, - outfile=args.outfile, - ) - - -# Metafile append subcommand parser. -parser_metafile_append = subparsers_metafile.add_parser( - name="append", - aliases=["a"], - description="Append a signatory or signatories to multisig metafile.", - help="Append signer(s) to a multisig.", -) -parser_metafile_append.set_defaults(func=metafile_append) -parser_metafile_append.add_argument( - "metafile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to desired multisig metafile to add to.", -) -parser_metafile_append.add_argument( - "threshold", - type=int, - help="The number of single signers required to approve a transaction.", -) -parser_metafile_append.add_argument( - "name", - type=str, - nargs="+", - help="""The name of the new multisig entity. For example 'Aptos' or 'The - Aptos Foundation'.""", -) -parser_metafile_append.add_argument( - "-k", - "--keyfiles", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative paths to single-signer keyfiles in the multisig.", - required=True, -) -parser_metafile_append.add_argument( - "-o", - "--outfile", - type=Path, - help="Custom relative path to new multisig metafile.", -) - - -def metafile_fund(args): - """Fund account at multisig address using devnet faucet, defaulting - to authentication key for address.""" - with open(args.metafile, encoding="utf-8") as metafile: - data = json.load(metafile) # Load JSON data from metafile. - address = data["address"] # Get multisig address. - auth_key = data["authentication_key"] # Get its authentication key. - # Determine the address to fund. - address_to_fund = auth_key if address is None else address - fund_address_from_faucet(address_to_fund) # Fund from faucet. - if address is None: # If no address listed before funding: - # Update multisig metafile address to authentication key. - update_multisig_address(args.metafile, auth_key) - - -# Metafile fund subcommand parser. -parser_metafile_fund = subparsers_metafile.add_parser( - name="fund", - aliases=["f"], - description="Fund a multisig account.", - help="Fund multisig account.", -) -parser_metafile_fund.set_defaults(func=metafile_fund) -parser_metafile_fund.add_argument( - "metafile", - type=Path, - help="Relative path to metafile.", -) - - -def metafile_incorporate(args): - """Incorporate single-signer keyfiles to multisig metafile.""" - metafile_check_update( - metafile_json={"n_signatories": 0, "signatories": []}, - name_tokens=args.name, - threshold=args.threshold, - keyfiles=args.keyfiles, - outfile=args.outfile, - ) - - -# Metafile incorporate subcommand parser. -parser_metafile_incorporate = subparsers_metafile.add_parser( - name="incorporate", - aliases=["i"], - description="""Incorporate multiple single-signer keyfiles into a multisig - metafile.""", - help="Incorporate single signers into a multisig.", -) -parser_metafile_incorporate.set_defaults(func=metafile_incorporate) -parser_metafile_incorporate.add_argument( - "threshold", - type=int, - help="The number of single signers required to approve a transaction.", -) -parser_metafile_incorporate.add_argument( - "name", - type=str, - nargs="+", - help="""The name of the multisig entity. For example 'Aptos' or 'The Aptos - Foundation'.""", -) -parser_metafile_incorporate.add_argument( - "-k", - "--keyfiles", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative paths to single-signer keyfiles in the multisig.", - required=True, -) -parser_metafile_incorporate.add_argument( - "-o", - "--outfile", - type=Path, - help="Custom relative path to desired multisig metafile.", -) - - -def metafile_remove(args): - """Remove signatories from a multisig metafile.""" - metafile_json = json.load(args.metafile) # Load metafile JSON. - # Sort 0-indexed signatory list indices from high to low. - args.signatories.sort(reverse=True) - # Loop over 0-indexed IDs to remove, high to low: - for index in args.signatories: - # Remove signatory at index from list. - del metafile_json["signatories"][index] - # Decrement signatory count. - metafile_json["n_signatories"] -= len(args.signatories) - metafile_check_update( # Check and write data to disk. - metafile_json=metafile_json, - name_tokens=args.name, - threshold=args.threshold, - keyfiles=None, - outfile=args.outfile, - ) - - -# Metafile remove subcommand parser. -parser_metafile_remove = subparsers_metafile.add_parser( - name="remove", - aliases=["r"], - description="Remove signatory or signatories from multisig metafile.", - help="Remove signer(s) from a multisig.", -) -parser_metafile_remove.set_defaults(func=metafile_remove) -parser_metafile_remove.add_argument( - "metafile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to desired multisig metafile to remove from.", -) -parser_metafile_remove.add_argument( - "threshold", - type=int, - help="The number of single signers required to approve a transaction.", -) -parser_metafile_remove.add_argument( - "name", - type=str, - nargs="+", - help="""The name of the new multisig entity. For example 'Aptos' or 'The - Aptos Foundation'.""", -) -parser_metafile_remove.add_argument( - "-s", - "--signatories", - action="extend", - nargs="+", - type=int, - help="""Signatory or signatories to remove, indicated by 0-indexed position - in signatories list.""", - required=True, -) -parser_metafile_remove.add_argument( - "-o", - "--outfile", - type=Path, - help="Custom relative path to new multisig metafile.", -) - - -def metafile_threshold(args): - """Update threshold for a multisig metafile.""" - metafile_json = json.load(args.metafile) # Load metafile JSON. - assert ( # Assert that threshold update is specified. - metafile_json["threshold"] != args.threshold - ), "No threshold update specified." - metafile_check_update( # Check and write data to disk. - metafile_json=metafile_json, - name_tokens=args.name, - threshold=args.threshold, - keyfiles=None, - outfile=args.outfile, - ) - - -# Metafile threshold subcommand parser. -parser_metafile_threshold = subparsers_metafile.add_parser( - name="threshold", - aliases=["t"], - description="Change signer threshold for multisig metafile.", - help="Change multisig threshold.", -) -parser_metafile_threshold.set_defaults(func=metafile_threshold) -parser_metafile_threshold.add_argument( - "metafile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to desired multisig metafile to modify threshold for.", -) -parser_metafile_threshold.add_argument( - "threshold", - type=int, - help="The number of single signers required to approve a transaction.", -) -parser_metafile_threshold.add_argument( - "name", - type=str, - nargs="+", - help="""The name of the new multisig entity. For example 'Aptos' or 'The - Aptos Foundation'.""", -) -parser_metafile_threshold.add_argument( - "-o", - "--outfile", - type=Path, - help="Custom relative path to new multisig metafile.", -) - -# Publish subcommand parser. -parser_publish = subparsers.add_parser( - name="publish", - aliases=["p"], - description="Assorted Move package publication operations.", - help="Move package publication.", -) -subparsers_publish = parser_publish.add_subparsers(required=True) - - -def publish_execute(args): - """Publish a Move package from a multisig account.""" - execute_transaction_from_signatures( - signature_files=args.signatures, - proposal_indexer_func=get_publication_transaction, - network=args.network, - ) - - -# Publish execute subcommand parser. -parser_publish_execute = subparsers_publish.add_parser( - name="execute", - aliases=["e"], - description="Execute package publication from proposal signatures.", - help="Publish a Move package.", - parents=[network_parser], -) -parser_publish_execute.set_defaults(func=publish_execute) -parser_publish_execute.add_argument( - "signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to publication transaction signatures for at least - threshold number of multisig signatories.""", -) - - -def publish_propose(args): - """Propose the publication of a Move package hosted on GitHub.""" - # Load publisher data. - publisher_data = json.load(args.metafile) - # Get publisher account address. - publisher_address = publisher_data["address"] - assert publisher_address is not None, "Need an address to publish from." - sequence_number = get_sequence_number( - prefixed_hex_to_bytes(publisher_address), args.network - ) # Get originating account sequence number. - write_json_file( # Write JSON to proposal file. - path=get_file_path(args.outfile, args.name, "publication_proposal"), - data={ - "filetype": "Publication proposal", - "description": check_name(args.name), - "github_user": args.user, - "github_project": args.project, - "commit": args.commit, - "manifest_path": args.manifest, - "named_address": args.named_address, - "module_sequence": args.module_sequence, - "multisig": publisher_data, - "sequence_number": sequence_number, - "chain_id": RestClient(NETWORK_URLS[args.network]).chain_id, - "expiry": args.expiry.isoformat(), - }, - check_if_exists=True, - ) - - -# Publish propose subcommand parser. -parser_publish_propose = subparsers_publish.add_parser( - name="propose", - aliases=["p"], - description="Propose a Move package publication, from a GitHub project.", - help="Propose a Move package publication.", - parents=[network_parser], -) -parser_publish_propose.set_defaults(func=publish_propose) -parser_publish_propose.add_argument( - "metafile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to multisig metafile for account to publish under.", -) -parser_publish_propose.add_argument( - "user", - type=str, - help="GitHub username for package to publish.", -) -parser_publish_propose.add_argument( - "project", - type=str, - help="GitHub project name for package to publish.", -) -parser_publish_propose.add_argument( - "commit", - type=str, - help="Commit hash to download, abridged or full.", -) -parser_publish_propose.add_argument( - "manifest", - type=str, - help="Relative path Move.toml for package.", -) -parser_publish_propose.add_argument( - "named_address", - metavar="named-address", - type=str, - help="Named address of publisher in Move.toml. For example 'protocol'.", -) -parser_publish_propose.add_argument( - "-m", - "--module-sequence", - type=str, - nargs="+", - help="""Sequence to publish modules in from bottom of dependency hierarchy - up. Modules that are used should be listed before any modules that use - them, and modules that declare friends should be declared before the - friends they declare. Module names should not include .move suffix.""", - required=True, -) -parser_publish_propose.add_argument( - "-e", - "--expiry", - help="Publication expiry, in ISO 8601 format. For example '2023-02-15'.", - type=datetime.fromisoformat, - required=True, -) -parser_publish_propose.add_argument( - "-d", - "--name", - type=str, - nargs="+", - help="Description for proposal. For example 'Genesis' or 'Upgrade'.", - required=True, -) -parser_publish_propose.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to publication proposal outfile.", -) - - -def publish_sign(args): - """Sign a package publication proposal.""" - proposal = json.load(args.proposal) # Load proposal data. - sign_raw_transaction( # Sign corresponding raw transaction. - keyfile=args.keyfile, - raw_transaction=get_publication_transaction(proposal), - optional_outfile_path=args.outfile, - name_tokens=args.name, - proposal=proposal, - filetype="Publication signature", - use_test_password=args.use_test_password, - ) - - -# Publish sign subcommand parser. -parser_publish_sign = subparsers_publish.add_parser( - name="sign", - aliases=["s"], - description="Sign a package publication transaction.", - help="Package publication transaction signing.", - parents=[use_test_password_parser], -) -parser_publish_sign.set_defaults(func=publish_sign) -parser_publish_sign.add_argument( - "proposal", - type=argparse.FileType("r", encoding="utf-8"), - help="Publication transaction proposal file.", -) -parser_publish_sign.add_argument( - "keyfile", - type=Path, - help="Relative path to single-signer keyfile for signing proposal.", -) -parser_publish_sign.add_argument( - "name", - type=str, - nargs="+", - help="Description for transaction signature.", -) -parser_publish_sign.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to publication transaction signature outfile.", -) - -# Rotate subcommand parser. -parser_rotate = subparsers.add_parser( - name="rotate", - aliases=["r"], - description="Assorted authentication key rotation operations.", - help="Authentication key rotation operations.", -) -subparsers_rotate = parser_rotate.add_subparsers(required=True) - -# Rotate challenge subcommand parser. -parser_rotate_challenge = subparsers_rotate.add_parser( - name="challenge", - aliases=["c"], - description="Authentication key rotation proof challenge operations.", - help="Authentication key rotation proof challenges.", -) -tmp = parser_rotate_challenge.add_subparsers(required=True) -subparsers_rotate_challenge = tmp # Temp variable for line breaking. - - -def rotate_challenge_propose(args): - """Propose a rotation proof challenge, storing an output file. - - Accepts either a single-signer keyfile or multisig metafile for both - originating and target accounts. If single-signer, assumes account - address is identical to authentication key.""" - # Load originator data. - originator_data = json.load(args.originator) - target_data = json.load(args.target) # Load target data. - # Check if originator is single-signer. - from_is_single = originator_data["filetype"] == "Keyfile" - # Check if target is single-signer. - to_is_single = target_data["filetype"] == "Keyfile" - if from_is_single: # If a single-signer originator: - # Address is assumed to be authentication key. - originator_address = originator_data["authentication_key"] - else: # If multisig originator: - # Address is that indicated in metafile. - originator_address = originator_data["address"] - if to_is_single: # If a single-signer target: - assert target_data["authentication_key"] == originator_address, ( - "Authentication key of single-signer target account must match " - "originating address." - ) # Assert authentication key identical to from address. - sequence_number = get_sequence_number( - prefixed_hex_to_bytes(originator_address), args.network - ) # Get originating account sequence number. - write_json_file( # Write JSON to proposal file. - path=get_file_path(args.outfile, args.name, "challenge_proposal"), - data={ - "filetype": "Rotation proof challenge proposal", - "description": check_name(args.name), - "from_public_key": originator_data["public_key"], - "from_is_single_signer": from_is_single, - "to_is_single_signer": to_is_single, - "sequence_number": sequence_number, - "originator": originator_address, - "current_auth_key": originator_data["authentication_key"], - "new_public_key": target_data["public_key"], - "chain_id": RestClient(NETWORK_URLS[args.network]).chain_id, - "expiry": args.expiry.isoformat(), - }, - check_if_exists=True, - ) - - -# Rotate challenge propose subcommand parser. -parser_rotate_challenge_propose = subparsers_rotate_challenge.add_parser( - name="propose", - aliases=["p"], - description="Propose a rotation proof challenge.", - help="Rotation proof challenge proposal.", - parents=[network_parser], -) -parser_rotate_challenge_propose.set_defaults(func=rotate_challenge_propose) -parser_rotate_challenge_propose.add_argument( - "originator", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative file path for either single-signer keyfile or multisig - metafile for originating account. If a single-signer keyfile, assumes - account address is identical to its authentication key.""", -) -parser_rotate_challenge_propose.add_argument( - "target", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative file path for either single-signer keyfile or multisig - metafile for target account. If a single-signer keyfile, assumes - account address is identical to its authentication key.""", -) -parser_rotate_challenge_propose.add_argument( - "expiry", - help="Transaction expiry, in ISO 8601 format. For example '2023-02-15'.", - type=datetime.fromisoformat, -) -parser_rotate_challenge_propose.add_argument( - "name", - type=str, - nargs="+", - help="Description for rotation. For example 'Setup' or 'Add signer'.", -) -parser_rotate_challenge_propose.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to rotation proof challenge proposal outfile.", -) - - -def rotate_challenge_sign(args): - """Sign a rotation proof challenge proposal, storing output file.""" - proposal_data = json.load(args.proposal) # Load proposal data. - keyfile_data, private_key_bytes = check_keyfile_password( - args.keyfile, args.use_test_password - ) # Check password, get keyfile data and private key bytes. - if private_key_bytes is None: # If can't decrypt private key: - return # Return. - # Get rotation proof challenged BCS bytes. - rotation_proof_challenge_bcs = get_rotation_challenge_bcs(proposal_data) - # Create Aptos-style account. - account = Account.load_key(bytes_to_prefixed_hex(private_key_bytes)) - # Sign the serialized rotation proof challenge. - signature = account.sign(rotation_proof_challenge_bcs).data() - write_json_file( # Write JSON to signature file. - path=get_file_path(args.outfile, args.name, "challenge_signature"), - data={ - "filetype": "Rotation proof challenge signature", - "description": check_name(args.name), - "challenge_proposal": proposal_data, - "signatory": get_public_signatory_fields(keyfile_data), - "signature": bytes_to_prefixed_hex(signature), - }, - check_if_exists=True, - ) - - -# Rotate challenge sign subcommand parser. -parser_rotate_challenge_sign = subparsers_rotate_challenge.add_parser( - name="sign", - aliases=["s"], - description="Sign a rotation proof challenge proposal.", - help="Rotation proof challenge proposal signing.", - parents=[use_test_password_parser], -) -parser_rotate_challenge_sign.set_defaults(func=rotate_challenge_sign) -parser_rotate_challenge_sign.add_argument( - "proposal", - type=argparse.FileType("r", encoding="utf-8"), - help="Rotation proof challenge proposal file.", -) -parser_rotate_challenge_sign.add_argument( - "keyfile", - type=Path, - help="Single-signer keyfile for signing challenge proposal.", -) -parser_rotate_challenge_sign.add_argument( - "name", - type=str, - nargs="+", - help="Description for rotation signature.", -) -parser_rotate_challenge_sign.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to rotation proof challenge signature outfile.", -) - -# Rotate execute subcommand parser. -parser_rotate_execute = subparsers_rotate.add_parser( - name="execute", - aliases=["e"], - description="Authentication key rotation execution operations.", - help="Execute an authentication key rotation.", -) -tmp = parser_rotate_execute.add_subparsers(required=True) -subparsers_rotate_execute = tmp # Temp variable for line breaking. - - -def rotate_execute_single(args): - """Rotate authentication key for single-signer account. - - Only supports rotation to a multisig account.""" - keyfile_data, private_key_bytes = check_keyfile_password( - args.keyfile, args.use_test_password - ) # Check password, get keyfile data and private key bytes. - if private_key_bytes is None: # If can't decrypt private key: - return # Return without rotating. - # Create Aptos-style account for single signer. - account = Account.load_key(bytes_to_prefixed_hex(private_key_bytes)) - # Get public key bytes for account. - from_public_key_bytes = prefixed_hex_to_bytes(keyfile_data["public_key"]) - signature_map, proposal = index_proposal_signatures( - args.signatures, "challenge_proposal" - ) # Index signatures into signature map, extract challenge proposal. - # Get rotation challenge BCS. - rotation_challenge_bcs = get_rotation_challenge_bcs(proposal) - # Get capability to update address mapping for multisig account. - cap_update_table = MultiEd25519Signature( - metafile_to_multisig_public_key(args.metafile), signature_map - ).to_bytes() - raw_transaction = construct_raw_rotation_transaction( - from_scheme=Authenticator.ED25519, - from_public_key_bytes=from_public_key_bytes, - to_scheme=Authenticator.MULTI_ED25519, - to_public_key_bytes=prefixed_hex_to_bytes(proposal["new_public_key"]), - cap_rotate_key=account.sign(rotation_challenge_bcs).data(), - cap_update_table=cap_update_table, - sender_prefixed_hex=proposal["originator"], - sequence_number=proposal["sequence_number"], - expiry=datetime.fromisoformat(proposal["expiry"]), - chain_id=proposal["chain_id"], - ) # Construct raw rotation transaction. - assert_successful_transaction( # Assert transaction succeeds. - network=args.network, - raw_transaction=raw_transaction, - public_key=account.public_key(), - signature=account.sign(raw_transaction.keyed()), - ) - # Update multisig metafile address. - update_multisig_address(args.metafile, proposal["originator"]) - - -# Rotate execute single subcommand parser. -parser_rotate_execute_single = subparsers_rotate_execute.add_parser( - name="single", - aliases=["s"], - description="""Rotate the authentication key of a single-signer account to - the authentication key of a multisig account. Assumes single-signer - account address is identical to its authentication key. Requires - single-signer password approval.""", - help="Rotate single-signer account to multisig account.", - parents=[network_parser, use_test_password_parser], -) -parser_rotate_execute_single.set_defaults(func=rotate_execute_single) -parser_rotate_execute_single.add_argument( - "keyfile", - type=Path, - help="Single-signer keyfile for account to rotate.", -) -parser_rotate_execute_single.add_argument( - "metafile", - type=Path, - help="Relative path to metafile for multisig to rotate to.", -) -parser_rotate_execute_single.add_argument( - "signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to rotation proof challenge signature files from - threshold number of signatories.""", -) - - -def rotate_execute_multisig(args): - """Rotate authentication key for a multisig account. - - Only supports rotation to a single-signer account if the account has - as its authentication key the multisig account address.""" - proposal = execute_transaction_from_signatures( - signature_files=args.signatures, - proposal_indexer_func=get_rotation_transaction, - network=args.network, - is_rotation_transaction=True, - ) # Execute rotation transaction from signatures, storing proposal. - # Update multisig metafile address for from account. - update_multisig_address(args.metafile, None) - # If just rotated to a multisig account: - if not proposal["challenge_proposal"]["to_is_single_signer"]: - assert args.to_metafile is not None, "Must specify to metafile." - update_multisig_address( - args.to_metafile, proposal["challenge_proposal"]["originator"] - ) # Update metafile address for account just rotated to. - - -# Rotate execute multisig subcommand parser. -parser_rotate_execute_multisig = subparsers_rotate_execute.add_parser( - name="multisig", - aliases=["m"], - description="""Rotate the authentication key of a multisig account to the - authentication key of either a multisig account or a single-signer - account. If rotating to a single-signer account, requires that account - address is identical to single-signer authentication key.""", - help="Rotate multisig account.", - parents=[network_parser], -) -parser_rotate_execute_multisig.set_defaults(func=rotate_execute_multisig) -parser_rotate_execute_multisig.add_argument( - "metafile", - type=Path, - help="Multisig metafile for account undergoing rotation.", -) -parser_rotate_execute_multisig.add_argument( - "-s", - "--signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to rotation transaction signatures for at least - threshold number of multisig signatories.""", - required=True, -) -parser_rotate_execute_multisig.add_argument( - "-t", - "--to-metafile", - type=Path, - help="""Relative path to multisig metafile for multisig account having new - authentication key, if rotating to a multisig account.""", -) - -# Rotate transaction subcommand parser. -parser_rotate_transaction = subparsers_rotate.add_parser( - name="transaction", - aliases=["t"], - description="""Authentication key rotation transaction operations for when - originating account is a multisig.""", - help="Authentication key rotation prep for multisig originator.", -) -tmp = parser_rotate_transaction.add_subparsers(required=True) -subparsers_rotate_transaction = tmp # Temp variable for line breaking. - - -def rotate_transaction_propose(args): - """Propose authentication key rotation transaction from multisig.""" - # Initialize empty from and to signatures for challenge proposal. - challenge_from_signatures, challenge_to_signatures = [], [] - challenge_proposal = extract_challenge_proposal_data( - signature_files=args.from_signatures, - proposal=None, - signatures_manifest=challenge_from_signatures, - ) # Extract from challenge proposal signatures. - challenge_proposal = extract_challenge_proposal_data( - signature_files=args.to_signatures, - proposal=challenge_proposal, - signatures_manifest=challenge_to_signatures, - ) # Extract to challenge proposal signatures. - write_json_file( # Write JSON to transaction proposal file. - path=get_file_path( - optional_path=args.outfile, - name_tokens=args.name, - extension="rotation_transaction_proposal", - ), - data={ - "filetype": "Rotation transaction proposal", - "description": check_name(args.name), - "challenge_proposal": challenge_proposal, - "challenge_from_signatures": challenge_from_signatures, - "challenge_to_signatures": challenge_to_signatures, - }, - check_if_exists=True, - ) - - -# Rotate transaction propose subcommand parser. -parser_rotate_transaction_propose = subparsers_rotate_transaction.add_parser( - name="propose", - aliases=["p"], - description="""Propose an authentication key rotation from a multisig - account originator.""", - help="Propose authentication key rotation for multisig account.", -) -parser_rotate_transaction_propose.set_defaults(func=rotate_transaction_propose) -parser_rotate_transaction_propose.add_argument( - "name", - type=str, - nargs="+", - help="Description for rotation transaction proposal.", -) -parser_rotate_transaction_propose.add_argument( - "-f", - "--from-signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to rotation proof challenge signatures for multisig - signatories at from account.""", - required=True, -) -parser_rotate_transaction_propose.add_argument( - "-t", - "--to-signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to rotation proof challenge signatures for requisite - signatories at to account. Can be a for a single signer account or for - a multisig account.""", - required=True, -) -parser_rotate_transaction_propose.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to rotation transaction proposal outfile.", -) - - -def rotate_transaction_sign(args): - """Sign an authentication key rotation transaction from a multisig - account.""" - proposal = json.load(args.proposal) # Load proposal data. - sign_raw_transaction( # Sign corresponding raw transaction. - keyfile=args.keyfile, - raw_transaction=get_rotation_transaction(proposal), - optional_outfile_path=args.outfile, - name_tokens=args.name, - proposal=proposal, - filetype="Rotation transaction signature", - use_test_password=args.use_test_password, - ) - - -# Rotate transaction sign subcommand parser. -parser_rotate_transaction_sign = subparsers_rotate_transaction.add_parser( - name="sign", - aliases=["s"], - description="Sign an authentication key rotation transaction.", - help="Authentication key rotation transaction signing.", - parents=[use_test_password_parser], -) -parser_rotate_transaction_sign.set_defaults(func=rotate_transaction_sign) -parser_rotate_transaction_sign.add_argument( - "proposal", - type=argparse.FileType("r", encoding="utf-8"), - help="Rotation transaction proposal file.", -) -parser_rotate_transaction_sign.add_argument( - "keyfile", - type=Path, - help="Relative path to single-signer keyfile for signing proposal.", -) -parser_rotate_transaction_sign.add_argument( - "name", - type=str, - nargs="+", - help="Description for transaction signature.", -) -parser_rotate_transaction_sign.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to rotation transaction signature outfile.", -) - -# Script subcommand parser. -parser_script = subparsers.add_parser( - name="script", - aliases=["s"], - description="Assorted Move script operations.", - help="Move script invocation.", -) -subparsers_script = parser_script.add_subparsers(required=True) - - -def script_execute(args): - """Invoke a Move script from a multisig account.""" - execute_transaction_from_signatures( - signature_files=args.signatures, - proposal_indexer_func=get_script_transaction, - network=args.network, - ) - - -# Script execute subcommand parser. -parser_script_execute = subparsers_script.add_parser( - name="execute", - aliases=["e"], - description="Execute script invocation from proposal signatures.", - help="Invoke a Move script.", - parents=[network_parser], -) -parser_script_execute.set_defaults(func=script_execute) -parser_script_execute.add_argument( - "signatures", - action="extend", - nargs="+", - type=argparse.FileType("r", encoding="utf-8"), - help="""Relative paths to script transaction signatures for at least - threshold number of multisig signatories.""", -) - - -def script_propose(args): - """Propose the invocation of a Move script hosted on GitHub.""" - # Load caller data. - caller_data = json.load(args.metafile) - # Get caller account address. - caller_address = caller_data["address"] - assert caller_address is not None, "Need an address to call from." - sequence_number = get_sequence_number( - prefixed_hex_to_bytes(caller_address), args.network - ) # Get calling account sequence number. - write_json_file( # Write JSON to proposal file. - path=get_file_path(args.outfile, args.name, "script_proposal"), - data={ - "filetype": "Script proposal", - "description": check_name(args.name), - "github_user": args.user, - "github_project": args.project, - "commit": args.commit, - "manifest_path": args.manifest, - "named_address": args.named_address, - "script_name": args.script_name, - "multisig": caller_data, - "sequence_number": sequence_number, - "chain_id": RestClient(NETWORK_URLS[args.network]).chain_id, - "expiry": args.expiry.isoformat(), - }, - check_if_exists=True, - ) - - -# Script propose subcommand parser. -parser_script_propose = subparsers_script.add_parser( - name="propose", - aliases=["p"], - description="Propose a Move script invocation, from a GitHub project.", - help="Propose a Move script invocation.", - parents=[network_parser], -) -parser_script_propose.set_defaults(func=script_propose) -parser_script_propose.add_argument( - "metafile", - type=argparse.FileType("r", encoding="utf-8"), - help="Relative path to multisig metafile for account to invoke from.", -) -parser_script_propose.add_argument( - "user", - type=str, - help="GitHub username for script to invoke.", -) -parser_script_propose.add_argument( - "project", - type=str, - help="GitHub project name for script to invoke.", -) -parser_script_propose.add_argument( - "commit", - type=str, - help="Commit hash to download, abridged or full.", -) -parser_script_propose.add_argument( - "manifest", - type=str, - help="Relative path Move.toml for package.", -) -parser_script_propose.add_argument( - "named_address", - metavar="named-address", - type=str, - help="Named address of signer in Move.toml. For example 'protocol'.", -) -parser_script_propose.add_argument( - "script_name", - metavar="script-name", - type=str, - help="Script function name. For example 'main' or 'governance_123'.", -) -parser_script_propose.add_argument( - "expiry", - help="Invocation expiry, in ISO 8601 format. For example '2023-02-15'.", - type=datetime.fromisoformat, -) -parser_script_propose.add_argument( - "name", - type=str, - nargs="+", - help="Description for proposal. For example 'Set volume limits'.", -) -parser_script_propose.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to invocation proposal outfile.", -) - - -def script_sign(args): - """Sign a script invocation proposal.""" - proposal = json.load(args.proposal) # Load proposal data. - sign_raw_transaction( # Sign corresponding raw transaction. - keyfile=args.keyfile, - raw_transaction=get_script_transaction(proposal), - optional_outfile_path=args.outfile, - name_tokens=args.name, - proposal=proposal, - filetype="Script signature", - use_test_password=args.use_test_password, - ) - - -# Script sign subcommand parser. -parser_script_sign = subparsers_script.add_parser( - name="sign", - aliases=["s"], - description="Sign a script invocation transaction.", - help="Script invocation transaction signing.", - parents=[use_test_password_parser], -) -parser_script_sign.set_defaults(func=script_sign) -parser_script_sign.add_argument( - "proposal", - type=argparse.FileType("r", encoding="utf-8"), - help="Script invocation transaction proposal file.", -) -parser_script_sign.add_argument( - "keyfile", - type=Path, - help="Relative path to single-signer keyfile for signing proposal.", -) -parser_script_sign.add_argument( - "name", - type=str, - nargs="+", - help="Description for transaction signature.", -) -parser_script_sign.add_argument( - "-o", - "--outfile", - type=Path, - help="Relative path to script invocation transaction signature outfile.", -) - -# AMEE commands <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -if __name__ == "__main__": - parsed_args = parser.parse_args() # Parse command line arguments. - parsed_args.func(parsed_args) # Call parsed args callback function. diff --git a/ecosystem/python/sdk/examples/multisig.py b/ecosystem/python/sdk/examples/multisig.py index 74cf018ff8e82..9fcb15e331d70 100644 --- a/ecosystem/python/sdk/examples/multisig.py +++ b/ecosystem/python/sdk/examples/multisig.py @@ -16,7 +16,6 @@ wait_for_user = True if __name__ == "__main__": - rest_client = RestClient(NODE_URL) faucet_client = FaucetClient(FAUCET_URL, rest_client) diff --git a/ecosystem/python/sdk/examples/multisig.sh b/ecosystem/python/sdk/examples/multisig.sh deleted file mode 100644 index 20b4976e7df20..0000000000000 --- a/ecosystem/python/sdk/examples/multisig.sh +++ /dev/null @@ -1,619 +0,0 @@ -# This file contains an assortment of shell scripts for to the AMEE -# tutorial (see "Your First Multisig"). -# -# All scripts are intended to be run from the `aptos_sdk` Python package -# directory (where amee.py is located), and use a single argument. For -# example, to display AMEE's subcommand menus, run the following: -# -# sh ../examples/multisig.sh menus - -# Helper functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -# Print n lines of whitespace between commands, where n is argument. -print_lines() { - for ((i=0;i<$1;i++)); do - echo - done -} - -# Print a whitespace break between calls. -print_break() { - print_lines 5 -} - -# Print a separator message using all arguments taken as a string. -heading() { - print_lines 2 - echo === $@ === - print_lines 2 -} - -# Wait for user to press Enter. -wait() { - print_lines 2 - read -p "Press Enter to continue..." -} - - -# Helper functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -# Demo scripts >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - -# Return if no arguments passed -if test "$#" = 0; then echo No subscript specified - -# Display menus. -elif test $1 = menus; then - - # :!:>help - # Print top-level menu. - poetry run python amee.py -h # <:!:help - - # Print nested subcommand help menus with whitespace in between. - print_break - poetry run python amee.py keyfile -h - print_break - poetry run python amee.py keyfile change-password -h - print_break - poetry run python amee.py keyfile extract -h - print_break - poetry run python amee.py keyfile fund -h - print_break - poetry run python amee.py keyfile generate -h - print_break - poetry run python amee.py keyfile verify -h - print_break - poetry run python amee.py metafile -h - print_break - poetry run python amee.py metafile append -h - print_break - poetry run python amee.py metafile fund -h - print_break - poetry run python amee.py metafile incorporate -h - print_break - poetry run python amee.py metafile remove -h - print_break - poetry run python amee.py metafile threshold -h - print_break - poetry run python amee.py publish -h - print_break - poetry run python amee.py publish execute -h - print_break - poetry run python amee.py publish propose -h - print_break - poetry run python amee.py publish sign -h - print_break - poetry run python amee.py rotate -h - print_break - poetry run python amee.py rotate challenge -h - print_break - poetry run python amee.py rotate challenge propose -h - print_break - poetry run python amee.py rotate challenge sign -h - print_break - poetry run python amee.py rotate execute -h - print_break - poetry run python amee.py rotate execute single -h - print_break - poetry run python amee.py rotate execute multisig -h - print_break - poetry run python amee.py rotate transaction -h - print_break - poetry run python amee.py rotate transaction propose -h - print_break - poetry run python amee.py rotate transaction sign -h - print_break - poetry run python amee.py script -h - print_break - poetry run python amee.py script execute -h - print_break - poetry run python amee.py script propose -h - print_break - poetry run python amee.py script sign -h - -# Demo keyfile operations. -elif test $1 = keyfiles; then - - rm -f *.keyfile - rm -f *.account_store - - heading Generate - # :!:>generate_keyfile - poetry run python amee.py keyfile generate \ - The Aptos Foundation # <:!:generate_keyfile - - wait - - heading Extract - # :!:>extract_keyfile - poetry run python amee.py k extract \ - the_aptos_foundation.keyfile \ - the_aptos_foundation.account_store # <:!:extract_keyfile - - wait - - heading Generate from store - # :!:>generate_from_store - poetry run python amee.py keyfile g \ - The Aptos Foundation \ - --account-store the_aptos_foundation.account_store \ - --outfile from_store.keyfile # <:!:generate_from_store - - wait - - heading Change password - # :!:>change_password - poetry run python amee.py keyfile change-password \ - from_store.keyfile # <:!:change_password - - wait - - heading Verify - # :!:>verify_password - poetry run python amee.py keyfile verify \ - from_store.keyfile # <:!:verify_password - - wait - - heading Deleting keyfiles and account store - - rm -f *.keyfile - rm -f *.account_store - - -# Demo metafile operations. -elif test $1 = metafiles; then - - rm -f *.keyfile - rm -f *.multisig - - # :!:>metafiles_ace_bee - heading Generate vanity account for Ace - - poetry run python amee.py keyfile generate \ - Ace \ - --vanity-prefix 0xace \ - --use-test-password - - heading Generate vanity account for Bee - - poetry run python amee.py keyfile generate \ - Bee \ - --vanity-prefix 0xbee \ - --use-test-password # <:!:metafiles_ace_bee - - wait - - # :!:>metafiles_incorporate - heading Incorporate Ace and Bee into 1-of-2 multisig - - poetry run python amee.py metafile incorporate \ - 1 \ - Ace and Bee \ - --keyfiles \ - ace.keyfile \ - bee.keyfile # <:!:metafiles_incorporate - - wait - - # :!:>metafiles_threshold - heading Increase threshold to two signatures - - poetry run python amee.py metafile threshold \ - ace_and_bee.multisig \ - 2 \ - Ace and Bee increased # <:!:metafiles_threshold - - wait - - # :!:>metafiles_cad_dee - heading Generate vanity account for Cad - - poetry run python amee.py keyfile generate \ - Cad \ - --vanity-prefix 0xcad \ - --use-test-password - - heading Generate vanity account for Dee - - poetry run python amee.py keyfile generate \ - Dee \ - --vanity-prefix 0xdee \ - --use-test-password # <:!:metafiles_cad_dee - - wait - - # :!:>metafiles_append - heading Append Cad and Dee to 3-of-4 multisig - - poetry run python amee.py metafile append \ - ace_and_bee.multisig \ - 3 \ - Cad and Dee added \ - --keyfiles \ - cad.keyfile \ - dee.keyfile # <:!:metafiles_append - - wait - - # :!:>metafiles_remove - heading Remove Ace and Dee for 1-of-2 multisig - - poetry run python amee.py metafile remove \ - cad_and_dee_added.multisig \ - 1 \ - Ace and Dee removed \ - --signatories 0 3 # <:!:metafiles_remove - - wait - - heading Deleting keyfiles and metafiles - - rm -f *.keyfile - rm -f *.multisig - -# Demo authentication key rotation operations. -elif test $1 = rotate; then - - rm -f *.keyfile - rm -f *.multisig - rm -f *.challenge_proposal - rm -f *.challenge_signature - rm -f *.rotation_transaction_proposal - rm -f *.rotation_transaction_signature - - # :!:>rotate_prep_accounts - heading Generate vanity account for Ace - - poetry run python amee.py keyfile generate \ - Ace \ - --vanity-prefix 0xace \ - --use-test-password - - heading Generate vanity account for Bee - - poetry run python amee.py keyfile generate \ - Bee \ - --vanity-prefix 0xbee \ - --use-test-password - - heading Fund Ace on devnet - - poetry run python amee.py keyfile fund \ - ace.keyfile # <:!:rotate_prep_accounts - - wait - - # :!:>rotate_convert_multisig - heading Incorporate to 1-of-2 multisig - - poetry run python amee.py metafile incorporate \ - 1 \ - Initial \ - --keyfiles \ - ace.keyfile \ - bee.keyfile - - heading Propose rotation challenge for rotating to multisig - - poetry run python amee.py rotate challenge propose \ - ace.keyfile \ - initial.multisig \ - 2030-01-01 \ - Initial \ - --network devnet - - heading Have Ace sign challenge proposal - - poetry run python amee.py rotate challenge sign \ - initial.challenge_proposal \ - ace.keyfile \ - Ace initial \ - --use-test-password - - heading Have Ace execute rotation from single-signer account - - poetry run python amee.py rotate execute single \ - ace.keyfile \ - initial.multisig \ - ace_initial.challenge_signature \ - --use-test-password \ - --network devnet # <:!:rotate_convert_multisig - - wait - - # :!:>rotate_increase_propose - heading Increase metafile threshold to two signatures - - poetry run python amee.py metafile threshold \ - initial.multisig \ - 2 \ - Increased - - heading Propose rotation challenge for increasing threshold - - poetry run python amee.py rotate challenge propose \ - initial.multisig \ - increased.multisig \ - 2030-01-01 \ - Increase \ - --network devnet - - heading Have Ace sign challenge proposal - - poetry run python amee.py rotate challenge sign \ - increase.challenge_proposal \ - ace.keyfile \ - Ace increase \ - --use-test-password - - heading Have Bee sign challenge proposal - - poetry run python amee.py rotate challenge sign \ - increase.challenge_proposal \ - bee.keyfile \ - Bee increase \ - --use-test-password # <:!:rotate_increase_propose - - wait - - # :!:>rotate_increase_execute - heading Propose rotation transaction - - poetry run python amee.py rotate transaction propose \ - Increase \ - --from-signatures \ - ace_increase.challenge_signature \ - --to-signatures \ - ace_increase.challenge_signature \ - bee_increase.challenge_signature \ - - heading Have Bee only sign rotation transaction proposal - - poetry run python amee.py rotate transaction sign \ - increase.rotation_transaction_proposal \ - bee.keyfile \ - Bee increase \ - --use-test-password - - heading Submit rotation transaction - - poetry run python amee.py rotate execute multisig \ - initial.multisig \ - --signatures \ - bee_increase.rotation_transaction_signature \ - --to-metafile \ - increased.multisig # <:!:rotate_increase_execute - - wait - - # :!:>rotate_convert_single_propose - heading Propose rotation challenge for rotating back to Ace - - poetry run python amee.py rotate challenge propose \ - increased.multisig \ - ace.keyfile \ - 2030-01-01 \ - Return \ - --network devnet - - heading Have Ace sign challenge proposal - - poetry run python amee.py rotate challenge sign \ - return.challenge_proposal \ - ace.keyfile \ - Ace return \ - --use-test-password - - heading Have Bee sign challenge proposal - - poetry run python amee.py rotate challenge sign \ - return.challenge_proposal \ - bee.keyfile \ - Bee return \ - --use-test-password # <:!:rotate_convert_single_propose - - wait - - # :!:>rotate_convert_single_execute - heading Propose rotation transaction - - poetry run python amee.py rotate transaction propose \ - Return \ - --from-signatures \ - ace_return.challenge_signature \ - bee_return.challenge_signature \ - --to-signatures \ - ace_return.challenge_signature \ - - heading Have Ace sign rotation transaction proposal - - poetry run python amee.py rotate transaction sign \ - return.rotation_transaction_proposal \ - ace.keyfile \ - Ace return \ - --use-test-password - - heading Have Bee sign rotation transaction proposal - - poetry run python amee.py rotate transaction sign \ - return.rotation_transaction_proposal \ - bee.keyfile \ - Bee return \ - --use-test-password - - heading Submit rotation transaction - - poetry run python amee.py rotate execute multisig \ - increased.multisig \ - --signatures \ - ace_return.rotation_transaction_signature \ - bee_return.rotation_transaction_signature \ - --network devnet # <:!:rotate_convert_single_execute - - wait - - heading Deleting JSON files - - rm -f *.keyfile - rm -f *.multisig - rm -f *.challenge_proposal - rm -f *.challenge_signature - rm -f *.rotation_transaction_proposal - rm -f *.rotation_transaction_signature - - -# Demo governance operations. -elif test $1 = govern; then - - rm -f *.keyfile - rm -f *.multisig - rm -f *.publication_proposal - rm -f *.publication_signature - rm -f *.script_proposal - rm -f *.script_signature - - # :!:>govern_prep_accounts - heading Generate vanity account for Ace - - poetry run python amee.py keyfile generate \ - Ace \ - --vanity-prefix 0xace \ - --use-test-password - - heading Generate vanity account for Bee - - poetry run python amee.py keyfile generate \ - Bee \ - --vanity-prefix 0xbee \ - --use-test-password # <:!:govern_prep_accounts - - wait - - # :!:>govern_prep_multisig - heading Incorporate to 1-of-2 multisig - - poetry run python amee.py metafile incorporate \ - 1 \ - Protocol \ - --keyfiles \ - ace.keyfile \ - bee.keyfile - - heading Fund multisig - - poetry run python amee.py metafile fund \ - protocol.multisig # <:!:govern_prep_multisig - - wait - - # :!:>govern_publish - heading Propose publication - - poetry run python amee.py publish propose \ - protocol.multisig \ - alnoki \ - aptos-core \ - 1c26076f5f \ - aptos-move/move-examples/upgrade_and_govern/v1_0_0/Move.toml \ - upgrade_and_govern \ - --module-sequence \ - parameters \ - --expiry 2030-12-31 \ - --name Genesis \ - --network devnet - - heading Sign publication proposal - - poetry run python amee.py publish sign \ - genesis.publication_proposal \ - ace.keyfile \ - Genesis \ - --use-test-password - - heading Execute publication - - poetry run python amee.py publish execute \ - genesis.publication_signature \ - --network devnet # <:!:govern_publish - - wait - - # :!:>govern_upgrade - heading Propose upgrade - - poetry run python amee.py publish propose \ - protocol.multisig \ - alnoki \ - aptos-core \ - 1c26076f5f \ - aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml \ - upgrade_and_govern \ - --module-sequence \ - parameters \ - transfer \ - --expiry 2030-12-31 \ - --name Upgrade \ - --network devnet - - heading Sign upgrade proposal - - poetry run python amee.py publish sign \ - upgrade.publication_proposal \ - ace.keyfile \ - Upgrade \ - --use-test-password - - heading Execute upgrade - - poetry run python amee.py publish execute \ - upgrade.publication_signature \ - --network devnet # <:!:govern_upgrade - - wait - - # :!:>govern_script - heading Propose script invocation - - poetry run python amee.py script propose \ - protocol.multisig \ - alnoki \ - aptos-core \ - 1c26076f5f \ - aptos-move/move-examples/upgrade_and_govern/v1_1_0/Move.toml \ - upgrade_and_govern \ - set_only \ - 2030-12-31 \ - Invoke \ - --network devnet - - heading Sign invocation proposal - - poetry run python amee.py script sign \ - invoke.script_proposal \ - ace.keyfile \ - Invoke \ - --use-test-password - - heading Execute script invocation - - poetry run python amee.py script execute \ - invoke.script_signature \ - --network devnet # <:!:govern_script - - wait - - heading Deleting JSON files - - rm -f *.keyfile - rm -f *.multisig - rm -f *.publication_proposal - rm -f *.publication_signature - rm -f *.script_proposal - rm -f *.script_signature - -else echo Invalid subscript name - -fi - -# Demo scripts <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/ecosystem/python/sdk/poetry.lock b/ecosystem/python/sdk/poetry.lock index 8d646616a1613..cbb9b438ba311 100644 --- a/ecosystem/python/sdk/poetry.lock +++ b/ecosystem/python/sdk/poetry.lock @@ -1,16 +1,10 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. - [[package]] name = "anyio" -version = "3.6.2" +version = "3.6.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" category = "main" optional = false python-versions = ">=3.6.2" -files = [ - {file = "anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"}, - {file = "anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"}, -] [package.dependencies] idna = ">=2.8" @@ -20,7 +14,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16,<0.22)"] +trio = ["trio (>=0.16)"] [[package]] name = "autoflake" @@ -29,34 +23,17 @@ description = "Removes unused imports and unused variables" category = "dev" optional = false python-versions = "*" -files = [ - {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, -] [package.dependencies] pyflakes = ">=1.1.0" [[package]] name = "black" -version = "22.12.0" +version = "22.10.0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, -] [package.dependencies] click = ">=8.0.0" @@ -80,10 +57,6 @@ description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" -files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] [[package]] name = "cffi" @@ -92,174 +65,10 @@ description = "Foreign Function Interface for Python calling C code." category = "main" optional = false python-versions = "*" -files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, -] [package.dependencies] pycparser = "*" -[[package]] -name = "charset-normalizer" -version = "3.0.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, - {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, -] - [[package]] name = "click" version = "8.1.3" @@ -267,10 +76,6 @@ description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -278,61 +83,11 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "colorama" -version = "0.4.6" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "cryptography" -version = "39.0.1" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" -optional = false -python-versions = ">=3.6" -files = [ - {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965"}, - {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106"}, - {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c"}, - {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4"}, - {file = "cryptography-39.0.1-cp36-abi3-win32.whl", hash = "sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8"}, - {file = "cryptography-39.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c5caeb8188c24888c90b5108a441c106f7faa4c4c075a2bcae438c6e8ca73cef"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4789d1e3e257965e960232345002262ede4d094d1a19f4d3b52e48d4d8f3b885"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a"}, - {file = "cryptography-39.0.1.tar.gz", hash = "sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695"}, -] - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "check-manifest", "mypy", "ruff", "types-pytz", "types-requests"] -sdist = ["setuptools-rust (>=0.11.4)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist", "pytz"] -test-randomorder = ["pytest-randomly"] -tox = ["tox"] +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "flake8" @@ -341,10 +96,6 @@ description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = ">=3.6.1" -files = [ - {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, - {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, -] [package.dependencies] importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""} @@ -354,35 +105,24 @@ pyflakes = ">=2.5.0,<2.6.0" [[package]] name = "h11" -version = "0.14.0" +version = "0.12.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} +python-versions = ">=3.6" [[package]] name = "httpcore" -version = "0.16.3" +version = "0.15.0" description = "A minimal low-level HTTP client." category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, - {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, -] [package.dependencies] -anyio = ">=3.0,<5.0" +anyio = ">=3.0.0,<4.0.0" certifi = "*" -h11 = ">=0.13,<0.15" +h11 = ">=0.11,<0.13" sniffio = ">=1.0.0,<2.0.0" [package.extras] @@ -391,19 +131,15 @@ socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "httpx" -version = "0.23.3" +version = "0.23.0" description = "The next generation HTTP client." category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, - {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, -] [package.dependencies] certifi = "*" -httpcore = ">=0.15.0,<0.17.0" +httpcore = ">=0.15.0,<0.16.0" rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" @@ -420,10 +156,6 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" -files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] [[package]] name = "importlib-metadata" @@ -432,10 +164,6 @@ description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.6" -files = [ - {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, - {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, -] [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} @@ -447,19 +175,15 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", [[package]] name = "isort" -version = "5.11.5" +version = "5.10.1" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.7.0" -files = [ - {file = "isort-5.11.5-py3-none-any.whl", hash = "sha256:ba1d72fb2595a01c7895a5128f9585a5cc4b6d395f1c8d514989b9a7eb2a8746"}, - {file = "isort-5.11.5.tar.gz", hash = "sha256:6be1f76a507cb2ecf16c7cf14a37e41609ca082330be4e3436a18ef74add55db"}, -] +python-versions = ">=3.6.1,<4.0" [package.extras] colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +pipfile-deprecated-finder = ["pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] @@ -470,10 +194,6 @@ description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] [[package]] name = "mypy" @@ -482,32 +202,6 @@ description = "Optional static typing for Python" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, - {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, - {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, - {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, - {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, - {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, - {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, - {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, - {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, - {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, - {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, - {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, - {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, - {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, - {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, - {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, - {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, - {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, - {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, - {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, -] [package.dependencies] mypy-extensions = ">=0.4.3" @@ -522,45 +216,31 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.4" +version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." category = "main" optional = false -python-versions = ">=2.7" -files = [ - {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, -] +python-versions = "*" [[package]] name = "pathspec" -version = "0.11.0" +version = "0.10.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"}, - {file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"}, -] [[package]] name = "platformdirs" -version = "3.0.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "2.5.2" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" -files = [ - {file = "platformdirs-3.0.0-py3-none-any.whl", hash = "sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"}, - {file = "platformdirs-3.0.0.tar.gz", hash = "sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] [[package]] name = "pycodestyle" @@ -569,10 +249,6 @@ description = "Python style guide checker" category = "dev" optional = false python-versions = ">=3.6" -files = [ - {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, - {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, -] [[package]] name = "pycparser" @@ -581,10 +257,6 @@ description = "C parser in Python" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] [[package]] name = "pyflakes" @@ -593,10 +265,6 @@ description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=3.6" -files = [ - {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, - {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, -] [[package]] name = "pynacl" @@ -605,48 +273,14 @@ description = "Python binding to the Networking and Cryptography (NaCl) library" category = "main" optional = false python-versions = ">=3.6" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] [package.dependencies] cffi = ">=1.4.1" [package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +docs = ["sphinx (>=1.6.5)", "sphinx_rtd_theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] -[[package]] -name = "requests" -version = "2.28.2" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=3.7, <4" -files = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - [[package]] name = "rfc3986" version = "1.5.0" @@ -654,10 +288,6 @@ description = "Validating URI References per RFC 3986" category = "main" optional = false python-versions = "*" -files = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, -] [package.dependencies] idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} @@ -672,22 +302,6 @@ description = "Sniff out which async library your code is running under" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, -] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] [[package]] name = "tomli" @@ -696,10 +310,6 @@ description = "A lil' TOML parser" category = "main" optional = false python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] [[package]] name = "typed-ast" @@ -708,7 +318,248 @@ description = "a fork of Python 2 and 3 ast modules with type comment support" category = "main" optional = false python-versions = ">=3.6" -files = [ + +[[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "zipp" +version = "3.9.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] +testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] + +[metadata] +lock-version = "1.1" +python-versions = ">=3.7,<4.0" +content-hash = "301fe03009d7ca15390916a00ee83233a5df4b05831a5e6af4aec99e54b40e7e" + +[metadata.files] +anyio = [ + {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"}, + {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"}, +] +autoflake = [ + {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, +] +black = [ + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, +] +certifi = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] +cffi = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] +flake8 = [ + {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, + {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, +] +h11 = [ + {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, + {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, +] +httpcore = [ + {file = "httpcore-0.15.0-py3-none-any.whl", hash = "sha256:1105b8b73c025f23ff7c36468e4432226cbb959176eab66864b8e31c4ee27fa6"}, + {file = "httpcore-0.15.0.tar.gz", hash = "sha256:18b68ab86a3ccf3e7dc0f43598eaddcf472b602aba29f9aa6ab85fe2ada3980b"}, +] +httpx = [ + {file = "httpx-0.23.0-py3-none-any.whl", hash = "sha256:42974f577483e1e932c3cdc3cd2303e883cbfba17fe228b0f63589764d7b9c4b"}, + {file = "httpx-0.23.0.tar.gz", hash = "sha256:f28eac771ec9eb4866d3fb4ab65abd42d38c424739e80c08d8d20570de60b0ef"}, +] +idna = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] +importlib-metadata = [ + {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, + {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, +] +isort = [ + {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, + {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, +] +mccabe = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] +mypy = [ + {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, + {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, + {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, + {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, + {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, + {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, + {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, + {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, + {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, + {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, + {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, + {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, + {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, + {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, + {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, + {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, + {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, + {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, + {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, +] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +pathspec = [ + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, +] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +pycodestyle = [ + {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, + {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, +] +pycparser = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] +pyflakes = [ + {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, + {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, +] +pynacl = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] +rfc3986 = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] +sniffio = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +typed-ast = [ {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, @@ -734,53 +585,11 @@ files = [ {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, ] - -[[package]] -name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, -] - -[[package]] -name = "urllib3" -version = "1.26.14" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, - {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, +typing-extensions = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "zipp" -version = "3.13.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "zipp-3.13.0-py3-none-any.whl", hash = "sha256:e8b2a36ea17df80ffe9e2c4fda3f693c3dad6df1697d3cd3af232db680950b0b"}, - {file = "zipp-3.13.0.tar.gz", hash = "sha256:23f70e964bc11a34cef175bc90ba2914e1e4545ea1e3e2f67c079671883f9cb6"}, +zipp = [ + {file = "zipp-3.9.0-py3-none-any.whl", hash = "sha256:972cfa31bc2fedd3fa838a51e9bc7e64b7fb725a8c00e7431554311f180e9980"}, + {file = "zipp-3.9.0.tar.gz", hash = "sha256:3a7af91c3db40ec72dd9d154ae18e008c69efe8ca88dde4f9a731bb82fe2f9eb"}, ] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.7,<4.0" -content-hash = "7863da4bd8a3f6c800a157c1d842f06d0dfbf1853a8ec02626eb7372ae3e719e" diff --git a/ecosystem/python/sdk/pyproject.toml b/ecosystem/python/sdk/pyproject.toml index f20bf476bdfe3..e7d0d35536c37 100644 --- a/ecosystem/python/sdk/pyproject.toml +++ b/ecosystem/python/sdk/pyproject.toml @@ -10,9 +10,6 @@ httpx = "^0.23.0" mypy = "^0.982" PyNaCl = "^1.5.0" python = ">=3.7,<4.0" -cryptography = "^39.0.0" -toml = "^0.10.2" -requests = "^2.27.1" [tool.poetry.dev-dependencies] autoflake = "1.4.0"