diff --git a/common/defs/bitcoin/actinium.json b/common/defs/bitcoin/actinium.json index 605ec4766..d32404c28 100644 --- a/common/defs/bitcoin/actinium.json +++ b/common/defs/bitcoin/actinium.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/axe.json b/common/defs/bitcoin/axe.json index 5af395765..254d8f528 100644 --- a/common/defs/bitcoin/axe.json +++ b/common/defs/bitcoin/axe.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bcash.json b/common/defs/bitcoin/bcash.json index 7c4ccccbe..ebfbfd234 100644 --- a/common/defs/bitcoin/bcash.json +++ b/common/defs/bitcoin/bcash.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": 0, "force_bip143": true, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -47,5 +46,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bcash_testnet.json b/common/defs/bitcoin/bcash_testnet.json index 058b86ba7..cc2931ddd 100644 --- a/common/defs/bitcoin/bcash_testnet.json +++ b/common/defs/bitcoin/bcash_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": 0, "force_bip143": true, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bellcoin.json b/common/defs/bitcoin/bellcoin.json index 8322c33a9..d84ec7b0b 100644 --- a/common/defs/bitcoin/bellcoin.json +++ b/common/defs/bitcoin/bellcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 20 }, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bgold.json b/common/defs/bitcoin/bgold.json index 3691e317a..18a7a7a96 100644 --- a/common/defs/bitcoin/bgold.json +++ b/common/defs/bitcoin/bgold.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": 79, "force_bip143": true, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -47,5 +46,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bgold_testnet.json b/common/defs/bitcoin/bgold_testnet.json index d2279826d..a89907df2 100644 --- a/common/defs/bitcoin/bgold_testnet.json +++ b/common/defs/bitcoin/bgold_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": 79, "force_bip143": true, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bitcoin.json b/common/defs/bitcoin/bitcoin.json index 8d0059d09..53239270d 100644 --- a/common/defs/bitcoin/bitcoin.json +++ b/common/defs/bitcoin/bitcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -47,5 +46,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bitcoin_regtest.json b/common/defs/bitcoin/bitcoin_regtest.json index 495495e87..9f29818b6 100644 --- a/common/defs/bitcoin/bitcoin_regtest.json +++ b/common/defs/bitcoin/bitcoin_regtest.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bitcoin_testnet.json b/common/defs/bitcoin/bitcoin_testnet.json index 85a34a446..5faa6b477 100644 --- a/common/defs/bitcoin/bitcoin_testnet.json +++ b/common/defs/bitcoin/bitcoin_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bitcore.json b/common/defs/bitcoin/bitcore.json index adc22c6cb..726b079d2 100644 --- a/common/defs/bitcoin/bitcore.json +++ b/common/defs/bitcoin/bitcore.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bitzeny.json b/common/defs/bitcoin/bitzeny.json index 5febe9a10..2fa9707f9 100644 --- a/common/defs/bitcoin/bitzeny.json +++ b/common/defs/bitcoin/bitzeny.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 20 }, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/bprivate.json b/common/defs/bitcoin/bprivate.json index 945327841..9a2d26a49 100644 --- a/common/defs/bitcoin/bprivate.json +++ b/common/defs/bitcoin/bprivate.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": 42, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/brhodium.json b/common/defs/bitcoin/brhodium.json index 9c1869093..8461d5bd2 100644 --- a/common/defs/bitcoin/brhodium.json +++ b/common/defs/bitcoin/brhodium.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/capricoin.json b/common/defs/bitcoin/capricoin.json deleted file mode 100644 index 8a70b4713..000000000 --- a/common/defs/bitcoin/capricoin.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "coin_name": "Capricoin", - "coin_shortcut": "CPC", - "coin_label": "Capricoin", - "website": "https://capricoin.org", - "github": "https://github.com/Capricoinofficial/Capricoin", - "maintainer": "Jozef Knaperek ", - "curve_name": "secp256k1", - "decimals": 8, - "address_type": 28, - "address_type_p2sh": 35, - "maxfee_kb": 2000000, - "minfee_kb": 1000, - "signed_message_header": "Capricoin Signed Message:\n", - "hash_genesis_block": "00000d23fa0fc52c90893adb1181c9ddffb6c797a3e41864b9a23aa2f2981fe3", - "xprv_magic": 76066276, - "xpub_magic": 76067358, - "xpub_magic_segwit_p2sh": null, - "xpub_magic_segwit_native": null, - "bech32_prefix": null, - "cashaddr_prefix": null, - "slip44": 289, - "segwit": false, - "decred": false, - "fork_id": null, - "force_bip143": false, - "bip115": false, - "default_fee_b": { - "Low": 1, - "Economy": 7, - "Normal": 14, - "High": 20 - }, - "dust_limit": 546, - "blocktime_seconds": 60, - "uri_prefix": "capricoin", - "min_address_length": 27, - "max_address_length": 34, - "bitcore": [], - "blockbook": [], - "negative_fee": false, - "cooldown": 100, - "consensus_branch_id": null, - "confidential_assets": null -} diff --git a/common/defs/bitcoin/capricoin.png b/common/defs/bitcoin/capricoin.png deleted file mode 100644 index 005e907bc..000000000 Binary files a/common/defs/bitcoin/capricoin.png and /dev/null differ diff --git a/common/defs/bitcoin/cpuchain.json b/common/defs/bitcoin/cpuchain.json index b1b9b351e..40c30c69d 100644 --- a/common/defs/bitcoin/cpuchain.json +++ b/common/defs/bitcoin/cpuchain.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 20 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/crown.json b/common/defs/bitcoin/crown.json index 0fd4ff9f0..c20969cbd 100644 --- a/common/defs/bitcoin/crown.json +++ b/common/defs/bitcoin/crown.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -42,5 +41,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/dash.json b/common/defs/bitcoin/dash.json index 510fef860..980d18883 100644 --- a/common/defs/bitcoin/dash.json +++ b/common/defs/bitcoin/dash.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": true, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/dash_testnet.json b/common/defs/bitcoin/dash_testnet.json index 4116b0fb2..2a7b5b009 100644 --- a/common/defs/bitcoin/dash_testnet.json +++ b/common/defs/bitcoin/dash_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": true, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/decred.json b/common/defs/bitcoin/decred.json index 5cd9de90a..f35b425a6 100644 --- a/common/defs/bitcoin/decred.json +++ b/common/defs/bitcoin/decred.json @@ -24,7 +24,6 @@ "decred": true, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/decred_testnet.json b/common/defs/bitcoin/decred_testnet.json index a7ae8a910..54aa6c814 100644 --- a/common/defs/bitcoin/decred_testnet.json +++ b/common/defs/bitcoin/decred_testnet.json @@ -24,7 +24,6 @@ "decred": true, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/digibyte.json b/common/defs/bitcoin/digibyte.json index 50553407d..93129a40c 100644 --- a/common/defs/bitcoin/digibyte.json +++ b/common/defs/bitcoin/digibyte.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/dogecoin.json b/common/defs/bitcoin/dogecoin.json index 7fec4f4c9..1dee1bdeb 100644 --- a/common/defs/bitcoin/dogecoin.json +++ b/common/defs/bitcoin/dogecoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 100000 }, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/elements.json b/common/defs/bitcoin/elements.json index 9878c680c..df1b85851 100644 --- a/common/defs/bitcoin/elements.json +++ b/common/defs/bitcoin/elements.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,6 +37,8 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": { "address_prefix": 4, "blech32_prefix": "el" diff --git a/common/defs/bitcoin/etp.json b/common/defs/bitcoin/etp.json index 7cdcd2548..8d16d377a 100644 --- a/common/defs/bitcoin/etp.json +++ b/common/defs/bitcoin/etp.json @@ -9,12 +9,12 @@ "decimals": 8, "address_type": 50, "address_type_p2sh": 5, - "maxfee_kb": 2000000, + "maxfee_kb": 2000000, "minfee_kb": 100, "signed_message_header": "Metaverse Signed Message:\n", "hash_genesis_block": "b81848ef9ae86e84c3da26564bc6ab3a79efc628239d11471ab5cd25c0684c2d", "xprv_magic": 76066276, - "xpub_magic": 76067358, + "xpub_magic": 76067358, "xpub_magic_segwit_p2sh": null, "xpub_magic_segwit_native": null, "bech32_prefix": null, @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -37,10 +36,11 @@ "min_address_length": 27, "max_address_length": 34, "bitcore": [], - "blockbook": [ - ], + "blockbook": [], "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/feathercoin.json b/common/defs/bitcoin/feathercoin.json index b809aad93..fa5343c0c 100644 --- a/common/defs/bitcoin/feathercoin.json +++ b/common/defs/bitcoin/feathercoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/florincoin.json b/common/defs/bitcoin/florincoin.json index 789fe7340..a40a1243d 100644 --- a/common/defs/bitcoin/florincoin.json +++ b/common/defs/bitcoin/florincoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/fujicoin.json b/common/defs/bitcoin/fujicoin.json index 25628d892..55da047be 100644 --- a/common/defs/bitcoin/fujicoin.json +++ b/common/defs/bitcoin/fujicoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10000, "Economy": 20000, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/gamecredits.json b/common/defs/bitcoin/gamecredits.json index ef9f763e5..185db1445 100644 --- a/common/defs/bitcoin/gamecredits.json +++ b/common/defs/bitcoin/gamecredits.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/gincoin.json b/common/defs/bitcoin/gincoin.json index 55be6b7cf..7fa2ae1b0 100644 --- a/common/defs/bitcoin/gincoin.json +++ b/common/defs/bitcoin/gincoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/groestlcoin.json b/common/defs/bitcoin/groestlcoin.json index 39fc22a03..f1f03adee 100644 --- a/common/defs/bitcoin/groestlcoin.json +++ b/common/defs/bitcoin/groestlcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/groestlcoin_testnet.json b/common/defs/bitcoin/groestlcoin_testnet.json index 301272c7a..92e19afb3 100644 --- a/common/defs/bitcoin/groestlcoin_testnet.json +++ b/common/defs/bitcoin/groestlcoin_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -42,5 +41,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/hatch.json b/common/defs/bitcoin/hatch.json index 319c487a0..ef6f9787d 100644 --- a/common/defs/bitcoin/hatch.json +++ b/common/defs/bitcoin/hatch.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/hatch_testnet.json b/common/defs/bitcoin/hatch_testnet.json index 02e6d10f9..3877a0b42 100644 --- a/common/defs/bitcoin/hatch_testnet.json +++ b/common/defs/bitcoin/hatch_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/horizen.json b/common/defs/bitcoin/horizen.json deleted file mode 100644 index 5a1b2f920..000000000 --- a/common/defs/bitcoin/horizen.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "coin_name": "Horizen", - "coin_shortcut": "ZEN", - "coin_label": "Horizen", - "website": "https://www.horizen.global", - "github": "https://github.com/ZencashOfficial/zen", - "maintainer": "Power_VANO ", - "curve_name": "secp256k1", - "decimals": 8, - "address_type": 8329, - "address_type_p2sh": 8342, - "maxfee_kb": 2000000, - "minfee_kb": 1000, - "signed_message_header": "Zcash Signed Message:\n", - "hash_genesis_block": "0007104ccda289427919efc39dc9e4d499804b7bebc22df55f8b834301260602", - "xprv_magic": 76066276, - "xpub_magic": 76067358, - "xpub_magic_segwit_p2sh": null, - "xpub_magic_segwit_native": null, - "bech32_prefix": null, - "cashaddr_prefix": null, - "slip44": 121, - "segwit": false, - "decred": false, - "fork_id": null, - "force_bip143": false, - "bip115": true, - "default_fee_b": { - "Normal": 10 - }, - "dust_limit": 546, - "blocktime_seconds": 150, - "uri_prefix": "horizen", - "min_address_length": 35, - "max_address_length": 95, - "bitcore": [ - "https://explorer.horizen.global" - ], - "blockbook": [], - "negative_fee": false, - "cooldown": 100, - "consensus_branch_id": null, - "confidential_assets": null -} diff --git a/common/defs/bitcoin/horizen.png b/common/defs/bitcoin/horizen.png deleted file mode 100644 index 53036a457..000000000 Binary files a/common/defs/bitcoin/horizen.png and /dev/null differ diff --git a/common/defs/bitcoin/komodo.json b/common/defs/bitcoin/komodo.json index 5bf974d71..8e821e80d 100644 --- a/common/defs/bitcoin/komodo.json +++ b/common/defs/bitcoin/komodo.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -45,5 +44,7 @@ "3": 1537743641, "4": 1991772603 }, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/koto.json b/common/defs/bitcoin/koto.json index 02adb0ce3..f501d84a7 100644 --- a/common/defs/bitcoin/koto.json +++ b/common/defs/bitcoin/koto.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/litecoin.json b/common/defs/bitcoin/litecoin.json index 0f33757dd..3f51cfea3 100644 --- a/common/defs/bitcoin/litecoin.json +++ b/common/defs/bitcoin/litecoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/litecoin_testnet.json b/common/defs/bitcoin/litecoin_testnet.json index b4d68ec2b..2f03f6522 100644 --- a/common/defs/bitcoin/litecoin_testnet.json +++ b/common/defs/bitcoin/litecoin_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/monacoin.json b/common/defs/bitcoin/monacoin.json index f3daf8fb9..7774ba36c 100644 --- a/common/defs/bitcoin/monacoin.json +++ b/common/defs/bitcoin/monacoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/monetaryunit.json b/common/defs/bitcoin/monetaryunit.json index c143d23c0..407e5c04d 100644 --- a/common/defs/bitcoin/monetaryunit.json +++ b/common/defs/bitcoin/monetaryunit.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/namecoin.json b/common/defs/bitcoin/namecoin.json index a2d4146fc..30820c3ce 100644 --- a/common/defs/bitcoin/namecoin.json +++ b/common/defs/bitcoin/namecoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/nix.json b/common/defs/bitcoin/nix.json index 312835b3e..ef5f331b0 100644 --- a/common/defs/bitcoin/nix.json +++ b/common/defs/bitcoin/nix.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/particl.json b/common/defs/bitcoin/particl.json index 79635ff5f..a9c7bd198 100644 --- a/common/defs/bitcoin/particl.json +++ b/common/defs/bitcoin/particl.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/particl_testnet.json b/common/defs/bitcoin/particl_testnet.json index 8db048e77..8297f99c7 100644 --- a/common/defs/bitcoin/particl_testnet.json +++ b/common/defs/bitcoin/particl_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/peercoin.json b/common/defs/bitcoin/peercoin.json index d46e6dffe..4842e2cfd 100644 --- a/common/defs/bitcoin/peercoin.json +++ b/common/defs/bitcoin/peercoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": true, "confidential_assets": null } diff --git a/common/defs/bitcoin/peercoin_testnet.json b/common/defs/bitcoin/peercoin_testnet.json index ca3a16c30..98b88c6f1 100644 --- a/common/defs/bitcoin/peercoin_testnet.json +++ b/common/defs/bitcoin/peercoin_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": true, "confidential_assets": null } diff --git a/common/defs/bitcoin/pesetacoin.json b/common/defs/bitcoin/pesetacoin.json index d178bc454..40231ede7 100644 --- a/common/defs/bitcoin/pesetacoin.json +++ b/common/defs/bitcoin/pesetacoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/pivx.json b/common/defs/bitcoin/pivx.json index 8fa8b25ed..0c734ae89 100644 --- a/common/defs/bitcoin/pivx.json +++ b/common/defs/bitcoin/pivx.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/pivx_testnet.json b/common/defs/bitcoin/pivx_testnet.json index 331550bd7..697051cbc 100644 --- a/common/defs/bitcoin/pivx_testnet.json +++ b/common/defs/bitcoin/pivx_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/polis.json b/common/defs/bitcoin/polis.json index 79a4cb532..a23f0f783 100644 --- a/common/defs/bitcoin/polis.json +++ b/common/defs/bitcoin/polis.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/primecoin.json b/common/defs/bitcoin/primecoin.json index e3cc83129..09eda9fa3 100644 --- a/common/defs/bitcoin/primecoin.json +++ b/common/defs/bitcoin/primecoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -38,5 +37,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/qtum.json b/common/defs/bitcoin/qtum.json index 44d972fa0..79d06ceed 100644 --- a/common/defs/bitcoin/qtum.json +++ b/common/defs/bitcoin/qtum.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 410, "Economy": 500, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/qtum_testnet.json b/common/defs/bitcoin/qtum_testnet.json index ed0313a6d..777197203 100644 --- a/common/defs/bitcoin/qtum_testnet.json +++ b/common/defs/bitcoin/qtum_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 410, "Economy": 500, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/ravencoin.json b/common/defs/bitcoin/ravencoin.json index 755452e4b..f54079a5c 100644 --- a/common/defs/bitcoin/ravencoin.json +++ b/common/defs/bitcoin/ravencoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10 }, @@ -42,5 +41,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/ritocoin.json b/common/defs/bitcoin/ritocoin.json index 86cb603cc..1900910eb 100644 --- a/common/defs/bitcoin/ritocoin.json +++ b/common/defs/bitcoin/ritocoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10 }, @@ -42,5 +41,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/smartcash.json b/common/defs/bitcoin/smartcash.json index e0ff4abd5..147f4357b 100644 --- a/common/defs/bitcoin/smartcash.json +++ b/common/defs/bitcoin/smartcash.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 1, "Economy": 10, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/smartcash_testnet.json b/common/defs/bitcoin/smartcash_testnet.json index 26b3089dd..d26b4208e 100644 --- a/common/defs/bitcoin/smartcash_testnet.json +++ b/common/defs/bitcoin/smartcash_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 1, "Economy": 10, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/stakenet.json b/common/defs/bitcoin/stakenet.json index 80ee55d0c..86b1de067 100644 --- a/common/defs/bitcoin/stakenet.json +++ b/common/defs/bitcoin/stakenet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 10, "Economy": 70, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/syscoin.json b/common/defs/bitcoin/syscoin.json index 676ce6fe4..5ccbe72a8 100644 --- a/common/defs/bitcoin/syscoin.json +++ b/common/defs/bitcoin/syscoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 100, "Economy": 700, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/terracoin.json b/common/defs/bitcoin/terracoin.json index 17ce4fa8a..9d973bd04 100644 --- a/common/defs/bitcoin/terracoin.json +++ b/common/defs/bitcoin/terracoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/unobtanium.json b/common/defs/bitcoin/unobtanium.json index 1a9d267da..a9d37dda7 100644 --- a/common/defs/bitcoin/unobtanium.json +++ b/common/defs/bitcoin/unobtanium.json @@ -40,9 +40,10 @@ "https://blockbook.flurbo.xyz", "https://blockbook.unobtanium.uno" ], - "bip115": false, "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/vertcoin.json b/common/defs/bitcoin/vertcoin.json index 0781ab11e..ed9b33f64 100644 --- a/common/defs/bitcoin/vertcoin.json +++ b/common/defs/bitcoin/vertcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 1000 }, @@ -44,5 +43,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/viacoin.json b/common/defs/bitcoin/viacoin.json index ebbec62e8..652774d0d 100644 --- a/common/defs/bitcoin/viacoin.json +++ b/common/defs/bitcoin/viacoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 1000, "Economy": 7000, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/vipstarcoin.json b/common/defs/bitcoin/vipstarcoin.json index 7ebb245c6..ee5f4c397 100644 --- a/common/defs/bitcoin/vipstarcoin.json +++ b/common/defs/bitcoin/vipstarcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 410, "Economy": 500, @@ -45,5 +44,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zcash.json b/common/defs/bitcoin/zcash.json index 33288e36e..bc57f8120 100644 --- a/common/defs/bitcoin/zcash.json +++ b/common/defs/bitcoin/zcash.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -49,5 +48,7 @@ "3": 1537743641, "4": 733220448 }, + "extra_data": true, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zcash_testnet.json b/common/defs/bitcoin/zcash_testnet.json index 9a74a0c51..c0a89e6c8 100644 --- a/common/defs/bitcoin/zcash_testnet.json +++ b/common/defs/bitcoin/zcash_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -45,5 +44,7 @@ "3": 1537743641, "4": 733220448 }, + "extra_data": true, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zcoin.json b/common/defs/bitcoin/zcoin.json index 904206ada..cca4013ab 100644 --- a/common/defs/bitcoin/zcoin.json +++ b/common/defs/bitcoin/zcoin.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 1, "Economy": 10, @@ -43,5 +42,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zcoin_testnet.json b/common/defs/bitcoin/zcoin_testnet.json index 9f3a2f8a7..cf01ad535 100644 --- a/common/defs/bitcoin/zcoin_testnet.json +++ b/common/defs/bitcoin/zcoin_testnet.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Low": 1, "Economy": 10, @@ -41,5 +40,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zcore.json b/common/defs/bitcoin/zcore.json index 484adec59..414b53238 100644 --- a/common/defs/bitcoin/zcore.json +++ b/common/defs/bitcoin/zcore.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/bitcoin/zelcash.json b/common/defs/bitcoin/zelcash.json index ecbd25a09..5969df33d 100644 --- a/common/defs/bitcoin/zelcash.json +++ b/common/defs/bitcoin/zelcash.json @@ -24,7 +24,6 @@ "decred": false, "fork_id": null, "force_bip143": false, - "bip115": false, "default_fee_b": { "Normal": 10 }, @@ -40,5 +39,7 @@ "negative_fee": false, "cooldown": 100, "consensus_branch_id": null, + "extra_data": false, + "timestamp": false, "confidential_assets": null } diff --git a/common/defs/coins_details.json b/common/defs/coins_details.json index 8280ce49a..2b5776356 100644 --- a/common/defs/coins_details.json +++ b/common/defs/coins_details.json @@ -5,7 +5,7 @@ "Github": "https://github.com/Actinium-project/Actinium", "Homepage": "https://actinium.org" }, - "marketcap_usd": 348858, + "marketcap_usd": 171465, "name": "Actinium", "shortcut": "ACM", "t1_enabled": "yes", @@ -23,7 +23,7 @@ "Github": "https://github.com/axerunners/axe", "Homepage": "https://axerunners.com" }, - "marketcap_usd": 2167490, + "marketcap_usd": 1393141, "name": "Axe", "shortcut": "AXE", "t1_enabled": "yes", @@ -41,7 +41,7 @@ "Github": "https://github.com/Bitcoin-ABC/bitcoin-abc", "Homepage": "https://www.bitcoincash.org" }, - "marketcap_usd": 6056391355, + "marketcap_usd": 3329289416, "name": "Bitcoin Cash", "shortcut": "BCH", "t1_enabled": "yes", @@ -85,7 +85,7 @@ "Github": "https://github.com/bitcoin/bitcoin", "Homepage": "https://bitcoin.org" }, - "marketcap_usd": 162513519175, + "marketcap_usd": 96809902563, "name": "Bitcoin", "shortcut": "BTC", "t1_enabled": "yes", @@ -115,7 +115,7 @@ "Github": "https://github.com/BTCPrivate/BitcoinPrivate", "Homepage": "https://btcprivate.org" }, - "marketcap_usd": 639557, + "marketcap_usd": 317022, "name": "Bitcoin Private", "shortcut": "BTCP", "t1_enabled": "yes", @@ -133,7 +133,7 @@ "Github": "https://github.com/BTCGPU/BTCGPU", "Homepage": "https://bitcoingold.org" }, - "marketcap_usd": 148051720, + "marketcap_usd": 107887499, "name": "Bitcoin Gold", "shortcut": "BTG", "t1_enabled": "yes", @@ -159,7 +159,7 @@ "Github": "https://github.com/LIMXTEC/BitCore", "Homepage": "https://bitcore.cc" }, - "marketcap_usd": 7727429, + "marketcap_usd": 3327660, "name": "Bitcore", "shortcut": "BTX", "t1_enabled": "yes", @@ -176,30 +176,12 @@ } ] }, - "bitcoin:CPC": { - "links": { - "Github": "https://github.com/Capricoinofficial/Capricoin", - "Homepage": "https://capricoin.org" - }, - "marketcap_usd": 31957, - "name": "Capricoin", - "shortcut": "CPC", - "t1_enabled": "no", - "t2_enabled": "yes", - "type": "coin", - "wallet": [ - { - "name": "Capricoin Mobile Wallet", - "url": "https://wallet.capricoin.org" - } - ] - }, "bitcoin:CPU": { "links": { "Github": "https://github.com/cpuchain/cpuchain", "Homepage": "https://cpuchain.org" }, - "marketcap_usd": 10463, + "marketcap_usd": 4854, "name": "CPUchain", "shortcut": "CPU", "t1_enabled": "yes", @@ -217,7 +199,7 @@ "Github": "https://github.com/Crowndev/crowncoin", "Homepage": "https://crownplatform.com" }, - "marketcap_usd": 1721485, + "marketcap_usd": 936306, "name": "Crown", "shortcut": "CRW", "t1_enabled": "soon", @@ -230,7 +212,7 @@ "Github": "https://github.com/dashpay/dash", "Homepage": "https://www.dash.org" }, - "marketcap_usd": 860715782, + "marketcap_usd": 425104492, "name": "Dash", "shortcut": "DASH", "t1_enabled": "yes", @@ -264,7 +246,7 @@ "Github": "https://github.com/decred/dcrd", "Homepage": "https://www.decred.org" }, - "marketcap_usd": 195645540, + "marketcap_usd": 104441440, "name": "Decred", "shortcut": "DCR", "t1_enabled": "yes", @@ -282,7 +264,7 @@ "Github": "https://github.com/digibyte/digibyte", "Homepage": "https://digibyte.io" }, - "marketcap_usd": 78622272, + "marketcap_usd": 40644560, "name": "DigiByte", "shortcut": "DGB", "t1_enabled": "yes", @@ -304,7 +286,7 @@ "Github": "https://github.com/dogecoin/dogecoin", "Homepage": "https://dogecoin.com" }, - "marketcap_usd": 295344122, + "marketcap_usd": 203883098, "name": "Dogecoin", "shortcut": "DOGE", "t1_enabled": "yes", @@ -356,7 +338,7 @@ "Github": "https://github.com/fujicoin/fujicoin", "Homepage": "https://fujicoin.org" }, - "marketcap_usd": 229577, + "marketcap_usd": 138375, "name": "Fujicoin", "shortcut": "FJC", "t1_enabled": "yes", @@ -374,7 +356,7 @@ "Github": "https://github.com/floblockchain/flo", "Homepage": "https://flo.cash" }, - "marketcap_usd": 5655356, + "marketcap_usd": 2228729, "name": "Flo", "shortcut": "FLO", "t1_enabled": "yes", @@ -392,7 +374,7 @@ "Github": "https://github.com/FeatherCoin/Feathercoin", "Homepage": "https://feathercoin.com" }, - "marketcap_usd": 2229384, + "marketcap_usd": 1320494, "name": "Feathercoin", "shortcut": "FTC", "t1_enabled": "yes", @@ -410,7 +392,7 @@ "Github": "https://github.com/gamecredits-project/gamecredits", "Homepage": "https://gamecredits.org" }, - "marketcap_usd": 3124500, + "marketcap_usd": 2360947, "name": "GameCredits", "shortcut": "GAME", "t1_enabled": "yes", @@ -441,7 +423,7 @@ "Github": "https://github.com/Groestlcoin/groestlcoin", "Homepage": "https://www.groestlcoin.org" }, - "marketcap_usd": 14809785, + "marketcap_usd": 8944515, "name": "Groestlcoin", "shortcut": "GRS", "t1_enabled": "yes", @@ -477,7 +459,7 @@ "Github": "https://github.com/komodoplatform/komodo", "Homepage": "https://komodoplatform.com" }, - "marketcap_usd": 73876290, + "marketcap_usd": 34657826, "name": "Komodo", "shortcut": "KMD", "t1_enabled": "yes", @@ -513,7 +495,7 @@ "Github": "https://github.com/litecoin-project/litecoin", "Homepage": "https://litecoin.org" }, - "marketcap_usd": 4115243879, + "marketcap_usd": 2233396068, "name": "Litecoin", "shortcut": "LTC", "t1_enabled": "yes", @@ -539,7 +521,7 @@ "Github": "https://github.com/monacoinproject/monacoin", "Homepage": "https://monacoin.org" }, - "marketcap_usd": 110358644, + "marketcap_usd": 69099669, "name": "Monacoin", "shortcut": "MONA", "t1_enabled": "yes", @@ -557,7 +539,7 @@ "Github": "https://github.com/muecoin/MUE", "Homepage": "https://www.monetaryunit.org" }, - "marketcap_usd": 931035, + "marketcap_usd": 450799, "name": "MonetaryUnit", "shortcut": "MUE", "t1_enabled": "yes", @@ -575,7 +557,7 @@ "Github": "https://github.com/nixplatform/nixcore", "Homepage": "https://nixplatform.io" }, - "marketcap_usd": 3735859, + "marketcap_usd": 1331028, "name": "NIX", "shortcut": "NIX", "t1_enabled": "yes", @@ -593,7 +575,7 @@ "Github": "https://github.com/namecoin/namecoin-core", "Homepage": "https://namecoin.org" }, - "marketcap_usd": 7517954, + "marketcap_usd": 3086751, "name": "Namecoin", "shortcut": "NMC", "t1_enabled": "yes", @@ -615,7 +597,7 @@ "Github": "https://github.com/particl/particl-core", "Homepage": "https://particl.io" }, - "marketcap_usd": 4820447, + "marketcap_usd": 2905464, "name": "Particl", "shortcut": "PART", "t1_enabled": "yes", @@ -633,7 +615,7 @@ "Github": "https://github.com/PIVX-Project/PIVX", "Homepage": "https://pivx.org" }, - "marketcap_usd": 19529599, + "marketcap_usd": 11226931, "name": "PIVX", "shortcut": "PIVX", "t1_enabled": "yes", @@ -655,7 +637,7 @@ "Github": "https://github.com/polispay/polis", "Homepage": "https://www.polispay.org" }, - "marketcap_usd": 6608492, + "marketcap_usd": 3633088, "name": "Polis", "shortcut": "POLIS", "t1_enabled": "yes", @@ -673,11 +655,11 @@ "Github": "https://github.com/peercoin/peercoin", "Homepage": "https://peercoin.net" }, - "marketcap_usd": 5513496, + "marketcap_usd": 4052101, "name": "Peercoin", "shortcut": "PPC", "t1_enabled": "soon", - "t2_enabled": "yes", + "t2_enabled": "soon", "type": "coin", "wallet": [ { @@ -691,7 +673,7 @@ "Github": "https://github.com/FundacionPesetacoin/PesetacoinCore", "Homepage": "https://pesetacoin.info" }, - "marketcap_usd": 168917, + "marketcap_usd": 60308, "name": "Pesetacoin", "shortcut": "PTC", "t1_enabled": "yes", @@ -704,7 +686,7 @@ "Github": "https://github.com/qtumproject/qtum", "Homepage": "https://qtum.org" }, - "marketcap_usd": 211671340, + "marketcap_usd": 107343806, "name": "Qtum", "shortcut": "QTUM", "t1_enabled": "yes", @@ -740,7 +722,7 @@ "Github": "https://github.com/RavenProject/Ravencoin", "Homepage": "https://ravencoin.org" }, - "marketcap_usd": 151119573, + "marketcap_usd": 73885389, "name": "Ravencoin", "shortcut": "RVN", "t1_enabled": "yes", @@ -766,7 +748,7 @@ "Github": "https://github.com/SmartCash/Core-Smart", "Homepage": "https://smartcash.cc" }, - "marketcap_usd": 6407070, + "marketcap_usd": 2908956, "name": "SmartCash", "shortcut": "SMART", "t1_enabled": "yes", @@ -784,7 +766,7 @@ "Github": "https://github.com/syscoin/syscoin", "Homepage": "https://syscoin.org" }, - "marketcap_usd": 17209672, + "marketcap_usd": 8033487, "name": "Syscoin", "shortcut": "SYS", "t1_enabled": "soon", @@ -802,7 +784,7 @@ "Github": "https://github.com/unobtanium-official/unobtanium", "Homepage": "https://unobtanium.uno" }, - "marketcap_usd": 13662159, + "marketcap_usd": 8301430, "name": "Unobtanium", "shortcut": "UNO", "t1_enabled": "soon", @@ -820,7 +802,7 @@ "Github": "https://github.com/viacoin", "Homepage": "https://viacoin.org" }, - "marketcap_usd": 4559309, + "marketcap_usd": 2079822, "name": "Viacoin", "shortcut": "VIA", "t1_enabled": "yes", @@ -856,7 +838,7 @@ "Github": "https://github.com/vertcoin-project/vertcoin-core", "Homepage": "https://vertcoin.org" }, - "marketcap_usd": 16703670, + "marketcap_usd": 10097905, "name": "Vertcoin", "shortcut": "VTC", "t1_enabled": "yes", @@ -874,7 +856,7 @@ "Github": "https://github.com/primecoin/primecoin", "Homepage": "https://primecoin.io" }, - "marketcap_usd": 940801, + "marketcap_usd": 731056, "name": "Primecoin", "shortcut": "XPM", "t1_enabled": "yes", @@ -892,7 +874,7 @@ "Github": "https://gitlab.com/bitcoinrh/BRhodiumNode", "Homepage": "https://www.bitcoinrh.org" }, - "marketcap_usd": 5117344, + "marketcap_usd": 3040730, "name": "Bitcoin Rhodium", "shortcut": "XRC", "t1_enabled": "yes", @@ -910,7 +892,7 @@ "Github": "https://github.com/X9Developers/XSN", "Homepage": "https://stakenet.io" }, - "marketcap_usd": 4879272, + "marketcap_usd": 2911316, "name": "Stakenet", "shortcut": "XSN", "t1_enabled": "yes", @@ -928,7 +910,7 @@ "Github": "https://github.com/zcoinofficial/zcoin", "Homepage": "https://zcoin.io" }, - "marketcap_usd": 51973336, + "marketcap_usd": 29503204, "name": "Zcoin", "shortcut": "XZC", "t1_enabled": "yes", @@ -950,7 +932,7 @@ "Github": "https://github.com/zcore-coin/zcore-2.0", "Homepage": "https://zcore.cash" }, - "marketcap_usd": 107389, + "marketcap_usd": 112528, "name": "ZCore", "shortcut": "ZCR", "t1_enabled": "soon", @@ -968,7 +950,7 @@ "Github": "https://github.com/zcash/zcash", "Homepage": "https://z.cash" }, - "marketcap_usd": 494685720, + "marketcap_usd": 234840969, "name": "Zcash", "shortcut": "ZEC", "t1_enabled": "yes", @@ -994,7 +976,7 @@ "Github": "https://github.com/zelcash", "Homepage": "https://zel.network" }, - "marketcap_usd": 4007588, + "marketcap_usd": 2159018, "name": "Zel", "shortcut": "ZEL", "t1_enabled": "yes", @@ -1002,25 +984,12 @@ "type": "coin", "wallet": [] }, - "bitcoin:ZEN": { - "links": { - "Github": "https://github.com/ZencashOfficial/zen", - "Homepage": "https://www.horizen.global" - }, - "marketcap_usd": 91170520, - "name": "Horizen", - "shortcut": "ZEN", - "t1_enabled": "no", - "t2_enabled": "yes", - "type": "coin", - "wallet": [] - }, "bitcoin:ZNY": { "links": { "Github": "https://github.com/BitzenyCoreDevelopers/bitzeny", "Homepage": "https://bitzeny.tech" }, - "marketcap_usd": 73157, + "marketcap_usd": 0, "name": "BitZeny", "shortcut": "ZNY", "t1_enabled": "yes", @@ -1138,7 +1107,7 @@ "links": { "Homepage": "https://0xbitcoin.org/" }, - "marketcap_usd": 887148, + "marketcap_usd": 430161, "name": "0xBitcoin", "network": "eth", "shortcut": "0xBTC", @@ -1158,7 +1127,7 @@ "Github": "https://github.com/MarsBlockchain/1sg-contract", "Homepage": "https://www.1.sg" }, - "marketcap_usd": 1594116, + "marketcap_usd": 1458486, "name": "1SG", "network": "eth", "shortcut": "1SG", @@ -1177,7 +1146,7 @@ "links": { "Homepage": "https://firstblood.io" }, - "marketcap_usd": 6461825, + "marketcap_usd": 3814373, "name": "FirstBlood", "network": "eth", "shortcut": "1ST", @@ -1196,7 +1165,7 @@ "links": { "Homepage": "https://ico.1worldonline.com" }, - "marketcap_usd": 6778959, + "marketcap_usd": 2192365, "name": "1World", "network": "eth", "shortcut": "1WO", @@ -1274,7 +1243,7 @@ "Github": "https://github.com/crypt04dvisor/AlphaWallet", "Homepage": "https://alphaplatform.co/" }, - "marketcap_usd": 413562, + "marketcap_usd": 594214, "name": "Alpha", "network": "eth", "shortcut": "A", @@ -1353,7 +1322,7 @@ "links": { "Homepage": "https://www.arcblock.io" }, - "marketcap_usd": 12263197, + "marketcap_usd": 6625937, "name": "ArcBlock Token", "network": "eth", "shortcut": "ABT", @@ -1373,7 +1342,7 @@ "Github": "https://github.com/theabyssportal", "Homepage": "https://www.theabyss.com" }, - "marketcap_usd": 1919978, + "marketcap_usd": 1076792, "name": "The Abyss", "network": "eth", "shortcut": "ABYSS", @@ -1411,7 +1380,7 @@ "links": { "Homepage": "https://tokenstars.com/en/ace" }, - "marketcap_usd": 77103, + "marketcap_usd": 35206, "name": "ACE (TokenStars)", "network": "eth", "shortcut": "ACE", @@ -1430,7 +1399,7 @@ "links": { "Homepage": "https://adbank.network" }, - "marketcap_usd": 411014, + "marketcap_usd": 241178, "name": "adbank", "network": "eth", "shortcut": "ADB", @@ -1469,7 +1438,7 @@ "links": { "Homepage": "https://adhive.tv" }, - "marketcap_usd": 149120, + "marketcap_usd": 65925, "name": "AdHive Token", "network": "eth", "shortcut": "ADH", @@ -1489,7 +1458,7 @@ "Github": "https://github.com/aditus", "Homepage": "https://aditus.net" }, - "marketcap_usd": 81698, + "marketcap_usd": 66469, "name": "Aditus", "network": "eth", "shortcut": "ADI", @@ -1509,7 +1478,7 @@ "Github": "https://github.com/adelecosystem", "Homepage": "https://adel.io" }, - "marketcap_usd": 173397, + "marketcap_usd": 105279, "name": "Adelphoi", "network": "eth", "shortcut": "ADL", @@ -1548,7 +1517,7 @@ "Github": "https://github.com/adchain", "Homepage": "https://adtoken.com" }, - "marketcap_usd": 3349522, + "marketcap_usd": 3205726, "name": "AdToken", "network": "eth", "shortcut": "ADT", @@ -1568,7 +1537,7 @@ "Github": "https://github.com/AdExBlockchain", "Homepage": "https://www.adex.network" }, - "marketcap_usd": 7353581, + "marketcap_usd": 4077495, "name": "AdEx Network", "network": "eth", "shortcut": "ADX", @@ -1648,7 +1617,7 @@ "Github": "https://github.com/singnet/singnet", "Homepage": "https://singularitynet.io" }, - "marketcap_usd": 11695889, + "marketcap_usd": 5843809, "name": "SingularityNET", "network": "eth", "shortcut": "AGI", @@ -1706,7 +1675,7 @@ "links": { "Homepage": "https://www.aidcoin.co" }, - "marketcap_usd": 527800, + "marketcap_usd": 214895, "name": "AidCoin", "network": "eth", "shortcut": "AID", @@ -1765,7 +1734,7 @@ "Github": "https://github.com/AigangNetwork", "Homepage": "https://aigang.network/" }, - "marketcap_usd": 13972, + "marketcap_usd": 6770, "name": "Aigang", "network": "eth", "shortcut": "AIX", @@ -1823,7 +1792,7 @@ "links": { "Homepage": "http://ailink.in" }, - "marketcap_usd": 57763, + "marketcap_usd": 35124, "name": "AiLink Token", "network": "eth", "shortcut": "ALI", @@ -1901,7 +1870,7 @@ "Github": "https://github.com/ambrosus", "Homepage": "https://ambrosus.com/index.html" }, - "marketcap_usd": 2355123, + "marketcap_usd": 2308049, "name": "Amber Token", "network": "eth", "shortcut": "AMB", @@ -1961,7 +1930,7 @@ "Github": "https://github.com/amlt-by-coinfirm", "Homepage": "https://amlt.coinfirm.io/" }, - "marketcap_usd": 1730871, + "marketcap_usd": 1143641, "name": "AMLT", "network": "eth", "shortcut": "AMLT", @@ -1981,7 +1950,7 @@ "Github": "https://github.com/amontech", "Homepage": "https://amon.tech" }, - "marketcap_usd": 637995, + "marketcap_usd": 321852, "name": "Amon", "network": "eth", "shortcut": "AMN", @@ -2001,7 +1970,7 @@ "Github": "https://github.com/AMO-Project/", "Homepage": "https://amo.foundation" }, - "marketcap_usd": 3382659, + "marketcap_usd": 3021713, "name": "AMO Coin", "network": "eth", "shortcut": "AMO", @@ -2020,7 +1989,7 @@ "links": { "Homepage": "https://ados.foundation/" }, - "marketcap_usd": 501726, + "marketcap_usd": 368397, "name": "Token AmonD", "network": "eth", "shortcut": "AMON", @@ -2040,7 +2009,7 @@ "Github": "https://github.com/ampleforth", "Homepage": "https://ampleforth.org" }, - "marketcap_usd": 2639522, + "marketcap_usd": 1672317, "name": "Ampleforth", "network": "eth", "shortcut": "AMPL", @@ -2118,7 +2087,7 @@ "links": { "Homepage": "https://aragon.org" }, - "marketcap_usd": 34256473, + "marketcap_usd": 16333319, "name": "Aragon", "network": "eth", "shortcut": "ANT", @@ -2137,7 +2106,7 @@ "links": { "Homepage": "https://www.aurorachain.io" }, - "marketcap_usd": 11165806, + "marketcap_usd": 5783128, "name": "Aurora", "network": "eth", "shortcut": "AOA", @@ -2157,7 +2126,7 @@ "Github": "https://github.com/Oxchild/crowdsale", "Homepage": "https://apisplatform.io" }, - "marketcap_usd": 2588355, + "marketcap_usd": 2617824, "name": "APIS", "network": "eth", "shortcut": "APIS", @@ -2177,7 +2146,7 @@ "Github": "https://github.com/Aptoide/AppCoins-ethereumj", "Homepage": "https://appcoins.io" }, - "marketcap_usd": 3713194, + "marketcap_usd": 1836877, "name": "AppCoins", "network": "eth", "shortcut": "APPC", @@ -2235,7 +2204,7 @@ "links": { "Homepage": "https://www.arbitragect.com" }, - "marketcap_usd": 27590, + "marketcap_usd": 11077, "name": "ArbitrageCT", "network": "eth", "shortcut": "ARCT", @@ -2294,7 +2263,7 @@ "links": { "Homepage": "https://aeron.aero" }, - "marketcap_usd": 2625684, + "marketcap_usd": 1378725, "name": "Aeron", "network": "eth", "shortcut": "ARN", @@ -2313,7 +2282,7 @@ "links": { "Homepage": "http://www.maecenas.co" }, - "marketcap_usd": 1526027, + "marketcap_usd": 709742, "name": "Maecenas", "network": "eth", "shortcut": "ART", @@ -2391,7 +2360,7 @@ "links": { "Homepage": "https://airswap.io" }, - "marketcap_usd": 3067764, + "marketcap_usd": 1408200, "name": "Airswap", "network": "eth", "shortcut": "AST", @@ -2430,7 +2399,7 @@ "links": { "Homepage": "https://atlant.io" }, - "marketcap_usd": 1153507, + "marketcap_usd": 736734, "name": "ATLANT", "network": "eth", "shortcut": "ATL", @@ -2469,7 +2438,7 @@ "Github": "https://github.com/atonomi", "Homepage": "https://atonomi.io" }, - "marketcap_usd": 106429, + "marketcap_usd": 74402, "name": "Atonomi", "network": "eth", "shortcut": "ATMI", @@ -2527,7 +2496,7 @@ "links": { "Homepage": "https://www.aston.company" }, - "marketcap_usd": 122152, + "marketcap_usd": 70163, "name": "Aston", "network": "eth", "shortcut": "ATX", @@ -2546,7 +2515,7 @@ "links": { "Homepage": "https://auctus.org" }, - "marketcap_usd": 348980, + "marketcap_usd": 231778, "name": "Auctus", "network": "eth", "shortcut": "AUC", @@ -2604,7 +2573,7 @@ "links": { "Homepage": "https://cubeint.io" }, - "marketcap_usd": 1968444, + "marketcap_usd": 1852909, "name": "Cube", "network": "eth", "shortcut": "AUTO", @@ -2643,7 +2612,7 @@ "links": { "Homepage": "https://aventus.io" }, - "marketcap_usd": 735397, + "marketcap_usd": 422230, "name": "Aventus", "network": "eth", "shortcut": "AVT", @@ -2702,7 +2671,7 @@ "Github": "https://www.github.com/axpire", "Homepage": "https://www.axpire.io" }, - "marketcap_usd": 853811, + "marketcap_usd": 572663, "name": "aXpire", "network": "eth", "shortcut": "AXPR", @@ -2721,7 +2690,7 @@ "links": { "Homepage": "https://www.b2bx.exchange" }, - "marketcap_usd": 10731048, + "marketcap_usd": 9921344, "name": "B2BX", "network": "eth", "shortcut": "B2BX", @@ -2780,7 +2749,7 @@ "links": { "Homepage": "https://www.banca.world" }, - "marketcap_usd": 443448, + "marketcap_usd": 291998, "name": "Banca", "network": "eth", "shortcut": "BANCA", @@ -2838,7 +2807,7 @@ "links": { "Homepage": "https://basicattentiontoken.org" }, - "marketcap_usd": 327645075, + "marketcap_usd": 172751013, "name": "Basic Attention Token", "network": "eth", "shortcut": "BAT", @@ -2857,7 +2826,7 @@ "links": { "Homepage": "https://getbabb.com" }, - "marketcap_usd": 5188972, + "marketcap_usd": 3284301, "name": "BABB", "network": "eth", "shortcut": "BAX", @@ -2876,7 +2845,7 @@ "links": { "Homepage": "http://bbcoin.tradove.com" }, - "marketcap_usd": 412875, + "marketcap_usd": 286237, "name": "TraDove B2BCoin", "network": "eth", "shortcut": "BBC", @@ -2896,7 +2865,7 @@ "Github": "https://github.com/brickblock-io", "Homepage": "https://www.brickblock.io/" }, - "marketcap_usd": 1123895, + "marketcap_usd": 889679, "name": "BRICKBLOCK TOKEN", "network": "eth", "shortcut": "BBK", @@ -2934,7 +2903,7 @@ "links": { "Homepage": "https://bigbom.com" }, - "marketcap_usd": 210956, + "marketcap_usd": 95101, "name": "Bigbom", "network": "eth", "shortcut": "BBO", @@ -2953,7 +2922,7 @@ "links": { "Homepage": "https://block-chain.com" }, - "marketcap_usd": 719026, + "marketcap_usd": 381580, "name": "Block-Chain.com", "network": "eth", "shortcut": "BC", @@ -3032,7 +3001,7 @@ "Github": "https://github.com/VinceBCD/BCDiploma", "Homepage": "https://www.bcdiploma.com" }, - "marketcap_usd": 1593277, + "marketcap_usd": 772468, "name": "Blockchain Certified Data Token", "network": "eth", "shortcut": "BCDT", @@ -3071,7 +3040,7 @@ "Github": "https://github.com/blockmason", "Homepage": "https://blockmason.io" }, - "marketcap_usd": 2700569, + "marketcap_usd": 1229357, "name": "BlockMason Credit Protocol Token", "network": "eth", "shortcut": "BCPT", @@ -3091,7 +3060,7 @@ "Github": "https://github.com/bitcv", "Homepage": "https://bitcv.one/" }, - "marketcap_usd": 6095229, + "marketcap_usd": 4476912, "name": "BitCapitalVendor Token", "network": "eth", "shortcut": "BCV", @@ -3111,7 +3080,7 @@ "Github": "https://github.com/bitdegree", "Homepage": "https://bitdegree.org" }, - "marketcap_usd": 376668, + "marketcap_usd": 225885, "name": "BitDegree Token", "network": "eth", "shortcut": "BDG", @@ -3150,7 +3119,7 @@ "Github": "https://github.com/thebeetoken", "Homepage": "https://www.beetoken.com" }, - "marketcap_usd": 87860, + "marketcap_usd": 49618, "name": "Bee Token", "network": "eth", "shortcut": "BEE", @@ -3190,7 +3159,7 @@ "Github": "https://github.com/Rentberry", "Homepage": "https://rentberry.com" }, - "marketcap_usd": 61607, + "marketcap_usd": 34123, "name": "Berry", "network": "eth", "shortcut": "BERRY", @@ -3210,7 +3179,7 @@ "Github": "https://github.com/daocasino", "Homepage": "https://dao.casino" }, - "marketcap_usd": 3314346, + "marketcap_usd": 1192242, "name": "DAO.Casino", "network": "eth", "shortcut": "BET", @@ -3230,7 +3199,7 @@ "Github": "https://github.com/bethereumproject", "Homepage": "https://www.bethereum.com/" }, - "marketcap_usd": 129864, + "marketcap_usd": 76748, "name": "Bethereum", "network": "eth", "shortcut": "BETHER", @@ -3250,7 +3219,7 @@ "Github": "https://github.com/betterbetting", "Homepage": "https://www.betterbetting.org" }, - "marketcap_usd": 74188, + "marketcap_usd": 45054, "name": "BetterBetting", "network": "eth", "shortcut": "BETR", @@ -3288,7 +3257,7 @@ "links": { "Homepage": "https://bnktothefuture.com" }, - "marketcap_usd": 10077021, + "marketcap_usd": 2834991, "name": "BnkToTheFuture", "network": "eth", "shortcut": "BFT", @@ -3385,7 +3354,7 @@ "Github": "https://github.com/BitScreenerTech", "Homepage": "https://tokensale.bitscreener.com/" }, - "marketcap_usd": 227365, + "marketcap_usd": 112265, "name": "Token BitScreenerToken", "network": "eth", "shortcut": "BITX", @@ -3404,7 +3373,7 @@ "links": { "Homepage": "https://www.bibox.com" }, - "marketcap_usd": 14538799, + "marketcap_usd": 7325833, "name": "Bibox Token", "network": "eth", "shortcut": "BIX", @@ -3482,7 +3451,7 @@ "Github": "https://github.com/BankEx", "Homepage": "https://bankex.com/" }, - "marketcap_usd": 695246, + "marketcap_usd": 378892, "name": "BANKEX", "network": "eth", "shortcut": "BKX", @@ -3541,7 +3510,7 @@ "Github": "https://github.com/hellobloom", "Homepage": "https://hellobloom.io" }, - "marketcap_usd": 2572595, + "marketcap_usd": 1255657, "name": "Bloom", "network": "eth", "shortcut": "BLT", @@ -3561,7 +3530,7 @@ "Github": "https://github.com/BlueCrypto", "Homepage": "https://blueprotocol.com/" }, - "marketcap_usd": 287400, + "marketcap_usd": 228656, "name": "Ethereum Blue", "network": "eth", "shortcut": "BLUE", @@ -3619,7 +3588,7 @@ "links": { "Homepage": "https://bluzelle.com" }, - "marketcap_usd": 4388812, + "marketcap_usd": 1900372, "name": "Bluzelle", "network": "eth", "shortcut": "BLZ", @@ -3639,7 +3608,7 @@ "Github": "https://github.com/blackmoonfg", "Homepage": "https://blackmooncrypto.com" }, - "marketcap_usd": 4987000, + "marketcap_usd": 3120015, "name": "Blackmoon Crypto BMC Token", "network": "eth", "shortcut": "BMC", @@ -3678,7 +3647,7 @@ "links": { "Homepage": "https://www.bitmart.com" }, - "marketcap_usd": 3222743, + "marketcap_usd": 1580027, "name": "BitMart Token", "network": "eth", "shortcut": "BMX", @@ -3756,7 +3725,7 @@ "Github": "https://github.com/bancorprotocol", "Homepage": "https://www.bancor.network" }, - "marketcap_usd": 19554681, + "marketcap_usd": 10148139, "name": "Bancor Network Token", "network": "eth", "shortcut": "BNT", @@ -3775,7 +3744,7 @@ "links": { "Homepage": "https://bounty0x.io" }, - "marketcap_usd": 243832, + "marketcap_usd": 97527, "name": "Bounty0x Token", "network": "eth", "shortcut": "BNTY", @@ -3794,7 +3763,7 @@ "links": { "Homepage": "https://bobsrepair.com" }, - "marketcap_usd": 490020, + "marketcap_usd": 246114, "name": "Bob's repair", "network": "eth", "shortcut": "BOB", @@ -3852,7 +3821,7 @@ "links": { "Homepage": "https://www.bolt.global" }, - "marketcap_usd": 2086337, + "marketcap_usd": 634636, "name": "BOLT Token", "network": "eth", "shortcut": "BOLT", @@ -3871,7 +3840,7 @@ "links": { "Homepage": "https://bonpay.com" }, - "marketcap_usd": 96511, + "marketcap_usd": 95002, "name": "Bonpay", "network": "eth", "shortcut": "BON", @@ -3928,7 +3897,7 @@ "links": { "Homepage": "https://www.bouts.pro" }, - "marketcap_usd": 114266, + "marketcap_usd": 68206, "name": "BoutsPro", "network": "eth", "shortcut": "BOUTS", @@ -3947,7 +3916,7 @@ "links": { "Homepage": "https://www.goblockparty.com" }, - "marketcap_usd": 162777, + "marketcap_usd": 24307, "name": "BOXX Token [Blockparty]", "network": "eth", "shortcut": "BOXX", @@ -3967,7 +3936,7 @@ "Github": "https://github.com/Blockport/tokensale", "Homepage": "https://blockport.io" }, - "marketcap_usd": 1823097, + "marketcap_usd": 791010, "name": "Blockport Token", "network": "eth", "shortcut": "BPT", @@ -3986,7 +3955,7 @@ "links": { "Homepage": "https://www.bitquence.com" }, - "marketcap_usd": 10626635, + "marketcap_usd": 5071128, "name": "Bitquence", "network": "eth", "shortcut": "BQX", @@ -4005,7 +3974,7 @@ "links": { "Homepage": "http://bro-consortium.io" }, - "marketcap_usd": 1520, + "marketcap_usd": 1312, "name": "BROTHER", "network": "eth", "shortcut": "BRAT", @@ -4025,7 +3994,7 @@ "Github": "https://github.com/breadwallet", "Homepage": "https://token.breadapp.com/en" }, - "marketcap_usd": 20653573, + "marketcap_usd": 9237297, "name": "Bread", "network": "eth", "shortcut": "BRD", @@ -4140,7 +4109,7 @@ "links": { "Homepage": "http://btclite.org" }, - "marketcap_usd": 43292, + "marketcap_usd": 25730, "name": "BTC Lite", "network": "eth", "shortcut": "BTCL", @@ -4355,7 +4324,7 @@ "links": { "Homepage": "https://biotron.io" }, - "marketcap_usd": 11747, + "marketcap_usd": 6900, "name": "Biotron", "network": "eth", "shortcut": "BTRN", @@ -4375,7 +4344,7 @@ "Github": "https://github.com/btuprotocol", "Homepage": "https://btu-protocol.com" }, - "marketcap_usd": 13928061, + "marketcap_usd": 6941380, "name": "BTU Protocol", "network": "eth", "shortcut": "BTU", @@ -4434,7 +4403,7 @@ "Github": "https://github.com/paxosglobal/busd-contract", "Homepage": "https://www.paxos.com/busd" }, - "marketcap_usd": 69841647, + "marketcap_usd": 142356258, "name": "Binance USD (BUSD)", "network": "eth", "shortcut": "BUSD", @@ -4492,7 +4461,7 @@ "links": { "Homepage": "https://www.bitz.com" }, - "marketcap_usd": 22047983, + "marketcap_usd": 16101674, "name": "Bit-Z Token", "network": "eth", "shortcut": "BZ", @@ -4511,7 +4480,7 @@ "links": { "Homepage": "https://bezant.io" }, - "marketcap_usd": 3752129, + "marketcap_usd": 2751531, "name": "Bezant", "network": "eth", "shortcut": "BZNT", @@ -4551,7 +4520,7 @@ "Github": "https://github.com/cryptotwenty", "Homepage": "https://crypto20.com" }, - "marketcap_usd": 24319334, + "marketcap_usd": 12857556, "name": "Crypto20's Token", "network": "eth", "shortcut": "C20", @@ -4570,7 +4539,7 @@ "links": { "Homepage": "https://www.carboneum.io" }, - "marketcap_usd": 228061, + "marketcap_usd": 198974, "name": "Carboneum", "network": "eth", "shortcut": "C8", @@ -4589,7 +4558,7 @@ "links": { "Homepage": "https://change-bank.com" }, - "marketcap_usd": 2055955, + "marketcap_usd": 653149, "name": "Change Bank", "network": "eth", "shortcut": "CAG", @@ -4609,7 +4578,7 @@ "Github": "https://github.com/Global-Crypto-Alliance/call-token", "Homepage": "https://gcalliance.io" }, - "marketcap_usd": 16069, + "marketcap_usd": 45304, "name": "CALL token", "network": "eth", "shortcut": "CALL", @@ -4628,7 +4597,7 @@ "links": { "Homepage": "https://canya.io" }, - "marketcap_usd": 1803188, + "marketcap_usd": 1173365, "name": "CanYaCoin", "network": "eth", "shortcut": "CAN", @@ -4647,7 +4616,7 @@ "links": { "Homepage": "https://cappasity.com/tech/" }, - "marketcap_usd": 732425, + "marketcap_usd": 379135, "name": "Cappasity", "network": "eth", "shortcut": "CAPP", @@ -4723,7 +4692,7 @@ "links": { "Homepage": "https://coin.cashbet.com" }, - "marketcap_usd": 1297635, + "marketcap_usd": 786504, "name": "CashBet Coin", "network": "eth", "shortcut": "CBC", @@ -4762,7 +4731,7 @@ "links": { "Homepage": "https://www.commerceblock.com" }, - "marketcap_usd": 2938171, + "marketcap_usd": 1562018, "name": "CommerceBlock", "network": "eth", "shortcut": "CBT", @@ -4839,7 +4808,7 @@ "links": { "Homepage": "https://ccore.io" }, - "marketcap_usd": 17639, + "marketcap_usd": 9429, "name": "Ccore", "network": "eth", "shortcut": "CCO", @@ -4878,7 +4847,7 @@ "links": { "Homepage": "http://crystal-clear.io" }, - "marketcap_usd": 9174, + "marketcap_usd": 3160, "name": "Crystal Clear Token", "network": "eth", "shortcut": "CCT", @@ -4917,7 +4886,7 @@ "links": { "Homepage": "https://www.coindash.io" }, - "marketcap_usd": 3958141, + "marketcap_usd": 1707144, "name": "CoinDash", "network": "eth", "shortcut": "CDT", @@ -4936,7 +4905,7 @@ "links": { "Homepage": "https://www.ceek.com/" }, - "marketcap_usd": 792404, + "marketcap_usd": 805853, "name": "CEEK VR Token", "network": "eth", "shortcut": "CEEK", @@ -4956,7 +4925,7 @@ "Github": "https://github.com/celer-network", "Homepage": "https://www.celer.network/" }, - "marketcap_usd": 12377267, + "marketcap_usd": 4502558, "name": "CelerToken", "network": "eth", "shortcut": "CELR", @@ -4976,7 +4945,7 @@ "Github": "https://github.com/coinsuperapi", "Homepage": "https://www.coinsuper.com" }, - "marketcap_usd": 525693, + "marketcap_usd": 297844, "name": "CEN", "network": "eth", "shortcut": "CEN", @@ -4995,7 +4964,7 @@ "links": { "Homepage": "https://www.centrality.ai" }, - "marketcap_usd": 69646614, + "marketcap_usd": 39108740, "name": "Centrality", "network": "eth", "shortcut": "CENNZ", @@ -5112,7 +5081,7 @@ "links": { "Homepage": "https://coinpoker.com" }, - "marketcap_usd": 2138151, + "marketcap_usd": 1109175, "name": "CoinPoker", "network": "eth", "shortcut": "CHP", @@ -5131,7 +5100,7 @@ "links": { "Homepage": "https://swissborg.com" }, - "marketcap_usd": 16565453, + "marketcap_usd": 11944917, "name": "SwissBorg", "network": "eth", "shortcut": "CHSB", @@ -5208,7 +5177,7 @@ "links": { "Homepage": "https://www.connectjob.io" }, - "marketcap_usd": 43246, + "marketcap_usd": 11943, "name": "ConnectJob", "network": "eth", "shortcut": "CJT", @@ -5246,7 +5215,7 @@ "links": { "Homepage": "https://www.coinlancer.io" }, - "marketcap_usd": 99703, + "marketcap_usd": 21110, "name": "Coinlancer", "network": "eth", "shortcut": "CL", @@ -5266,7 +5235,7 @@ "Github": "https://github.com/Cloudbric-Project", "Homepage": "https://www.cloudbric.io/" }, - "marketcap_usd": 754925, + "marketcap_usd": 364509, "name": "Cloudbric", "network": "eth", "shortcut": "CLB", @@ -5382,7 +5351,7 @@ "links": { "Homepage": "https://crowdmachine.com" }, - "marketcap_usd": 205422, + "marketcap_usd": 123024, "name": "Crowd Machine Compute Token", "network": "eth", "shortcut": "CMCT", @@ -5440,7 +5409,7 @@ "links": { "Homepage": "https://cindicator.com" }, - "marketcap_usd": 11475515, + "marketcap_usd": 5078273, "name": "Cindicator", "network": "eth", "shortcut": "CND", @@ -5459,7 +5428,7 @@ "links": { "Homepage": "https://cnntoken.io" }, - "marketcap_usd": 3260581, + "marketcap_usd": 1378042, "name": "Content Neutrality Network", "network": "eth", "shortcut": "CNN", @@ -5518,7 +5487,7 @@ "Github": "https://github.com/cobinhood", "Homepage": "https://cobinhood.com" }, - "marketcap_usd": 146387, + "marketcap_usd": 87003, "name": "Cobinhood Token", "network": "eth", "shortcut": "COB", @@ -5558,7 +5527,7 @@ "Github": "https://github.com/coinfi", "Homepage": "https://www.coinfi.com" }, - "marketcap_usd": 303249, + "marketcap_usd": 147175, "name": "CoinFi Token", "network": "eth", "shortcut": "COFI", @@ -5635,7 +5604,7 @@ "links": { "Homepage": "https://covesting.io/" }, - "marketcap_usd": 2127309, + "marketcap_usd": 1145377, "name": "Covesting", "network": "eth", "shortcut": "COV", @@ -5674,7 +5643,7 @@ "links": { "Homepage": "https://cryptopay.me" }, - "marketcap_usd": 2535386, + "marketcap_usd": 1053537, "name": "Cryptopay", "network": "eth", "shortcut": "CPAY", @@ -5734,7 +5703,7 @@ "Github": "https://github.com/aditus", "Homepage": "https://copytrack.io" }, - "marketcap_usd": 512169, + "marketcap_usd": 0, "name": "COPYTRACK", "network": "eth", "shortcut": "CPY", @@ -5811,7 +5780,7 @@ "links": { "Homepage": "https://crycash.io" }, - "marketcap_usd": 1020222, + "marketcap_usd": 419332, "name": "CryCash", "network": "eth", "shortcut": "CRC", @@ -5831,7 +5800,7 @@ "Github": "https://github.com/verifyas", "Homepage": "https://token.verify.as" }, - "marketcap_usd": 105376, + "marketcap_usd": 58832, "name": "Verify", "network": "eth", "shortcut": "CRED", @@ -5850,7 +5819,7 @@ "links": { "Homepage": "https://bitbounce.io" }, - "marketcap_usd": 3905942, + "marketcap_usd": 5289246, "name": "Credo / Bitbounce", "network": "eth", "shortcut": "CREDO", @@ -5908,7 +5877,7 @@ "links": { "Homepage": "https://crypterium.io" }, - "marketcap_usd": 33173172, + "marketcap_usd": 18714645, "name": "CrypteriumToken", "network": "eth", "shortcut": "CRPT", @@ -5946,7 +5915,7 @@ "links": { "Homepage": "https://credits.com/en" }, - "marketcap_usd": 8891184, + "marketcap_usd": 4522781, "name": "Credits", "network": "eth", "shortcut": "CS", @@ -6140,7 +6109,7 @@ "links": { "Homepage": "https://www.civic.com" }, - "marketcap_usd": 18025800, + "marketcap_usd": 10943803, "name": "Civic", "network": "eth", "shortcut": "CVC", @@ -6179,7 +6148,7 @@ "links": { "Homepage": "http://www.cybervein.org" }, - "marketcap_usd": 4642095, + "marketcap_usd": 5856346, "name": "CyberVein", "network": "eth", "shortcut": "CVT", @@ -6219,7 +6188,7 @@ "Github": "https://github.com/cargoxio", "Homepage": "https://cargox.io" }, - "marketcap_usd": 1754655, + "marketcap_usd": 1031377, "name": "CargoX", "network": "eth", "shortcut": "CXO", @@ -6258,7 +6227,7 @@ "links": { "Homepage": "https://cyberfmradio.com" }, - "marketcap_usd": 81046, + "marketcap_usd": 9897, "name": "CyberFM", "network": "eth", "shortcut": "CYFM", @@ -6277,7 +6246,7 @@ "links": { "Homepage": "https://cybermusic.io" }, - "marketcap_usd": 18368, + "marketcap_usd": 9052, "name": "CyberMusic", "network": "eth", "shortcut": "CYMT", @@ -6296,7 +6265,7 @@ "links": { "Homepage": "http://www.canonchain.com" }, - "marketcap_usd": 1942595, + "marketcap_usd": 362326, "name": "CanonChain", "network": "eth", "shortcut": "CZR", @@ -6353,7 +6322,7 @@ "links": { "Homepage": "https://dacsee.io/#" }, - "marketcap_usd": 2922750, + "marketcap_usd": 1199982, "name": "DACSEE", "network": "eth", "shortcut": "DACS", @@ -6372,7 +6341,7 @@ "links": { "Homepage": "https://dadi.cloud" }, - "marketcap_usd": 2283997, + "marketcap_usd": 1126742, "name": "DADI", "network": "eth", "shortcut": "DADI", @@ -6392,7 +6361,7 @@ "Github": "https://github.com/makerdao", "Homepage": "https://makerdao.com" }, - "marketcap_usd": 121510652, + "marketcap_usd": 94662749, "name": "Dai Stablecoin v2.0", "network": "eth", "shortcut": "DAI", @@ -6411,7 +6380,7 @@ "links": { "Homepage": "http://www.dalecoin.org" }, - "marketcap_usd": 6115, + "marketcap_usd": 2658, "name": "DaleCoin", "network": "eth", "shortcut": "DALC", @@ -6431,7 +6400,7 @@ "Github": "https://github.com/project-daneel", "Homepage": "https://daneel.io" }, - "marketcap_usd": 22743, + "marketcap_usd": 11866, "name": "DaneelToken", "network": "eth", "shortcut": "DAN", @@ -6469,7 +6438,7 @@ "links": { "Homepage": "https://datum.org" }, - "marketcap_usd": 1012619, + "marketcap_usd": 512196, "name": "Datum Token", "network": "eth", "shortcut": "DAT", @@ -6489,7 +6458,7 @@ "Github": "https://github.com/streamr-dev", "Homepage": "https://www.streamr.com" }, - "marketcap_usd": 9659259, + "marketcap_usd": 4220036, "name": "Streamr DATAcoin", "network": "eth", "shortcut": "DATA", @@ -6528,7 +6497,7 @@ "links": { "Homepage": "https://www.datx.co" }, - "marketcap_usd": 477740, + "marketcap_usd": 213013, "name": "DATx", "network": "eth", "shortcut": "DATX", @@ -6548,7 +6517,7 @@ "Github": "https://github.com/DAVFoundation", "Homepage": "https://dav.network/" }, - "marketcap_usd": 115652, + "marketcap_usd": 52714, "name": "DAV Token", "network": "eth", "shortcut": "DAV", @@ -6567,7 +6536,7 @@ "links": { "Homepage": "https://www.daex.io" }, - "marketcap_usd": 1303014, + "marketcap_usd": 725191, "name": "DAEX", "network": "eth", "shortcut": "DAX", @@ -6606,7 +6575,7 @@ "Github": "https://github.com/chronologic", "Homepage": "https://chronologic.network" }, - "marketcap_usd": 239408, + "marketcap_usd": 113155, "name": "ChronoLogic DAY", "network": "eth", "shortcut": "DAY", @@ -6704,7 +6673,7 @@ "Github": "https://github.com/Dentacoin", "Homepage": "https://dentacoin.com" }, - "marketcap_usd": 11045513, + "marketcap_usd": 9603876, "name": "Dentacoin", "network": "eth", "shortcut": "DCN", @@ -6782,7 +6751,7 @@ "links": { "Homepage": "https://deltachain.tech" }, - "marketcap_usd": 7486, + "marketcap_usd": 9275, "name": "DeltaChain", "network": "eth", "shortcut": "DELTA", @@ -6801,7 +6770,7 @@ "links": { "Homepage": "https://www.dentwireless.com" }, - "marketcap_usd": 13608343, + "marketcap_usd": 7155384, "name": "DENT", "network": "eth", "shortcut": "DENT", @@ -6839,7 +6808,7 @@ "links": { "Homepage": "https://www.coinbit.co.kr/" }, - "marketcap_usd": 1822115, + "marketcap_usd": 871761, "name": "DEX", "network": "eth", "shortcut": "DEX", @@ -6878,7 +6847,7 @@ "links": { "Homepage": "https://digix.global/" }, - "marketcap_usd": 85990908, + "marketcap_usd": 42984796, "name": "Digix DAO", "network": "eth", "shortcut": "DGD", @@ -6938,7 +6907,7 @@ "Github": "https://github.com/DigitexFutures", "Homepage": "https://digitexfutures.com/" }, - "marketcap_usd": 27358782, + "marketcap_usd": 19637857, "name": "DigitexFutures", "network": "eth", "shortcut": "DGTX", @@ -6958,7 +6927,7 @@ "Github": "https://github.com/DigixGlobal", "Homepage": "https://digix.global" }, - "marketcap_usd": 6018620, + "marketcap_usd": 5679864, "name": "Digix Gold Token", "network": "eth", "shortcut": "DGX", @@ -6997,7 +6966,7 @@ "links": { "Homepage": "https://etheroll.com" }, - "marketcap_usd": 3147521, + "marketcap_usd": 1499560, "name": "Etheroll", "network": "eth", "shortcut": "DICE", @@ -7016,7 +6985,7 @@ "links": { "Homepage": "https://inmediate.io" }, - "marketcap_usd": 827470, + "marketcap_usd": 289244, "name": "Digital Insurance Token", "network": "eth", "shortcut": "DIT", @@ -7054,7 +7023,7 @@ "links": { "Homepage": "https://www.agrello.org" }, - "marketcap_usd": 3767050, + "marketcap_usd": 2034417, "name": "Agrello", "network": "eth", "shortcut": "DLT", @@ -7074,7 +7043,7 @@ "Github": "https://github.com/suntechsoft/dmarket-smartcontract", "Homepage": "https://dmarket.com" }, - "marketcap_usd": 8839167, + "marketcap_usd": 5814957, "name": "DMarket Token", "network": "eth", "shortcut": "DMT", @@ -7093,7 +7062,7 @@ "links": { "Homepage": "https://www.encrypgen.com" }, - "marketcap_usd": 836844, + "marketcap_usd": 570793, "name": "EncrypGen", "network": "eth", "shortcut": "DNA", @@ -7113,7 +7082,7 @@ "Github": "https://github.com/district0x", "Homepage": "https://district0x.io" }, - "marketcap_usd": 4220792, + "marketcap_usd": 1920002, "name": "District0x Network Token", "network": "eth", "shortcut": "DNT", @@ -7152,7 +7121,7 @@ "links": { "Homepage": "https://dock.io" }, - "marketcap_usd": 4250479, + "marketcap_usd": 1859367, "name": "Dock", "network": "eth", "shortcut": "DOCK", @@ -7190,7 +7159,7 @@ "links": { "Homepage": "https://dovu.io" }, - "marketcap_usd": 217490, + "marketcap_usd": 160675, "name": "Dovu", "network": "eth", "shortcut": "DOV", @@ -7249,7 +7218,7 @@ "links": { "Homepage": "https://dreamteam.gg" }, - "marketcap_usd": 3682920, + "marketcap_usd": 1427231, "name": "DREAM", "network": "eth", "shortcut": "DREAM", @@ -7269,7 +7238,7 @@ "Github": "https://github.com/dragonchain/dragonchain", "Homepage": "https://dragonchain.com" }, - "marketcap_usd": 15297639, + "marketcap_usd": 6340951, "name": "Dragon", "network": "eth", "shortcut": "DRGN", @@ -7307,7 +7276,7 @@ "links": { "Homepage": "https://token.domraider.com" }, - "marketcap_usd": 503154, + "marketcap_usd": 339135, "name": "DomRaider", "network": "eth", "shortcut": "DRT", @@ -7406,7 +7375,7 @@ "Github": "https://github.com/dethertech", "Homepage": "https://dether.io" }, - "marketcap_usd": 168853, + "marketcap_usd": 88079, "name": "dether", "network": "eth", "shortcut": "DTH", @@ -7425,7 +7394,7 @@ "links": { "Homepage": "https://www.tokens.net" }, - "marketcap_usd": 26941744, + "marketcap_usd": 15705361, "name": "Dynamic Trading Rights", "network": "eth", "shortcut": "DTR", @@ -7444,7 +7413,7 @@ "links": { "Homepage": "https://datarius.io" }, - "marketcap_usd": 38066, + "marketcap_usd": 19126, "name": "Datarius Credit", "network": "eth", "shortcut": "DTRC", @@ -7483,7 +7452,7 @@ "links": { "Homepage": "https://datawallet.com" }, - "marketcap_usd": 478507, + "marketcap_usd": 218343, "name": "Datawallet", "network": "eth", "shortcut": "DXT", @@ -7560,7 +7529,7 @@ "links": { "Homepage": "https://ebcoin.io" }, - "marketcap_usd": 497393, + "marketcap_usd": 216912, "name": "EBCoin", "network": "eth", "shortcut": "EBC", @@ -7637,7 +7606,7 @@ "links": { "Homepage": "https://omnitude.tech" }, - "marketcap_usd": 363930, + "marketcap_usd": 394246, "name": "Omnitude", "network": "eth", "shortcut": "ECOM", @@ -7675,7 +7644,7 @@ "links": { "Homepage": "https://edgeless.io" }, - "marketcap_usd": 1531798, + "marketcap_usd": 699657, "name": "Edgeless", "network": "eth", "shortcut": "EDG", @@ -7694,7 +7663,7 @@ "links": { "Homepage": "https://eidoo.io" }, - "marketcap_usd": 13964254, + "marketcap_usd": 5634483, "name": "Eidoo", "network": "eth", "shortcut": "EDO", @@ -7714,7 +7683,7 @@ "Github": "https://github.com/EndorCoin", "Homepage": "https://www.endor.com" }, - "marketcap_usd": 4900202, + "marketcap_usd": 3174626, "name": "Endor Protocol Token", "network": "eth", "shortcut": "EDR", @@ -7774,7 +7743,7 @@ "Github": "https://github.com/egretia", "Homepage": "https://www.egretia.io" }, - "marketcap_usd": 6723965, + "marketcap_usd": 2626521, "name": "Egretia Token", "network": "eth", "shortcut": "EGT", @@ -7832,7 +7801,7 @@ "links": { "Homepage": "https://echolink.info" }, - "marketcap_usd": 724899, + "marketcap_usd": 378423, "name": "EchoLink", "network": "eth", "shortcut": "EKO", @@ -7870,7 +7839,7 @@ "links": { "Homepage": "https://electrify.asia" }, - "marketcap_usd": 350688, + "marketcap_usd": 205848, "name": "Electrify.Asia", "network": "eth", "shortcut": "ELEC", @@ -7890,7 +7859,7 @@ "Github": "https://github.com/aelfProject", "Homepage": "https://aelf.io/" }, - "marketcap_usd": 48968670, + "marketcap_usd": 26864693, "name": "ELF Token", "network": "eth", "shortcut": "ELF", @@ -7929,7 +7898,7 @@ "Github": "https://github.com/eltcoin", "Homepage": "http://www.eltcoin.tech/" }, - "marketcap_usd": 18859, + "marketcap_usd": 7597, "name": "ELTCOIN", "network": "eth", "shortcut": "ELTCOIN", @@ -7949,7 +7918,7 @@ "Github": "https://github.com/Elysian-ELY", "Homepage": "https://elycoin.io" }, - "marketcap_usd": 48392, + "marketcap_usd": 34619, "name": "ELYCOIN", "network": "eth", "shortcut": "ELY", @@ -8087,7 +8056,7 @@ "Github": "https://github.com/enigmampc", "Homepage": "https://enigma.co/" }, - "marketcap_usd": 19226415, + "marketcap_usd": 6249722, "name": "Enigma", "network": "eth", "shortcut": "ENG", @@ -8106,7 +8075,7 @@ "links": { "Homepage": "https://engagementtoken.com" }, - "marketcap_usd": 12054, + "marketcap_usd": 5356, "name": "Engagement Token", "network": "eth", "shortcut": "ENGT", @@ -8126,7 +8095,7 @@ "Github": "https://github.com/enjin/contracts", "Homepage": "https://enjincoin.io" }, - "marketcap_usd": 85276951, + "marketcap_usd": 39544487, "name": "ENJIN", "network": "eth", "shortcut": "ENJ", @@ -8225,7 +8194,7 @@ "links": { "Homepage": "https://emphy.io" }, - "marketcap_usd": 81565, + "marketcap_usd": 17779, "name": "Emphy", "network": "eth", "shortcut": "EPY", @@ -8263,7 +8232,7 @@ "links": { "Homepage": "https://eroscoin.org" }, - "marketcap_usd": 382451, + "marketcap_usd": 148242, "name": "Eroscoin", "network": "eth", "shortcut": "ERO", @@ -8283,7 +8252,7 @@ "Github": "https://github.com/Krishtopa/ContractEristica", "Homepage": "https://eristica.com/" }, - "marketcap_usd": 364909, + "marketcap_usd": 173418, "name": "Eristica", "network": "eth", "shortcut": "ERT", @@ -8323,7 +8292,7 @@ "Github": "https://github.com/EtherSportz/ESZCoin", "Homepage": "https://ethersportz.com" }, - "marketcap_usd": 195813, + "marketcap_usd": 35533, "name": "ESZCoin", "network": "eth", "shortcut": "ESZ", @@ -8457,7 +8426,7 @@ "links": { "Homepage": "https://energitoken.com" }, - "marketcap_usd": 611227, + "marketcap_usd": 163106, "name": "EnergiToken", "network": "eth", "shortcut": "ETK", @@ -8517,7 +8486,7 @@ "Github": "https://github.com/stasisnet", "Homepage": "https://stasis.net" }, - "marketcap_usd": 35107888, + "marketcap_usd": 35013779, "name": "STASIS EURS", "network": "eth", "shortcut": "EURS", @@ -8555,7 +8524,7 @@ "links": { "Homepage": "https://eventchain.io" }, - "marketcap_usd": 90749, + "marketcap_usd": 42586, "name": "EventChain", "network": "eth", "shortcut": "EVC", @@ -8594,7 +8563,7 @@ "Github": "https://github.com/devery", "Homepage": "https://devery.io" }, - "marketcap_usd": 126383, + "marketcap_usd": 64645, "name": "Devery", "network": "eth", "shortcut": "EVE", @@ -8614,7 +8583,7 @@ "Github": "https://github.com/evedo-co", "Homepage": "https://www.evedo.co" }, - "marketcap_usd": 202406, + "marketcap_usd": 38421, "name": "Evedo Token", "network": "eth", "shortcut": "EVED", @@ -8673,7 +8642,7 @@ "links": { "Homepage": "https://everex.io " }, - "marketcap_usd": 5631323, + "marketcap_usd": 2533880, "name": "EVX Token", "network": "eth", "shortcut": "EVX", @@ -8771,7 +8740,7 @@ "links": { "Homepage": "https://exrnchain.com" }, - "marketcap_usd": 1522349, + "marketcap_usd": 651617, "name": "EXRNchain", "network": "eth", "shortcut": "EXRN", @@ -8810,7 +8779,7 @@ "links": { "Homepage": "https://experty.io/en" }, - "marketcap_usd": 804449, + "marketcap_usd": 444845, "name": "Experty", "network": "eth", "shortcut": "EXY", @@ -8887,7 +8856,7 @@ "links": { "Homepage": "https://tokensale.faceter.io" }, - "marketcap_usd": 441376, + "marketcap_usd": 280564, "name": "Faceter", "network": "eth", "shortcut": "FACE", @@ -8985,7 +8954,7 @@ "links": { "Homepage": "https://friendz.io" }, - "marketcap_usd": 966598, + "marketcap_usd": 400550, "name": "Friendz", "network": "eth", "shortcut": "FDZ", @@ -9104,7 +9073,7 @@ "Github": "https://github.com/FortKnoxster", "Homepage": "https://fortknoxster.com" }, - "marketcap_usd": 330435, + "marketcap_usd": 168669, "name": "Knoxstertoken", "network": "eth", "shortcut": "FKX", @@ -9123,7 +9092,7 @@ "links": { "Homepage": "https://www.flixxo.com" }, - "marketcap_usd": 498415, + "marketcap_usd": 306243, "name": "Flixxo", "network": "eth", "shortcut": "FLIXX", @@ -9142,7 +9111,7 @@ "links": { "Homepage": "https://firelotto.io" }, - "marketcap_usd": 122353, + "marketcap_usd": 63992, "name": "Fire Lotto", "network": "eth", "shortcut": "FLOT", @@ -9162,7 +9131,7 @@ "Github": "https://github.com/gameflip", "Homepage": "https://gameflip.com" }, - "marketcap_usd": 543083, + "marketcap_usd": 296123, "name": "FLIP Token", "network": "eth", "shortcut": "FLP", @@ -9278,7 +9247,7 @@ "links": { "Homepage": "https://www.foglink.io" }, - "marketcap_usd": 1283113, + "marketcap_usd": 299650, "name": "FNKOS", "network": "eth", "shortcut": "FNKOS", @@ -9297,7 +9266,7 @@ "links": { "Homepage": "https://fintab.io/ico" }, - "marketcap_usd": 12369, + "marketcap_usd": 4173, "name": "Fintab", "network": "eth", "shortcut": "FNTB", @@ -9317,7 +9286,7 @@ "Github": "https://github.com/f-o-a-m", "Homepage": "http://foam.space" }, - "marketcap_usd": 5776046, + "marketcap_usd": 3578841, "name": "FOAM Token", "network": "eth", "shortcut": "FOAM", @@ -9375,7 +9344,7 @@ "links": { "Homepage": "https://www.fota.io" }, - "marketcap_usd": 288305, + "marketcap_usd": 127351, "name": "Fortuna", "network": "eth", "shortcut": "FOTA", @@ -9511,7 +9480,7 @@ "links": { "Homepage": "https://fusion.org" }, - "marketcap_usd": 5348512, + "marketcap_usd": 3824255, "name": "Fusion", "network": "eth", "shortcut": "FSN", @@ -9549,7 +9518,7 @@ "links": { "Homepage": "https://fanstime.org" }, - "marketcap_usd": 763508, + "marketcap_usd": 286702, "name": "FansTime", "network": "eth", "shortcut": "FTI", @@ -9588,7 +9557,7 @@ "Github": "https://github.com/farmatrust", "Homepage": "https://www.farmatrust.io" }, - "marketcap_usd": 325173, + "marketcap_usd": 88062, "name": "FarmaTrust Token", "network": "eth", "shortcut": "FTT", @@ -9607,7 +9576,7 @@ "links": { "Homepage": "https://www.fintrux.com" }, - "marketcap_usd": 963344, + "marketcap_usd": 668929, "name": "FintruX Network", "network": "eth", "shortcut": "FTX", @@ -9627,7 +9596,7 @@ "Github": "https://github.com/futuraxproject", "Homepage": "https://futurax.global" }, - "marketcap_usd": 6256, + "marketcap_usd": 2436, "name": "FUTURAX", "network": "eth", "shortcut": "FTXT", @@ -9647,7 +9616,7 @@ "Github": "https://github.com/etherparty", "Homepage": "https://etherparty.io" }, - "marketcap_usd": 2760160, + "marketcap_usd": 1323055, "name": "Etherparty FUEL", "network": "eth", "shortcut": "FUEL", @@ -9666,7 +9635,7 @@ "links": { "Homepage": "https://funfair.io" }, - "marketcap_usd": 21043242, + "marketcap_usd": 9411593, "name": "Funfair", "network": "eth", "shortcut": "FUN", @@ -9685,7 +9654,7 @@ "links": { "Homepage": "https://fuzex.co" }, - "marketcap_usd": 527638, + "marketcap_usd": 290739, "name": "FuzeX", "network": "eth", "shortcut": "FXT", @@ -9743,7 +9712,7 @@ "links": { "Homepage": "https://flyp.me" }, - "marketcap_usd": 230863, + "marketcap_usd": 84458, "name": "FlypMe", "network": "eth", "shortcut": "FYP", @@ -10056,7 +10025,7 @@ "links": { "Homepage": "https://gems.org" }, - "marketcap_usd": 284429, + "marketcap_usd": 90733, "name": "Gems", "network": "eth", "shortcut": "GEM", @@ -10076,7 +10045,7 @@ "Github": "https://github.com/daostack", "Homepage": "https://daostack.io" }, - "marketcap_usd": 4403819, + "marketcap_usd": 1231815, "name": "DAOstack", "network": "eth", "shortcut": "GEN", @@ -10095,7 +10064,7 @@ "links": { "Homepage": "https://parkgene.io" }, - "marketcap_usd": 78337, + "marketcap_usd": 46793, "name": "Parkgene", "network": "eth", "shortcut": "GENE", @@ -10115,7 +10084,7 @@ "Github": "https://github.com/Getprotocol", "Homepage": "http://www.get-protocol.io" }, - "marketcap_usd": 3952063, + "marketcap_usd": 2335321, "name": "GET Protocol", "network": "eth", "shortcut": "GET", @@ -10270,7 +10239,7 @@ "links": { "Homepage": "https://gnosis.pm" }, - "marketcap_usd": 18740793, + "marketcap_usd": 10653346, "name": "Gnosis", "network": "eth", "shortcut": "GNO", @@ -10290,7 +10259,7 @@ "Github": "https://github.com/golemfactory/golem", "Homepage": "https://golem.network" }, - "marketcap_usd": 57608720, + "marketcap_usd": 29748309, "name": "Golem", "network": "eth", "shortcut": "GNT", @@ -10309,7 +10278,7 @@ "links": { "Homepage": "https://genaro.network" }, - "marketcap_usd": 2568432, + "marketcap_usd": 1024350, "name": "Genaro Network", "network": "eth", "shortcut": "GNX", @@ -10329,7 +10298,7 @@ "Github": "https://github.com/GNYIO", "Homepage": "https://www.gny.io/" }, - "marketcap_usd": 6497961, + "marketcap_usd": 3808510, "name": "GNY", "network": "eth", "shortcut": "GNY", @@ -10368,7 +10337,7 @@ "links": { "Homepage": "https://gonetwork.co/index.html" }, - "marketcap_usd": 356055, + "marketcap_usd": 137896, "name": "GoNetwork", "network": "eth", "shortcut": "GOT", @@ -10387,7 +10356,7 @@ "links": { "Homepage": "http://gridplus.io" }, - "marketcap_usd": 2059365, + "marketcap_usd": 1032100, "name": "Grid+", "network": "eth", "shortcut": "GRID", @@ -10465,7 +10434,7 @@ "links": { "Homepage": "https://www.gsc.social" }, - "marketcap_usd": 2732611, + "marketcap_usd": 1532501, "name": "Global Social Chain", "network": "eth", "shortcut": "GSC", @@ -10504,7 +10473,7 @@ "Github": "https://github.com/GameLeLe", "Homepage": "https://game.com" }, - "marketcap_usd": 3673115, + "marketcap_usd": 2502172, "name": "GTC Token", "network": "eth", "shortcut": "GTC", @@ -10544,7 +10513,7 @@ "Github": "https://github.com/GIFTO-io", "Homepage": "https://gifto.io/" }, - "marketcap_usd": 6146360, + "marketcap_usd": 8111679, "name": "Gifto", "network": "eth", "shortcut": "GTO", @@ -10563,7 +10532,7 @@ "links": { "Homepage": "https://peerguess.com" }, - "marketcap_usd": 5477, + "marketcap_usd": 5902, "name": "Peerguess", "network": "eth", "shortcut": "GUESS", @@ -10602,7 +10571,7 @@ "links": { "Homepage": "https://matchpool.co" }, - "marketcap_usd": 186980, + "marketcap_usd": 103995, "name": "Matchpool", "network": "eth", "shortcut": "GUP", @@ -10622,7 +10591,7 @@ "Github": "https://github.com/GenesisVision", "Homepage": "https://genesis.vision" }, - "marketcap_usd": 4856460, + "marketcap_usd": 2241543, "name": "Genesis Vision", "network": "eth", "shortcut": "GVT", @@ -10778,7 +10747,7 @@ "links": { "Homepage": "https://www.showhand.io" }, - "marketcap_usd": 13842, + "marketcap_usd": 5807, "name": "ShowHand", "network": "eth", "shortcut": "HAND", @@ -10835,7 +10804,7 @@ "links": { "Homepage": "https://heartbout.com" }, - "marketcap_usd": 109535, + "marketcap_usd": 45749, "name": "HeartBout", "network": "eth", "shortcut": "HB", @@ -10854,7 +10823,7 @@ "links": { "Homepage": "https://www.hubii.network" }, - "marketcap_usd": 1286875, + "marketcap_usd": 1110745, "name": "Hubii Network", "network": "eth", "shortcut": "HBT", @@ -10873,7 +10842,7 @@ "links": { "Homepage": "https://www.hbzcoin.com/#" }, - "marketcap_usd": 421959, + "marketcap_usd": 369286, "name": "HBZ coin", "network": "eth", "shortcut": "HBZ", @@ -10951,7 +10920,7 @@ "links": { "Homepage": "https://heronode.io" }, - "marketcap_usd": 61823, + "marketcap_usd": 29438, "name": "HeroNode", "network": "eth", "shortcut": "HER", @@ -10991,7 +10960,7 @@ "Github": "https://github.com/myHelloGold/Foundation", "Homepage": "https://www.hellogold.org" }, - "marketcap_usd": 172156, + "marketcap_usd": 146531, "name": "HelloGold", "network": "eth", "shortcut": "HGT", @@ -11087,7 +11056,7 @@ "links": { "Homepage": "https://hacken.io" }, - "marketcap_usd": 845511, + "marketcap_usd": 565065, "name": "Hacken", "network": "eth", "shortcut": "HKN", @@ -11145,7 +11114,7 @@ "links": { "Homepage": "https://humaniq.com" }, - "marketcap_usd": 966530, + "marketcap_usd": 469360, "name": "Humaniq", "network": "eth", "shortcut": "HMQ", @@ -11223,7 +11192,7 @@ "Github": "https://github.com/ethorse", "Homepage": "https://ethorse.com" }, - "marketcap_usd": 47496, + "marketcap_usd": 14380, "name": "Ethorse", "network": "eth", "shortcut": "HORSE", @@ -11243,7 +11212,7 @@ "Github": "https://github.com/Holo-Host", "Homepage": "https://holo.host/" }, - "marketcap_usd": 107133544, + "marketcap_usd": 50042585, "name": "Holo Token", "network": "eth", "shortcut": "HOT (Holo)", @@ -11262,7 +11231,7 @@ "links": { "Homepage": "https://thehydrofoundation.com/" }, - "marketcap_usd": 1602775, + "marketcap_usd": 811270, "name": "Hydro Protocol", "network": "eth", "shortcut": "HOT (Hydro)", @@ -11300,7 +11269,7 @@ "links": { "Homepage": "https://www.hbg.com" }, - "marketcap_usd": 990800213, + "marketcap_usd": 660966773, "name": "Huobi Token", "network": "eth", "shortcut": "HT", @@ -11359,7 +11328,7 @@ "Github": "https://github.com/HurifyPlatform", "Homepage": "https://hurify.co/" }, - "marketcap_usd": 57945, + "marketcap_usd": 28418, "name": "$Hurify Token", "network": "eth", "shortcut": "HUR", @@ -11399,7 +11368,7 @@ "Github": "https://github.com/HiveProjectLTD", "Homepage": "https://www.hiveterminal.com" }, - "marketcap_usd": 832771, + "marketcap_usd": 780298, "name": "Hiveterminal Token", "network": "eth", "shortcut": "HVN", @@ -11419,7 +11388,7 @@ "Github": "https://github.com/hydrogen-dev", "Homepage": "https://www.hydrogenplatform.com/hydro" }, - "marketcap_usd": 7076633, + "marketcap_usd": 2764215, "name": "Hydro", "network": "eth", "shortcut": "HYDRO", @@ -11592,7 +11561,7 @@ "links": { "Homepage": "https://indahash.com" }, - "marketcap_usd": 1204535, + "marketcap_usd": 529592, "name": "indaHash", "network": "eth", "shortcut": "IDH", @@ -11612,7 +11581,7 @@ "Github": "https://github.com/rupiah-token/", "Homepage": "https://www.rupiahtoken.com" }, - "marketcap_usd": 93056, + "marketcap_usd": 84730, "name": "Rupiah Token", "network": "eth", "shortcut": "IDRT", @@ -11631,7 +11600,7 @@ "links": { "Homepage": "https://investfeed.com" }, - "marketcap_usd": 73717, + "marketcap_usd": 30384, "name": "InvestFeed", "network": "eth", "shortcut": "IFT", @@ -11650,7 +11619,7 @@ "links": { "Homepage": "http://igtoken.net" }, - "marketcap_usd": 39795, + "marketcap_usd": 15917, "name": "IGToken", "network": "eth", "shortcut": "IG", @@ -11689,7 +11658,7 @@ "links": { "Homepage": "https://ihtcoin.com" }, - "marketcap_usd": 1470353, + "marketcap_usd": 711096, "name": "I HOUSE TOKEN", "network": "eth", "shortcut": "IHT", @@ -11766,7 +11735,7 @@ "links": { "Homepage": "https://indorse.io" }, - "marketcap_usd": 105668, + "marketcap_usd": 40693, "name": "Indorse", "network": "eth", "shortcut": "IND", @@ -11786,7 +11755,7 @@ "Github": "https://github.com/InfinitusToken/InfinitusToken", "Homepage": "https://inftech.io/ " }, - "marketcap_usd": 162796, + "marketcap_usd": 75660, "name": "InfinitusTokens", "network": "eth", "shortcut": "INF", @@ -11805,7 +11774,7 @@ "links": { "Homepage": "https://iungo.network" }, - "marketcap_usd": 46459, + "marketcap_usd": 16934, "name": "Iungo", "network": "eth", "shortcut": "ING", @@ -11843,7 +11812,7 @@ "links": { "Homepage": "https://insights.network" }, - "marketcap_usd": 2235189, + "marketcap_usd": 1119908, "name": "Insights Network", "network": "eth", "shortcut": "INSTAR", @@ -11901,7 +11870,7 @@ "Github": "https://github.com/InMax-Exchange", "Homepage": "https://inmax.live/ " }, - "marketcap_usd": 72465, + "marketcap_usd": 53507, "name": "Token INMAX", "network": "eth", "shortcut": "INX", @@ -11921,7 +11890,7 @@ "Github": "https://github.com/Internxt/", "Homepage": "https://internxt.com/" }, - "marketcap_usd": 628293, + "marketcap_usd": 378615, "name": "Internxt", "network": "eth", "shortcut": "INXT", @@ -11960,7 +11929,7 @@ "Github": "https://github.com/iotexproject/iotex-core", "Homepage": "http://iotex.io/" }, - "marketcap_usd": 23614779, + "marketcap_usd": 9654982, "name": "IoTeX Network", "network": "eth", "shortcut": "IOTX", @@ -11980,7 +11949,7 @@ "Github": "https://github.com/InsurePal", "Homepage": "https://insurepal.io/" }, - "marketcap_usd": 1327648, + "marketcap_usd": 484526, "name": "InsurePal token", "network": "eth", "shortcut": "IPL", @@ -11999,7 +11968,7 @@ "links": { "Homepage": "https://ip.sx" }, - "marketcap_usd": 276651, + "marketcap_usd": 99924, "name": "IP Exchange", "network": "eth", "shortcut": "IPSX", @@ -12019,7 +11988,7 @@ "Github": "https://github.com/iqeon", "Homepage": "https://iqeon.io/" }, - "marketcap_usd": 3934166, + "marketcap_usd": 5378154, "name": "IQeon", "network": "eth", "shortcut": "IQN", @@ -12079,7 +12048,7 @@ "Github": "https://github.com/IoTChainCode", "Homepage": "https://iotchain.io/" }, - "marketcap_usd": 10830389, + "marketcap_usd": 5725576, "name": "IoT Chain", "network": "eth", "shortcut": "ITC", @@ -12138,7 +12107,7 @@ "links": { "Homepage": "https://www.ivykoin.com" }, - "marketcap_usd": 642191, + "marketcap_usd": 3319792, "name": "IvyKoin Public Network Tokens", "network": "eth", "shortcut": "IVY", @@ -12157,7 +12126,7 @@ "links": { "Homepage": "https://www.insurex.co" }, - "marketcap_usd": 260107, + "marketcap_usd": 101118, "name": "InsureX", "network": "eth", "shortcut": "IXT", @@ -12196,7 +12165,7 @@ "Github": "https://github.com/jet8", "Homepage": "https://jet8.io" }, - "marketcap_usd": 316910, + "marketcap_usd": 118739, "name": "J8T Token", "network": "eth", "shortcut": "J8T", @@ -12273,7 +12242,7 @@ "Github": "https://github.com/jibrelnetwork", "Homepage": "https://jibrel.network" }, - "marketcap_usd": 5227457, + "marketcap_usd": 3738211, "name": "Jibrel Network", "network": "eth", "shortcut": "JNT", @@ -12293,7 +12262,7 @@ "Github": "https://github.com/JobchainOfficial", "Homepage": "https://www.jobchain.com" }, - "marketcap_usd": 15372, + "marketcap_usd": 0, "name": "JOBCHAIN", "network": "eth", "shortcut": "JOB", @@ -12351,7 +12320,7 @@ "Github": "https://github.com/jsecoin", "Homepage": "https://jsecoin.com" }, - "marketcap_usd": 73104, + "marketcap_usd": 36715, "name": "JSE Token", "network": "eth", "shortcut": "JSE", @@ -12370,7 +12339,7 @@ "links": { "Homepage": "http://www.kan.land" }, - "marketcap_usd": 14920689, + "marketcap_usd": 9459837, "name": "BitKan", "network": "eth", "shortcut": "KAN", @@ -12448,7 +12417,7 @@ "links": { "Homepage": "https://kindads.io" }, - "marketcap_usd": 38801, + "marketcap_usd": 24059, "name": "Kind Ads Token", "network": "eth", "shortcut": "KIND", @@ -12487,7 +12456,7 @@ "Github": "https://github.com/KyberNetwork", "Homepage": "https://kyber.network" }, - "marketcap_usd": 97893330, + "marketcap_usd": 80325528, "name": "Kyber Network", "network": "eth", "shortcut": "KNC", @@ -12506,7 +12475,7 @@ "links": { "Homepage": "https://kanadecoin.com" }, - "marketcap_usd": 51535, + "marketcap_usd": 57730, "name": "KanadeCoin", "network": "eth", "shortcut": "KNDC", @@ -12525,7 +12494,7 @@ "links": { "Homepage": "https://kora.network" }, - "marketcap_usd": 13436, + "marketcap_usd": 6689, "name": "Kora Network Token", "network": "eth", "shortcut": "KNT", @@ -12584,7 +12553,7 @@ "Github": "https://github.com/Cryptense/", "Homepage": "https://kryll.io/" }, - "marketcap_usd": 1381037, + "marketcap_usd": 833690, "name": "Kryll", "network": "eth", "shortcut": "KRL", @@ -12643,7 +12612,7 @@ "links": { "Homepage": "https://ico.kuende.com" }, - "marketcap_usd": 33403, + "marketcap_usd": 26502, "name": "Kuende Token", "network": "eth", "shortcut": "KUE", @@ -12662,7 +12631,7 @@ "links": { "Homepage": "https://4new.io" }, - "marketcap_usd": 16560, + "marketcap_usd": 7098, "name": "4NEW", "network": "eth", "shortcut": "KWATT", @@ -12720,7 +12689,7 @@ "Github": "https://github.com/latoken", "Homepage": "https://latoken.com/" }, - "marketcap_usd": 20157850, + "marketcap_usd": 11657299, "name": "LATOKEN", "network": "eth", "shortcut": "LA", @@ -12759,7 +12728,7 @@ "Github": "https://github.com/LambdaIM", "Homepage": "https://www.lambda.im/" }, - "marketcap_usd": 17389800, + "marketcap_usd": 7447987, "name": "Lambda", "network": "eth", "shortcut": "LAMB", @@ -12797,7 +12766,7 @@ "links": { "Homepage": "https://www.mycred.io" }, - "marketcap_usd": 12792368, + "marketcap_usd": 7803185, "name": "Cred", "network": "eth", "shortcut": "LBA", @@ -12816,7 +12785,7 @@ "links": { "Homepage": "https://www.localcoinswap.com" }, - "marketcap_usd": 193800, + "marketcap_usd": 129229, "name": "LocalCoinSwap", "network": "eth", "shortcut": "LCS", @@ -12835,7 +12804,7 @@ "links": { "Homepage": "https://www.leadcoin.network/" }, - "marketcap_usd": 37336, + "marketcap_usd": 24646, "name": "LEADCOIN", "network": "eth", "shortcut": "LDC", @@ -12875,7 +12844,7 @@ "Github": "https://github.com/livecodingtvofficial", "Homepage": "https://ledu.education-ecosystem.com" }, - "marketcap_usd": 859083, + "marketcap_usd": 0, "name": "Education Ecosystem", "network": "eth", "shortcut": "LEDU", @@ -12895,7 +12864,7 @@ "Github": "https://github.com/ETHLend", "Homepage": "https://ethlend.io/" }, - "marketcap_usd": 36077464, + "marketcap_usd": 22834921, "name": "EHTLend", "network": "eth", "shortcut": "LEND", @@ -12914,7 +12883,7 @@ "links": { "Homepage": "https://www.leocoin.org/" }, - "marketcap_usd": 370239, + "marketcap_usd": 238753, "name": "LEOcoin", "network": "eth", "shortcut": "LEO", @@ -12933,7 +12902,7 @@ "links": { "Homepage": "https://www.leverj.io" }, - "marketcap_usd": 1767193, + "marketcap_usd": 802282, "name": "Leverj", "network": "eth", "shortcut": "LEV", @@ -12990,7 +12959,7 @@ "links": { "Homepage": "http://legendsroomlv.com" }, - "marketcap_usd": 47535, + "marketcap_usd": 24344, "name": "Legends", "network": "eth", "shortcut": "LGD", @@ -13068,7 +13037,7 @@ "Github": "https://github.com/windingtree", "Homepage": "https://windingtree.com/" }, - "marketcap_usd": 3622068, + "marketcap_usd": 1342912, "name": "Winding Tree", "network": "eth", "shortcut": "LIF", @@ -13087,7 +13056,7 @@ "links": { "Homepage": "http://www.lifelabs.io" }, - "marketcap_usd": 1566651, + "marketcap_usd": 646610, "name": "LIFE", "network": "eth", "shortcut": "LIFE", @@ -13126,7 +13095,7 @@ "links": { "Homepage": "https://link.smartcontract.com" }, - "marketcap_usd": 1394620235, + "marketcap_usd": 692178756, "name": "Chainlink", "network": "eth", "shortcut": "LINK (Chainlink)", @@ -13164,7 +13133,7 @@ "links": { "Homepage": "https://www.linkey.info" }, - "marketcap_usd": 4245391, + "marketcap_usd": 723937, "name": "Linkey", "network": "eth", "shortcut": "LKY", @@ -13184,7 +13153,7 @@ "Github": "https://github.com/GNYIO", "Homepage": "https://www.gny.io/lisk" }, - "marketcap_usd": 608630, + "marketcap_usd": 571390, "name": "Lisk Machine Learning", "network": "eth", "shortcut": "LML", @@ -13204,7 +13173,7 @@ "Github": "https://github.com/lendingblock", "Homepage": "https://lendingblock.com" }, - "marketcap_usd": 1617043, + "marketcap_usd": 637885, "name": "Lendingblock", "network": "eth", "shortcut": "LND", @@ -13223,7 +13192,7 @@ "links": { "Homepage": "https://LockChain.co" }, - "marketcap_usd": 6280815, + "marketcap_usd": 3240705, "name": "LockChain", "network": "eth", "shortcut": "LOC", @@ -13243,7 +13212,7 @@ "Github": "http://github.com/locipro/loci-coin-sale", "Homepage": "https://locipro.com" }, - "marketcap_usd": 29782, + "marketcap_usd": 15440, "name": "LOCIcoin", "network": "eth", "shortcut": "LOCI", @@ -13262,7 +13231,7 @@ "links": { "Homepage": "https://www.locuschain.com" }, - "marketcap_usd": 985521, + "marketcap_usd": 2814817, "name": "Locus Chain", "network": "eth", "shortcut": "LOCUS", @@ -13320,7 +13289,7 @@ "Github": "github.com/loomnetwork/", "Homepage": "https://loomx.io" }, - "marketcap_usd": 20253985, + "marketcap_usd": 11898376, "name": "Loom Network", "network": "eth", "shortcut": "LOOM", @@ -13359,7 +13328,7 @@ "links": { "Homepage": "https://liquidity.network/" }, - "marketcap_usd": 1129372, + "marketcap_usd": 698724, "name": "Liquidity Network Token", "network": "eth", "shortcut": "LQD", @@ -13379,7 +13348,7 @@ "Github": "https://github.com/loopring", "Homepage": "https://loopring.org" }, - "marketcap_usd": 38492458, + "marketcap_usd": 27018877, "name": "Loopring", "network": "eth", "shortcut": "LRC", @@ -13399,7 +13368,7 @@ "Github": "https://github.com/Play2Live/blockchain", "Homepage": "https://play2live.io" }, - "marketcap_usd": 82863, + "marketcap_usd": 46171, "name": "LUCToken", "network": "eth", "shortcut": "LUC", @@ -13457,7 +13426,7 @@ "Github": "https://github.com/lunyr", "Homepage": "https://lunyr.com" }, - "marketcap_usd": 2212963, + "marketcap_usd": 1031403, "name": "Lunyr", "network": "eth", "shortcut": "LUN", @@ -13575,7 +13544,7 @@ "Github": "https://github.com/decentraland", "Homepage": "https://decentraland.org" }, - "marketcap_usd": 44310877, + "marketcap_usd": 23397464, "name": "Decentraland MANA", "network": "eth", "shortcut": "MANA", @@ -13613,7 +13582,7 @@ "links": { "Homepage": "https://midasprotocol.io/" }, - "marketcap_usd": 823067, + "marketcap_usd": 489394, "name": "MIDAS PROTOCOL", "network": "eth", "shortcut": "MAS", @@ -13691,7 +13660,7 @@ "links": { "Homepage": "https://crypto.com" }, - "marketcap_usd": 81543584, + "marketcap_usd": 46366740, "name": "Crypto.com", "network": "eth", "shortcut": "MCO", @@ -13710,7 +13679,7 @@ "links": { "Homepage": "https://moedaseeds.com" }, - "marketcap_usd": 11376977, + "marketcap_usd": 5317121, "name": "Moeda Loyalty Points", "network": "eth", "shortcut": "MDA", @@ -13729,7 +13698,7 @@ "links": { "Homepage": "https://www.mdt.co" }, - "marketcap_usd": 3884902, + "marketcap_usd": 2168486, "name": "Measurable Data Token", "network": "eth", "shortcut": "MDT", @@ -13768,7 +13737,7 @@ "Github": "https://github.com/mesg-foundation", "Homepage": "https://mesg.com" }, - "marketcap_usd": 589882, + "marketcap_usd": 319711, "name": "MESG", "network": "eth", "shortcut": "MESG", @@ -13807,7 +13776,7 @@ "links": { "Homepage": "https://www.metronome.io" }, - "marketcap_usd": 5441908, + "marketcap_usd": 2886954, "name": "Metronome", "network": "eth", "shortcut": "MET", @@ -13826,7 +13795,7 @@ "links": { "Homepage": "https://metamorph.pro" }, - "marketcap_usd": 133092, + "marketcap_usd": 48740, "name": "MetaMorph", "network": "eth", "shortcut": "METM", @@ -13846,7 +13815,7 @@ "Github": "https://github.com/syncfab", "Homepage": "https://syncfab.com/" }, - "marketcap_usd": 381771, + "marketcap_usd": 340599, "name": "SyncFab Smart Manufacturing Blockchain", "network": "eth", "shortcut": "MFG", @@ -13866,7 +13835,7 @@ "Github": "https://github.com/MainframeHQ", "Homepage": "https://mainframe.com" }, - "marketcap_usd": 8361254, + "marketcap_usd": 5093143, "name": "Mainframe Token", "network": "eth", "shortcut": "MFT", @@ -13885,7 +13854,7 @@ "links": { "Homepage": "https://mftu.net" }, - "marketcap_usd": 81018, + "marketcap_usd": 10620, "name": "Mainstream For The Underground", "network": "eth", "shortcut": "MFTU", @@ -13904,7 +13873,7 @@ "links": { "Homepage": "https://mobilego.io" }, - "marketcap_usd": 768429, + "marketcap_usd": 644879, "name": "MobileGo", "network": "eth", "shortcut": "MGO", @@ -13981,7 +13950,7 @@ "links": { "Homepage": "https://token.morpheuslabs.io" }, - "marketcap_usd": 1986075, + "marketcap_usd": 857823, "name": "Morpheus Infrastructure Token", "network": "eth", "shortcut": "MITX", @@ -14001,7 +13970,7 @@ "Github": "https://github.com/makerdao", "Homepage": "https://makerdao.com" }, - "marketcap_usd": 573446810, + "marketcap_usd": 207551876, "name": "MakerDAO", "network": "eth", "shortcut": "MKR", @@ -14040,7 +14009,7 @@ "links": { "Homepage": "https://melonport.com" }, - "marketcap_usd": 5434079, + "marketcap_usd": 2863138, "name": "Melonport", "network": "eth", "shortcut": "MLN (new)", @@ -14059,7 +14028,7 @@ "links": { "Homepage": "https://minereum.com" }, - "marketcap_usd": 83123, + "marketcap_usd": 62899, "name": "Minereum", "network": "eth", "shortcut": "MNE", @@ -14118,7 +14087,7 @@ "links": { "Homepage": "https://moss.land" }, - "marketcap_usd": 7404750, + "marketcap_usd": 5108535, "name": "Moss Coin", "network": "eth", "shortcut": "MOC", @@ -14195,7 +14164,7 @@ "links": { "Homepage": "https://mark.space" }, - "marketcap_usd": 594456, + "marketcap_usd": 204803, "name": "MARK.SPACE", "network": "eth", "shortcut": "MRK", @@ -14291,7 +14260,7 @@ "links": { "Homepage": "http://www.monetha.io" }, - "marketcap_usd": 3934663, + "marketcap_usd": 1715981, "name": "Monetha", "network": "eth", "shortcut": "MTH", @@ -14310,7 +14279,7 @@ "links": { "Homepage": "https://www.metalpay.com" }, - "marketcap_usd": 19073371, + "marketcap_usd": 10465618, "name": "Metal", "network": "eth", "shortcut": "MTL", @@ -14329,7 +14298,7 @@ "links": { "Homepage": "https://medicalchain.com" }, - "marketcap_usd": 981145, + "marketcap_usd": 638158, "name": "MedToken", "network": "eth", "shortcut": "MTN", @@ -14386,7 +14355,7 @@ "links": { "Homepage": "https://www.matryx.ai" }, - "marketcap_usd": 546092, + "marketcap_usd": 290868, "name": "Matryx", "network": "eth", "shortcut": "MTX", @@ -14463,7 +14432,7 @@ "links": { "Homepage": "http://mvlchain.io" }, - "marketcap_usd": 2108522, + "marketcap_usd": 1548054, "name": "Mass Vehicle Ledger Token", "network": "eth", "shortcut": "MVL", @@ -14483,7 +14452,7 @@ "Github": "https://github.com/Merculet", "Homepage": "https://www.merculet.io" }, - "marketcap_usd": 543697, + "marketcap_usd": 213871, "name": "Merculet", "network": "eth", "shortcut": "MVP", @@ -14502,7 +14471,7 @@ "links": { "Homepage": "https://www.restartenergy.io" }, - "marketcap_usd": 3241848, + "marketcap_usd": 974808, "name": "RED MWAT", "network": "eth", "shortcut": "MWAT", @@ -14521,7 +14490,7 @@ "links": { "Homepage": "https://mysterium.network" }, - "marketcap_usd": 1397002, + "marketcap_usd": 750846, "name": "Mysterium", "network": "eth", "shortcut": "MYST", @@ -14560,7 +14529,7 @@ "Github": "https://github.com/NANJ-COIN", "Homepage": "https://nanjcoin.com/" }, - "marketcap_usd": 318948, + "marketcap_usd": 158899, "name": "NANJCOIN", "network": "eth", "shortcut": "NANJ", @@ -14638,7 +14607,7 @@ "links": { "Homepage": "https://niobiumcoin.io" }, - "marketcap_usd": 824998, + "marketcap_usd": 499433, "name": "Niobium Coin", "network": "eth", "shortcut": "NBC", @@ -14657,7 +14626,7 @@ "links": { "Homepage": "https://nucleus.vision" }, - "marketcap_usd": 5647816, + "marketcap_usd": 2204199, "name": "Nucleus Vision", "network": "eth", "shortcut": "NCASH", @@ -14677,7 +14646,7 @@ "Github": "https://github.com/polyswarm", "Homepage": "https://polyswarm.io" }, - "marketcap_usd": 2937121, + "marketcap_usd": 1163433, "name": "Nectar", "network": "eth", "shortcut": "NCT", @@ -14716,7 +14685,7 @@ "Github": "https://github.com/ndexnetwork/NDX", "Homepage": "https://ndexnetwork.com" }, - "marketcap_usd": 3530, + "marketcap_usd": 1757, "name": "nDEX", "network": "eth", "shortcut": "NDX", @@ -14736,7 +14705,7 @@ "Github": "https://github.com/ethfinex/", "Homepage": "https://nectar.community" }, - "marketcap_usd": 5256764, + "marketcap_usd": 4298026, "name": "Ethfinex Nectar Token", "network": "eth", "shortcut": "NEC", @@ -14794,7 +14763,7 @@ "Github": "https://github.com/neufund", "Homepage": "https://neufund.org" }, - "marketcap_usd": 4365461, + "marketcap_usd": 3814019, "name": "NEU Fund", "network": "eth", "shortcut": "NEU", @@ -14813,7 +14782,7 @@ "links": { "Homepage": "http://nexo.io" }, - "marketcap_usd": 88874044, + "marketcap_usd": 49477157, "name": "Nexo", "network": "eth", "shortcut": "NEXO", @@ -14832,7 +14801,7 @@ "links": { "Homepage": "https://www.nagaico.com" }, - "marketcap_usd": 1051257, + "marketcap_usd": 628217, "name": "NAGA Coin", "network": "eth", "shortcut": "NGC", @@ -14912,7 +14881,7 @@ "Github": "https://github.com/numerai", "Homepage": "https://numer.ai" }, - "marketcap_usd": 17272629, + "marketcap_usd": 11908902, "name": "Numerai", "network": "eth", "shortcut": "NMR", @@ -14932,7 +14901,7 @@ "Github": "https://github.com/NoahFoundation/NoahCoin", "Homepage": "https://noahcoin.org" }, - "marketcap_usd": 43768744, + "marketcap_usd": 0, "name": "Noah Coin", "network": "eth", "shortcut": "NOAH", @@ -14951,7 +14920,7 @@ "links": { "Homepage": "https://nobscrypto.com" }, - "marketcap_usd": 62557, + "marketcap_usd": 31897, "name": "No BS Crypto", "network": "eth", "shortcut": "NOBS", @@ -14971,7 +14940,7 @@ "Github": "https://github.com/nitrotoken/nitro-crowdsale", "Homepage": "https://nitro.live" }, - "marketcap_usd": 26867, + "marketcap_usd": 15940, "name": "Nitro", "network": "eth", "shortcut": "NOX", @@ -15010,7 +14979,7 @@ "links": { "Homepage": "https://napoleonx.ai" }, - "marketcap_usd": 1889237, + "marketcap_usd": 2081551, "name": "NaPoleonX", "network": "eth", "shortcut": "NPX", @@ -15030,7 +14999,7 @@ "Github": "https://github.com/pundix", "Homepage": "https://pundix.com" }, - "marketcap_usd": 41377265, + "marketcap_usd": 24104830, "name": "Pundi X Token", "network": "eth", "shortcut": "NPXS", @@ -15088,7 +15057,7 @@ "links": { "Homepage": "https://nuggets.life/" }, - "marketcap_usd": 1218537, + "marketcap_usd": 1193135, "name": "Nuggets Token", "network": "eth", "shortcut": "NUG", @@ -15166,7 +15135,7 @@ "Github": "https://github.com/NeutralGroup", "Homepage": "https://neutralproject.com" }, - "marketcap_usd": 80148, + "marketcap_usd": 80187, "name": "Neutral Dollar", "network": "eth", "shortcut": "NUSD", @@ -15242,7 +15211,7 @@ "links": { "Homepage": "https://www.openanx.org/en" }, - "marketcap_usd": 3848424, + "marketcap_usd": 1715100, "name": "OAX", "network": "eth", "shortcut": "OAX", @@ -15281,7 +15250,7 @@ "links": { "Homepage": "http://www.ocnex.net" }, - "marketcap_usd": 2770646, + "marketcap_usd": 1417923, "name": "Odyssey", "network": "eth", "shortcut": "OCN", @@ -15301,7 +15270,7 @@ "Github": "https://github.com/odemio", "Homepage": "https://odem.io/" }, - "marketcap_usd": 10921769, + "marketcap_usd": 7488539, "name": "ODEM Token", "network": "eth", "shortcut": "ODE", @@ -15341,7 +15310,7 @@ "Github": "https://github.com/originprotocol", "Homepage": "https://www.originprotocol.com" }, - "marketcap_usd": 8251130, + "marketcap_usd": 6182250, "name": "OriginToken", "network": "eth", "shortcut": "OGN", @@ -15440,7 +15409,7 @@ "Github": "https://github.com/Oneledger", "Homepage": "https://oneledger.io" }, - "marketcap_usd": 2884903, + "marketcap_usd": 832612, "name": "OneLedger Token", "network": "eth", "shortcut": "OLT", @@ -15460,7 +15429,7 @@ "Github": "https://github.com/omisego", "Homepage": "https://omg.omise.co" }, - "marketcap_usd": 131036666, + "marketcap_usd": 64992556, "name": "OmiseGO", "network": "eth", "shortcut": "OMG", @@ -15499,7 +15468,7 @@ "links": { "Homepage": "https://shivom.io" }, - "marketcap_usd": 1571653, + "marketcap_usd": 543389, "name": "Shivom", "network": "eth", "shortcut": "OMX", @@ -15519,7 +15488,7 @@ "Github": "https://github.com/MenloOne/", "Homepage": "https://www.menlo.one" }, - "marketcap_usd": 45406, + "marketcap_usd": 22040, "name": "Menlo One", "network": "eth", "shortcut": "ONE", @@ -15558,7 +15527,7 @@ "Github": "https://github.com/onGsocial", "Homepage": "https://somee.social" }, - "marketcap_usd": 161555, + "marketcap_usd": 150904, "name": "SoMee.Social", "network": "eth", "shortcut": "ONG", @@ -15577,7 +15546,7 @@ "links": { "Homepage": "https://on.live" }, - "marketcap_usd": 305810, + "marketcap_usd": 151066, "name": "On.Live", "network": "eth", "shortcut": "ONL", @@ -15596,7 +15565,7 @@ "links": { "Homepage": "https://www.ono.chat" }, - "marketcap_usd": 127969, + "marketcap_usd": 132317, "name": "ONO Token", "network": "eth", "shortcut": "ONOT", @@ -15616,7 +15585,7 @@ "Github": "https://github.com/opacity", "Homepage": "https://opacity.io" }, - "marketcap_usd": 1401029, + "marketcap_usd": 697874, "name": "Opacity", "network": "eth", "shortcut": "OPQ", @@ -15635,7 +15604,7 @@ "links": { "Homepage": "https://opus-foundation.org" }, - "marketcap_usd": 71845, + "marketcap_usd": 177771, "name": "Opus Foundation", "network": "eth", "shortcut": "OPT", @@ -15654,7 +15623,7 @@ "links": { "Homepage": "https://optitoken.io" }, - "marketcap_usd": 220084, + "marketcap_usd": 118913, "name": "OptiToken", "network": "eth", "shortcut": "OPTI", @@ -15693,7 +15662,7 @@ "Github": "https://github.com/orbs-network", "Homepage": "https://orbs.com" }, - "marketcap_usd": 26216962, + "marketcap_usd": 16216809, "name": "Orbs", "network": "eth", "shortcut": "ORBS", @@ -15732,7 +15701,7 @@ "links": { "Homepage": "https://ori.network" }, - "marketcap_usd": 24423, + "marketcap_usd": 10405, "name": "Origami", "network": "eth", "shortcut": "ORI", @@ -15751,7 +15720,7 @@ "links": { "Homepage": "https://www.originsport.io" }, - "marketcap_usd": 1768951, + "marketcap_usd": 610909, "name": "Origin Sport", "network": "eth", "shortcut": "ORS", @@ -15810,7 +15779,7 @@ "Github": "https://github.com/OpenSTFoundation", "Homepage": "https://simpletoken.org" }, - "marketcap_usd": 8328457, + "marketcap_usd": 5435820, "name": "Simple Token 'OST'", "network": "eth", "shortcut": "OST", @@ -15829,7 +15798,7 @@ "links": { "Homepage": "https://otn.org" }, - "marketcap_usd": 18928, + "marketcap_usd": 9428, "name": "Open Trading Network", "network": "eth", "shortcut": "OTN", @@ -15869,7 +15838,7 @@ "Github": "https://github.com/owndata", "Homepage": "https://owndata.network" }, - "marketcap_usd": 629463, + "marketcap_usd": 304494, "name": "OWNDATA", "network": "eth", "shortcut": "OWN", @@ -15948,7 +15917,7 @@ "links": { "Homepage": "https://www.pchain.org" }, - "marketcap_usd": 1579232, + "marketcap_usd": 899509, "name": "PCHAIN", "network": "eth", "shortcut": "PAI", @@ -16007,7 +15976,7 @@ "links": { "Homepage": "https://patron-influencers.com" }, - "marketcap_usd": 25925, + "marketcap_usd": 34363, "name": "Patron", "network": "eth", "shortcut": "PAT", @@ -16086,7 +16055,7 @@ "Github": "https://github.com/paxosglobal", "Homepage": "https://www.paxos.com/standard" }, - "marketcap_usd": 201975161, + "marketcap_usd": 222473810, "name": "Paxos Standard (PAX)", "network": "eth", "shortcut": "PAX", @@ -16106,7 +16075,7 @@ "Github": "https://github.com/paxosglobal/paxos-gold-contract", "Homepage": "https://www.paxos.com/paxgold" }, - "marketcap_usd": 17355127, + "marketcap_usd": 17357920, "name": "Paxos Gold", "network": "eth", "shortcut": "PAXG", @@ -16125,7 +16094,7 @@ "links": { "Homepage": "http://www.tenx.tech" }, - "marketcap_usd": 7155124, + "marketcap_usd": 3487114, "name": "TenX", "network": "eth", "shortcut": "PAY", @@ -16183,7 +16152,7 @@ "Github": "https://github.com/Peculium-Dev/", "Homepage": "https://peculium.io" }, - "marketcap_usd": 3893050, + "marketcap_usd": 1650003, "name": "Peculium", "network": "eth", "shortcut": "PCL", @@ -16223,7 +16192,7 @@ "Github": "https://github.com/opiria-pdata/Pdata", "Homepage": "https://opiria.io" }, - "marketcap_usd": 186275, + "marketcap_usd": 128088, "name": "PDATA", "network": "eth", "shortcut": "PDATA", @@ -16358,7 +16327,7 @@ "links": { "Homepage": "https://www.phitoken.io" }, - "marketcap_usd": 379327, + "marketcap_usd": 717182, "name": "PHI Token", "network": "eth", "shortcut": "PHI", @@ -16377,7 +16346,7 @@ "links": { "Homepage": "https://piplcoin.com" }, - "marketcap_usd": 56854, + "marketcap_usd": 71752, "name": "PIPL Coin", "network": "eth", "shortcut": "PIPL", @@ -16453,7 +16422,7 @@ "links": { "Homepage": "https://playkey.io" }, - "marketcap_usd": 489724, + "marketcap_usd": 246649, "name": "Playkey", "network": "eth", "shortcut": "PKT", @@ -16491,7 +16460,7 @@ "links": { "Homepage": "https://polybius.io" }, - "marketcap_usd": 8294342, + "marketcap_usd": 5556060, "name": "Polybius", "network": "eth", "shortcut": "PLBT", @@ -16511,7 +16480,7 @@ "Github": "https://github.com/twentythirty/PillarToken", "Homepage": "https://www.pillarproject.io" }, - "marketcap_usd": 5958488, + "marketcap_usd": 3407401, "name": "Pillar Project", "network": "eth", "shortcut": "PLR", @@ -16550,7 +16519,7 @@ "links": { "Homepage": "https://plutus.it" }, - "marketcap_usd": 2192332, + "marketcap_usd": 846834, "name": "Pluton", "network": "eth", "shortcut": "PLU", @@ -16569,7 +16538,7 @@ "links": { "Homepage": "https://pumapay.io" }, - "marketcap_usd": 3639250, + "marketcap_usd": 2574128, "name": "PumaPay", "network": "eth", "shortcut": "PMA", @@ -16608,7 +16577,7 @@ "Github": "https://github.com/kleros", "Homepage": "https://kleros.io" }, - "marketcap_usd": 10608273, + "marketcap_usd": 4167708, "name": "Pinakion", "network": "eth", "shortcut": "PNK", @@ -16627,7 +16596,7 @@ "links": { "Homepage": "https://po.et" }, - "marketcap_usd": 5269171, + "marketcap_usd": 2511805, "name": "Po.et Tokens", "network": "eth", "shortcut": "POE", @@ -16665,7 +16634,7 @@ "links": { "Homepage": "https://clearpoll.com" }, - "marketcap_usd": 200560, + "marketcap_usd": 50130, "name": "ClearPoll", "network": "eth", "shortcut": "POLL", @@ -16684,7 +16653,7 @@ "links": { "Homepage": "https://polymath.network" }, - "marketcap_usd": 13346119, + "marketcap_usd": 7948877, "name": "Polymath Network", "network": "eth", "shortcut": "POLY", @@ -16762,7 +16731,7 @@ "links": { "Homepage": "https://powerledger.io" }, - "marketcap_usd": 39051938, + "marketcap_usd": 20945756, "name": "PowerLedger", "network": "eth", "shortcut": "POWR", @@ -16781,7 +16750,7 @@ "links": { "Homepage": "https://www.paypie.com" }, - "marketcap_usd": 4085076, + "marketcap_usd": 1234763, "name": "PayPie", "network": "eth", "shortcut": "PPP", @@ -16801,7 +16770,7 @@ "Github": "https://github.com/Bitpopulous", "Homepage": "https://populous.co" }, - "marketcap_usd": 21658655, + "marketcap_usd": 10276137, "name": "Populous", "network": "eth", "shortcut": "PPT", @@ -16820,7 +16789,7 @@ "links": { "Homepage": "https://presearch.io" }, - "marketcap_usd": 6386567, + "marketcap_usd": 1880549, "name": "Presearch", "network": "eth", "shortcut": "PRE", @@ -16840,7 +16809,7 @@ "Github": "https://github.com/paragon-coin/token", "Homepage": "https://paragoncoin.com" }, - "marketcap_usd": 618589, + "marketcap_usd": 136941, "name": "Paragon", "network": "eth", "shortcut": "PRG", @@ -16859,7 +16828,7 @@ "links": { "Homepage": "https://privatix.io" }, - "marketcap_usd": 264104, + "marketcap_usd": 122633, "name": "Privatix", "network": "eth", "shortcut": "PRIX", @@ -16995,7 +16964,7 @@ "links": { "Homepage": "https://primas.io" }, - "marketcap_usd": 1102785, + "marketcap_usd": 612387, "name": "Primas", "network": "eth", "shortcut": "PST", @@ -17034,7 +17003,7 @@ "links": { "Homepage": "https://patientory.com" }, - "marketcap_usd": 320011, + "marketcap_usd": 129385, "name": "Patientory", "network": "eth", "shortcut": "PTOY", @@ -17053,7 +17022,7 @@ "links": { "Homepage": "https://www.proton.global" }, - "marketcap_usd": 791127, + "marketcap_usd": 432229, "name": "Proton Token", "network": "eth", "shortcut": "PTT", @@ -17133,7 +17102,7 @@ "Github": "https://github.com/playgame-global", "Homepage": "https://its.playgame.com" }, - "marketcap_usd": 404306, + "marketcap_usd": 189398, "name": "PlayGame", "network": "eth", "shortcut": "PXG", @@ -17171,7 +17140,7 @@ "links": { "Homepage": "https://pylon-network.org" }, - "marketcap_usd": 289876, + "marketcap_usd": 170701, "name": "Pylon Network", "network": "eth", "shortcut": "PYLNT", @@ -17191,7 +17160,7 @@ "Github": "https://github.com/PaycentGlobal", "Homepage": "https://paycent.com/" }, - "marketcap_usd": 28064, + "marketcap_usd": 18506, "name": "Paycentos", "network": "eth", "shortcut": "PYN", @@ -17210,7 +17179,7 @@ "links": { "Homepage": "https://liquid.plus" }, - "marketcap_usd": 17833549, + "marketcap_usd": 11055876, "name": "QASH", "network": "eth", "shortcut": "QASH", @@ -17249,7 +17218,7 @@ "Github": "https://github.com/qiibee", "Homepage": "https://www.qiibee.com" }, - "marketcap_usd": 2302260, + "marketcap_usd": 1144210, "name": "qiibeeToken", "network": "eth", "shortcut": "QBX", @@ -17268,7 +17237,7 @@ "links": { "Homepage": "https://quarkchain.io" }, - "marketcap_usd": 8428431, + "marketcap_usd": 4845781, "name": "QuarkChain", "network": "eth", "shortcut": "QKC", @@ -17288,7 +17257,7 @@ "Github": "https://github.com/quantnetwork", "Homepage": "https://www.quant.network/" }, - "marketcap_usd": 41866489, + "marketcap_usd": 22606832, "name": "Quant", "network": "eth", "shortcut": "QNT", @@ -17347,7 +17316,7 @@ "Github": "https://github.com/quantstamp", "Homepage": "https://quantstamp.com/" }, - "marketcap_usd": 6597500, + "marketcap_usd": 3403647, "name": "Quantstamp Token", "network": "eth", "shortcut": "QSP", @@ -17406,7 +17375,7 @@ "links": { "Homepage": "https://qunqun.io" }, - "marketcap_usd": 3086887, + "marketcap_usd": 1885144, "name": "QunQun", "network": "eth", "shortcut": "QUN", @@ -17425,7 +17394,7 @@ "links": { "Homepage": "https://revain.org" }, - "marketcap_usd": 15693406, + "marketcap_usd": 6162073, "name": "Revain", "network": "eth", "shortcut": "R", @@ -17484,7 +17453,7 @@ "links": { "Homepage": "http://token.dprating.com" }, - "marketcap_usd": 368914, + "marketcap_usd": 207270, "name": "DPRating", "network": "eth", "shortcut": "RATING", @@ -17504,7 +17473,7 @@ "Github": "https://github.com/rublixdev", "Homepage": "https://rublix.io/" }, - "marketcap_usd": 3195701, + "marketcap_usd": 1674968, "name": "Rublix", "network": "eth", "shortcut": "RBLX", @@ -17524,7 +17493,7 @@ "Github": "https://github.com/ripio/rcn-token", "Homepage": "https://ripiocredit.network" }, - "marketcap_usd": 33042539, + "marketcap_usd": 16192971, "name": "Ripio Credit Network", "network": "eth", "shortcut": "RCN", @@ -17544,7 +17513,7 @@ "Github": "https://github.com/raiden-network/raiden/", "Homepage": "https://raiden.network" }, - "marketcap_usd": 6630111, + "marketcap_usd": 3053336, "name": "Raiden Network", "network": "eth", "shortcut": "RDN", @@ -17602,7 +17571,7 @@ "links": { "Homepage": "https://www.real.markets" }, - "marketcap_usd": 324934, + "marketcap_usd": 140746, "name": "Real Estate Asset Ledger", "network": "eth", "shortcut": "REAL", @@ -17621,7 +17590,7 @@ "links": { "Homepage": "https://www.rebellious.io" }, - "marketcap_usd": 28785, + "marketcap_usd": 9140, "name": "Rebellious", "network": "eth", "shortcut": "REBL", @@ -17641,7 +17610,7 @@ "Github": "https://github.com/red", "Homepage": "https://ico.red-lang.org" }, - "marketcap_usd": 439538, + "marketcap_usd": 221836, "name": "Red Community Token", "network": "eth", "shortcut": "RED", @@ -17680,7 +17649,7 @@ "links": { "Homepage": "https://reftoken.io" }, - "marketcap_usd": 356815, + "marketcap_usd": 147110, "name": "RefToken", "network": "eth", "shortcut": "REF", @@ -17699,7 +17668,7 @@ "links": { "Homepage": "https://remme.io" }, - "marketcap_usd": 2228385, + "marketcap_usd": 1423991, "name": "Remme", "network": "eth", "shortcut": "REM", @@ -17739,7 +17708,7 @@ "Github": "https://github.com/renproject", "Homepage": "https://renproject.io/" }, - "marketcap_usd": 48053396, + "marketcap_usd": 28332420, "name": "Republic Token", "network": "eth", "shortcut": "REN", @@ -17758,7 +17727,7 @@ "links": { "Homepage": "https://augur.net" }, - "marketcap_usd": 132268103, + "marketcap_usd": 79533206, "name": "Augur", "network": "eth", "shortcut": "REP", @@ -17777,7 +17746,7 @@ "links": { "Homepage": "https://request.network" }, - "marketcap_usd": 10876013, + "marketcap_usd": 4997460, "name": "Request Network", "network": "eth", "shortcut": "REQ", @@ -17797,7 +17766,7 @@ "Github": "https://github.com/rexmls/RexToken", "Homepage": "https://imbrex.io" }, - "marketcap_usd": 115490, + "marketcap_usd": 110005, "name": "imbrex", "network": "eth", "shortcut": "REX", @@ -17816,7 +17785,7 @@ "links": { "Homepage": "https://refereum.com" }, - "marketcap_usd": 3951507, + "marketcap_usd": 2563386, "name": "Refereum", "network": "eth", "shortcut": "RFR", @@ -17855,7 +17824,7 @@ "links": { "Homepage": "https://www.rchain.coop" }, - "marketcap_usd": 6689984, + "marketcap_usd": 4134359, "name": "RChain", "network": "eth", "shortcut": "RHOC", @@ -17913,7 +17882,7 @@ "links": { "Homepage": "http://iex.ec/" }, - "marketcap_usd": 44668305, + "marketcap_usd": 18492032, "name": "IEx.ec", "network": "eth", "shortcut": "RLC", @@ -17933,7 +17902,7 @@ "Github": "https://github.com/Smartroulette", "Homepage": "https://smartplay.tech" }, - "marketcap_usd": 9180, + "marketcap_usd": 4865, "name": "RouletteToken", "network": "eth", "shortcut": "RLT", @@ -17971,7 +17940,7 @@ "links": { "Homepage": "http://www.relex.io" }, - "marketcap_usd": 255164, + "marketcap_usd": 139000, "name": "Relex", "network": "eth", "shortcut": "RLX", @@ -17991,7 +17960,7 @@ "Github": "https://github.com/rightmesh", "Homepage": "https://www.rightmesh.io/" }, - "marketcap_usd": 115272, + "marketcap_usd": 57391, "name": "RightMesh Token", "network": "eth", "shortcut": "RMESH", @@ -18029,7 +17998,7 @@ "links": { "Homepage": "https://www.oneroot.io/en" }, - "marketcap_usd": 2538293, + "marketcap_usd": 1645398, "name": "OneRoot Network", "network": "eth", "shortcut": "RNT", @@ -18048,7 +18017,7 @@ "links": { "Homepage": "https://bitrent.io" }, - "marketcap_usd": 22494, + "marketcap_usd": 23685, "name": "BitRent", "network": "eth", "shortcut": "RNTB", @@ -18087,7 +18056,7 @@ "links": { "Homepage": "https://icerockmining.io" }, - "marketcap_usd": 1051383, + "marketcap_usd": 615386, "name": "ICE ROCK MINING", "network": "eth", "shortcut": "ROCK2", @@ -18164,7 +18133,7 @@ "links": { "Homepage": "https://www.rocketpool.net" }, - "marketcap_usd": 7232364, + "marketcap_usd": 3007680, "name": "Rocket Pool", "network": "eth", "shortcut": "RPL", @@ -18222,7 +18191,7 @@ "links": { "Homepage": "https://www.rotharium.io" }, - "marketcap_usd": 2353145, + "marketcap_usd": 1220391, "name": "Rotharium", "network": "eth", "shortcut": "RTH", @@ -18261,7 +18230,7 @@ "links": { "Homepage": "http://ruffchain.com" }, - "marketcap_usd": 6392795, + "marketcap_usd": 2774074, "name": "Ruff", "network": "eth", "shortcut": "RUFF", @@ -18319,7 +18288,7 @@ "links": { "Homepage": "https://rivetzintl.com" }, - "marketcap_usd": 137029, + "marketcap_usd": 82702, "name": "Rivetz", "network": "eth", "shortcut": "RVT", @@ -18416,7 +18385,7 @@ "Github": "https://github.com/makerdao", "Homepage": "https://makerdao.com" }, - "marketcap_usd": 21360558, + "marketcap_usd": 16319278, "name": "Dai Stablecoin v1.0", "network": "eth", "shortcut": "SAI", @@ -18435,7 +18404,7 @@ "links": { "Homepage": "https://saltlending.com" }, - "marketcap_usd": 5332518, + "marketcap_usd": 5100012, "name": "Salt Lending Token", "network": "eth", "shortcut": "SALT", @@ -18454,7 +18423,7 @@ "links": { "Homepage": "https://santiment.net" }, - "marketcap_usd": 10168270, + "marketcap_usd": 5408283, "name": "Santiment", "network": "eth", "shortcut": "SAN", @@ -18492,7 +18461,7 @@ "links": { "Homepage": "https://ico.nexus.social" }, - "marketcap_usd": 78238, + "marketcap_usd": 40688, "name": "SocialCoin", "network": "eth", "shortcut": "SCL", @@ -18530,7 +18499,7 @@ "links": { "Homepage": "http://seele.pro" }, - "marketcap_usd": 58828742, + "marketcap_usd": 31466901, "name": "Seele", "network": "eth", "shortcut": "SEELE", @@ -18569,7 +18538,7 @@ "links": { "Homepage": "https://www.sentinel-chain.org" }, - "marketcap_usd": 284125, + "marketcap_usd": 163548, "name": "Sentinel Chain", "network": "eth", "shortcut": "SENC", @@ -18607,7 +18576,7 @@ "links": { "Homepage": "https://sentinel.co" }, - "marketcap_usd": 2054131, + "marketcap_usd": 944448, "name": "SENTinel", "network": "eth", "shortcut": "SENT", @@ -18742,7 +18711,7 @@ "links": { "Homepage": "https://www.shipchain.io" }, - "marketcap_usd": 2409562, + "marketcap_usd": 1129501, "name": "ShipChain", "network": "eth", "shortcut": "SHIP", @@ -18839,7 +18808,7 @@ "Github": "https://github.com/SpectivOfficial", "Homepage": "https://spectivvr.com" }, - "marketcap_usd": 17412, + "marketcap_usd": 8778, "name": "Signal", "network": "eth", "shortcut": "SIG", @@ -18858,7 +18827,7 @@ "links": { "Homepage": "https://www.skb-coin.jp/en" }, - "marketcap_usd": 1236815, + "marketcap_usd": 448199, "name": "Sakura Bloom", "network": "eth", "shortcut": "SKB", @@ -18897,7 +18866,7 @@ "Github": "https://github.com/Steamtradenet/smart-contract", "Homepage": "https://skincoin.org" }, - "marketcap_usd": 31351, + "marketcap_usd": 24256, "name": "SKIN", "network": "eth", "shortcut": "SKIN", @@ -19032,7 +19001,7 @@ "links": { "Homepage": "https://suncontract.org" }, - "marketcap_usd": 3328061, + "marketcap_usd": 1627083, "name": "SunContract", "network": "eth", "shortcut": "SNC", @@ -19090,7 +19059,7 @@ "links": { "Homepage": "https://singulardtv.com" }, - "marketcap_usd": 5052822, + "marketcap_usd": 2297728, "name": "SingularDTV", "network": "eth", "shortcut": "SNGLS", @@ -19129,7 +19098,7 @@ "Github": "https://github.com/sonm-io", "Homepage": "https://sonm.com" }, - "marketcap_usd": 4303519, + "marketcap_usd": 1725686, "name": "SONM", "network": "eth", "shortcut": "SNM", @@ -19148,7 +19117,7 @@ "links": { "Homepage": "https://snovian.space" }, - "marketcap_usd": 183693, + "marketcap_usd": 209251, "name": "Snovian.Space", "network": "eth", "shortcut": "SNOV", @@ -19168,7 +19137,7 @@ "Github": "https://github.com/status-im", "Homepage": "https://status.im" }, - "marketcap_usd": 52892687, + "marketcap_usd": 31861338, "name": "Status Network Token", "network": "eth", "shortcut": "SNT", @@ -19187,7 +19156,7 @@ "links": { "Homepage": "https://silentnotary.com" }, - "marketcap_usd": 199808, + "marketcap_usd": 94246, "name": "Silent Notary", "network": "eth", "shortcut": "SNTR", @@ -19225,7 +19194,7 @@ "links": { "Homepage": "https://www.allsportschain.com" }, - "marketcap_usd": 6393716, + "marketcap_usd": 3480697, "name": "All Sports", "network": "eth", "shortcut": "SOC", @@ -19283,7 +19252,7 @@ "Github": "https://github.com/cryptosoulgame", "Homepage": "https://cryptosoul.io/" }, - "marketcap_usd": 38996, + "marketcap_usd": 18607, "name": "CryptoSoul", "network": "eth", "shortcut": "SOUL", @@ -19302,7 +19271,7 @@ "links": { "Homepage": "https://spankchain.com" }, - "marketcap_usd": 1531419, + "marketcap_usd": 370869, "name": "SpankChain", "network": "eth", "shortcut": "SPANK", @@ -19360,7 +19329,7 @@ "Github": "https://github.com/SPZ-TOKEN", "Homepage": "https://swapcoinz.org" }, - "marketcap_usd": 14785, + "marketcap_usd": 4818, "name": "SWAPCOINZ", "network": "eth", "shortcut": "SPAZ", @@ -19399,7 +19368,7 @@ "links": { "Homepage": "https://spindle.zone" }, - "marketcap_usd": 313056, + "marketcap_usd": 159173, "name": "SPINDLE", "network": "eth", "shortcut": "SPD", @@ -19418,7 +19387,7 @@ "links": { "Homepage": "https://sportyfi.io" }, - "marketcap_usd": 90096, + "marketcap_usd": 40960, "name": "Sportify", "network": "eth", "shortcut": "SPF", @@ -19457,7 +19426,7 @@ "links": { "Homepage": "https://www.sapien.network/" }, - "marketcap_usd": 669390, + "marketcap_usd": 309992, "name": "Sapien", "network": "eth", "shortcut": "SPN", @@ -19476,7 +19445,7 @@ "links": { "Homepage": "https://sp8de.com" }, - "marketcap_usd": 109979, + "marketcap_usd": 27378, "name": "Sp8de", "network": "eth", "shortcut": "SPX", @@ -19496,7 +19465,7 @@ "Github": "https://github.com/sirin-labs/crowdsale-smart-contract", "Homepage": "https://sirinlabs.com" }, - "marketcap_usd": 3360798, + "marketcap_usd": 4169489, "name": "Sirin Labs", "network": "eth", "shortcut": "SRN", @@ -19554,7 +19523,7 @@ "links": { "Homepage": "https://smartshare.vip/#" }, - "marketcap_usd": 849242, + "marketcap_usd": 354685, "name": "Smartshare", "network": "eth", "shortcut": "SSP", @@ -19592,7 +19561,7 @@ "links": { "Homepage": "https://coinstarter.com" }, - "marketcap_usd": 17790, + "marketcap_usd": 8560, "name": "Starter Coin", "network": "eth", "shortcut": "STAC", @@ -19611,7 +19580,7 @@ "links": { "Homepage": "https://stacs.io" }, - "marketcap_usd": 2437497, + "marketcap_usd": 1448695, "name": "STACS", "network": "eth", "shortcut": "STACS", @@ -19630,7 +19599,7 @@ "links": { "Homepage": "http://starbase.co" }, - "marketcap_usd": 136854, + "marketcap_usd": 82785, "name": "Star Token", "network": "eth", "shortcut": "STAR", @@ -19689,7 +19658,7 @@ "links": { "Homepage": "https://stktoken.com" }, - "marketcap_usd": 737837, + "marketcap_usd": 412585, "name": "STK Token", "network": "eth", "shortcut": "STK", @@ -19766,7 +19735,7 @@ "Github": "https://github.com/Storj", "Homepage": "https://storj.io" }, - "marketcap_usd": 20598790, + "marketcap_usd": 9615687, "name": "STORJ", "network": "eth", "shortcut": "STORJ", @@ -19785,7 +19754,7 @@ "links": { "Homepage": "https://www.stormtoken.com" }, - "marketcap_usd": 10191682, + "marketcap_usd": 6440580, "name": "Storm Token", "network": "eth", "shortcut": "STORM", @@ -19844,7 +19813,7 @@ "links": { "Homepage": "https://staker.network" }, - "marketcap_usd": 1714, + "marketcap_usd": 944, "name": "Staker", "network": "eth", "shortcut": "STR", @@ -19883,7 +19852,7 @@ "links": { "Homepage": "https://bitjob.io" }, - "marketcap_usd": 25732, + "marketcap_usd": 9294, "name": "bitJob", "network": "eth", "shortcut": "STU", @@ -19903,7 +19872,7 @@ "Github": "https://github.com/stx-technologies/stox-token", "Homepage": "https://www.stox.com" }, - "marketcap_usd": 413134, + "marketcap_usd": 288441, "name": "StoxToken", "network": "eth", "shortcut": "STX", @@ -19923,7 +19892,7 @@ "Github": "https://github.com/SubstratumNetwork", "Homepage": "https://substratum.net" }, - "marketcap_usd": 1747312, + "marketcap_usd": 1189624, "name": "Substratum", "network": "eth", "shortcut": "SUB", @@ -19942,7 +19911,7 @@ "links": { "Homepage": "https://www.suretly.com" }, - "marketcap_usd": 74677, + "marketcap_usd": 57803, "name": "Suretly", "network": "eth", "shortcut": "SUR", @@ -19961,7 +19930,7 @@ "links": { "Homepage": "https://ico.savedroid.com" }, - "marketcap_usd": 192709, + "marketcap_usd": 526804, "name": "savedroid", "network": "eth", "shortcut": "SVD", @@ -20000,7 +19969,7 @@ "links": { "Homepage": "http://www.swftcoin.com" }, - "marketcap_usd": 4828798, + "marketcap_usd": 2488544, "name": "SwftCoin", "network": "eth", "shortcut": "SWFTC", @@ -20039,7 +20008,7 @@ "links": { "Homepage": "http://swarm.city" }, - "marketcap_usd": 364357, + "marketcap_usd": 110132, "name": "Swarm City Token", "network": "eth", "shortcut": "SWT", @@ -20058,7 +20027,7 @@ "links": { "Homepage": "http://www.spectre.ai" }, - "marketcap_usd": 10839687, + "marketcap_usd": 8899373, "name": "Spectre.ai D-Token", "network": "eth", "shortcut": "SXDT", @@ -20097,7 +20066,7 @@ "links": { "Homepage": "http://www.spectre.ai" }, - "marketcap_usd": 1732934, + "marketcap_usd": 903809, "name": "Spectre.ai U-Token", "network": "eth", "shortcut": "SXUT", @@ -20173,7 +20142,7 @@ "links": { "Homepage": "https://taklimakan.io" }, - "marketcap_usd": 71447, + "marketcap_usd": 42813, "name": "Taklimakan Network", "network": "eth", "shortcut": "TAN", @@ -20193,7 +20162,7 @@ "Github": "https://github.com/lamden", "Homepage": "https://www.lamden.io" }, - "marketcap_usd": 2281736, + "marketcap_usd": 1077389, "name": "Lamden Tau", "network": "eth", "shortcut": "TAU", @@ -20311,7 +20280,7 @@ "links": { "Homepage": "https://tokenbox.io" }, - "marketcap_usd": 119020, + "marketcap_usd": 46121, "name": "Tokenbox", "network": "eth", "shortcut": "TBX", @@ -20370,7 +20339,7 @@ "links": { "Homepage": "https://www.thorecash.com" }, - "marketcap_usd": 54194, + "marketcap_usd": 25627, "name": "Thore Cash", "network": "eth", "shortcut": "TCH", @@ -20466,7 +20435,7 @@ "links": { "Homepage": "https://tokenstars.com/team" }, - "marketcap_usd": 128390, + "marketcap_usd": 87972, "name": "TEAM (TokenStars)", "network": "eth", "shortcut": "TEAM", @@ -20504,7 +20473,7 @@ "links": { "Homepage": "https://www.tokenomy.com" }, - "marketcap_usd": 5995495, + "marketcap_usd": 3185261, "name": "Tokenomy", "network": "eth", "shortcut": "TEN", @@ -20543,7 +20512,7 @@ "links": { "Homepage": "https://ico.tefoodint.com" }, - "marketcap_usd": 2610853, + "marketcap_usd": 1173026, "name": "TE-FOOD", "network": "eth", "shortcut": "TFD", @@ -20563,7 +20532,7 @@ "Github": "https://github.com/TrueFlip", "Homepage": "https://trueflip.io" }, - "marketcap_usd": 2673731, + "marketcap_usd": 921956, "name": "TrueFlip", "network": "eth", "shortcut": "TFL", @@ -20582,7 +20551,7 @@ "links": { "Homepage": "https://ico.truegame.io" }, - "marketcap_usd": 266247, + "marketcap_usd": 121217, "name": "Truegame", "network": "eth", "shortcut": "TGAME", @@ -20660,7 +20629,7 @@ "links": { "Homepage": "https://www.thorecoin.com" }, - "marketcap_usd": 149899386, + "marketcap_usd": 89090776, "name": "ThoreCoin", "network": "eth", "shortcut": "THR", @@ -20679,7 +20648,7 @@ "links": { "Homepage": "https://ico.thrivelabs.io" }, - "marketcap_usd": 254240, + "marketcap_usd": 60103, "name": "Thrive Token", "network": "eth", "shortcut": "THRT", @@ -20718,7 +20687,7 @@ "links": { "Homepage": "https://ties.network" }, - "marketcap_usd": 695831, + "marketcap_usd": 180161, "name": "Ties.DB", "network": "eth", "shortcut": "TIE", @@ -20756,7 +20725,7 @@ "links": { "Homepage": "https://chronobank.io" }, - "marketcap_usd": 742946, + "marketcap_usd": 477359, "name": "Chronobank", "network": "eth", "shortcut": "TIME", @@ -20794,7 +20763,7 @@ "links": { "Homepage": "https://www.blocktix.io" }, - "marketcap_usd": 238512, + "marketcap_usd": 74090, "name": "Blocktix", "network": "eth", "shortcut": "TIX", @@ -20851,7 +20820,7 @@ "links": { "Homepage": "https://etherscan.io/token/TokenCard" }, - "marketcap_usd": 6710571, + "marketcap_usd": 3339169, "name": "TokenCard", "network": "eth", "shortcut": "TKN", @@ -20928,7 +20897,7 @@ "links": { "Homepage": "https://transcodium.com" }, - "marketcap_usd": 101946, + "marketcap_usd": 57216, "name": "Transcodium", "network": "eth", "shortcut": "TNS", @@ -20948,7 +20917,7 @@ "Github": "https://github.com/tierion", "Homepage": "https://tierion.com" }, - "marketcap_usd": 18573735, + "marketcap_usd": 10306349, "name": "Tierion Network Token", "network": "eth", "shortcut": "TNT", @@ -21006,7 +20975,7 @@ "links": { "Homepage": "https://origintrail.io" }, - "marketcap_usd": 3477969, + "marketcap_usd": 2029334, "name": "OriginTrail", "network": "eth", "shortcut": "TRAC", @@ -21102,7 +21071,7 @@ "Github": "https://github.com/WeTrustPlatform", "Homepage": "https://www.wetrust.io" }, - "marketcap_usd": 992104, + "marketcap_usd": 565686, "name": "WeTrust", "network": "eth", "shortcut": "TRST", @@ -21199,7 +21168,7 @@ "Github": "https://github.com/tvtwocom", "Homepage": "https://tv-two.com" }, - "marketcap_usd": 361127, + "marketcap_usd": 192167, "name": "TV-TWO: Token for Television", "network": "eth", "shortcut": "TTV", @@ -21219,7 +21188,7 @@ "Github": "https://github.com/trusttoken", "Homepage": "https://www.trusttoken.com" }, - "marketcap_usd": 141037653, + "marketcap_usd": 137742047, "name": "TrueUSD", "network": "eth", "shortcut": "TUSD", @@ -21276,7 +21245,7 @@ "links": { "Homepage": "https://taas.fund" }, - "marketcap_usd": 5387080, + "marketcap_usd": 3200492, "name": "Token-as-a-Service", "network": "eth", "shortcut": "TaaS", @@ -21296,7 +21265,7 @@ "Github": "https://github.com/Thartoken", "Homepage": "https://thartoken.com" }, - "marketcap_usd": 42668, + "marketcap_usd": 19664, "name": "Thar token", "network": "eth", "shortcut": "Thar", @@ -21316,7 +21285,7 @@ "Github": "https://github.com/ubex-ai", "Homepage": "https://www.ubex.com/" }, - "marketcap_usd": 1348766, + "marketcap_usd": 635983, "name": "UBEX Token", "network": "eth", "shortcut": "UBEX", @@ -21335,7 +21304,7 @@ "links": { "Homepage": "https://unibright.io" }, - "marketcap_usd": 29532074, + "marketcap_usd": 12023716, "name": "Unibright", "network": "eth", "shortcut": "UBT", @@ -21354,7 +21323,7 @@ "links": { "Homepage": "https://u.cash" }, - "marketcap_usd": 1035194, + "marketcap_usd": 542549, "name": "U.CASH", "network": "eth", "shortcut": "UCASH", @@ -21393,7 +21362,7 @@ "links": { "Homepage": "https://uchain.world" }, - "marketcap_usd": 46527, + "marketcap_usd": 9127, "name": "UChain", "network": "eth", "shortcut": "UCN", @@ -21412,7 +21381,7 @@ "links": { "Homepage": "https://www.upfiring.com" }, - "marketcap_usd": 1362446, + "marketcap_usd": 579978, "name": "Upfiring", "network": "eth", "shortcut": "UFR", @@ -21432,7 +21401,7 @@ "Github": "https://github.com/unikoingold/UnikoinGold-UKG-Contract", "Homepage": "https://unikoingold.com" }, - "marketcap_usd": 1298844, + "marketcap_usd": 969736, "name": "UnikoinGold", "network": "eth", "shortcut": "UKG", @@ -21451,7 +21420,7 @@ "links": { "Homepage": "https://uptoken.org" }, - "marketcap_usd": 605422, + "marketcap_usd": 186176, "name": "UpToken", "network": "eth", "shortcut": "UP", @@ -21470,7 +21439,7 @@ "links": { "Homepage": "https://sentinelprotocol.io" }, - "marketcap_usd": 5119487, + "marketcap_usd": 5220163, "name": "Sentinel Protocol", "network": "eth", "shortcut": "UPP", @@ -21489,7 +21458,7 @@ "links": { "Homepage": "https://uquidcoin.com" }, - "marketcap_usd": 4021974, + "marketcap_usd": 4102221, "name": "Uquid Coin", "network": "eth", "shortcut": "UQC", @@ -21569,7 +21538,7 @@ "Github": "https://github.com/centrehq/centre-tokens", "Homepage": "https://www.centre.io" }, - "marketcap_usd": 424112004, + "marketcap_usd": 600948908, "name": "USD//Coin", "network": "eth", "shortcut": "USDC", @@ -21588,7 +21557,7 @@ "links": { "Homepage": "https://stably.io" }, - "marketcap_usd": 1447891, + "marketcap_usd": 1552212, "name": "StableUSD", "network": "eth", "shortcut": "USDS", @@ -21627,7 +21596,7 @@ "Github": "https://github.com/dforcenetwork", "Homepage": "https://dforce.network" }, - "marketcap_usd": 2536339, + "marketcap_usd": 2718232, "name": "dForce Stablecoin", "network": "eth", "shortcut": "USDx", @@ -21646,7 +21615,7 @@ "links": { "Homepage": "https://utrust.com" }, - "marketcap_usd": 6284087, + "marketcap_usd": 2874676, "name": "UTRUST", "network": "eth", "shortcut": "UTK", @@ -21666,7 +21635,7 @@ "Github": "https://github.com/UniversaBlockchain/universa", "Homepage": "https://www.universa.io" }, - "marketcap_usd": 3644177, + "marketcap_usd": 2383521, "name": "Universa", "network": "eth", "shortcut": "UTNP", @@ -21685,7 +21654,7 @@ "links": { "Homepage": "https://uttoken.io" }, - "marketcap_usd": 7443526, + "marketcap_usd": 7121772, "name": "United Traders Token", "network": "eth", "shortcut": "UTT", @@ -21704,7 +21673,7 @@ "links": { "Homepage": "https://u.network/" }, - "marketcap_usd": 7730525, + "marketcap_usd": 2823965, "name": "U Networks", "network": "eth", "shortcut": "UUU", @@ -21724,7 +21693,7 @@ "Github": "https://github.com/smartvalor/ValorToken", "Homepage": "https://smartvalor.com" }, - "marketcap_usd": 5154600, + "marketcap_usd": 3080799, "name": "ValorToken", "network": "eth", "shortcut": "VALOR", @@ -21764,7 +21733,7 @@ "Github": "https://github.com/VeriDocGlobal", "Homepage": "https://www.veridocglobal.com/" }, - "marketcap_usd": 2928495, + "marketcap_usd": 2085058, "name": "VeriDocGlobal", "network": "eth", "shortcut": "VDG", @@ -21804,7 +21773,7 @@ "Github": "https://github.com/blockv", "Homepage": "https://blockv.io" }, - "marketcap_usd": 3518785, + "marketcap_usd": 1594929, "name": "BLOCKv", "network": "eth", "shortcut": "VEE", @@ -21881,7 +21850,7 @@ "links": { "Homepage": "https://veritas.veritaseum.com" }, - "marketcap_usd": 22500128, + "marketcap_usd": 10232961, "name": "Veritaseum", "network": "eth", "shortcut": "VERI", @@ -21900,7 +21869,7 @@ "links": { "Homepage": "https://www.viberate.com" }, - "marketcap_usd": 3554034, + "marketcap_usd": 1587085, "name": "Viberate", "network": "eth", "shortcut": "VIB", @@ -21919,7 +21888,7 @@ "links": { "Homepage": "https://www.vibehub.io" }, - "marketcap_usd": 3515915, + "marketcap_usd": 1540293, "name": "VIBE Coin", "network": "eth", "shortcut": "VIBE", @@ -21959,7 +21928,7 @@ "Github": "https://github.com/videocoin", "Homepage": "https://www.videocoin.io" }, - "marketcap_usd": 2063771, + "marketcap_usd": 3338825, "name": "VideoCoin", "network": "eth", "shortcut": "VID", @@ -21979,7 +21948,7 @@ "Github": "https://github.com/V-ID/V-ID-Token", "Homepage": "https://www.v-id.org" }, - "marketcap_usd": 5129043, + "marketcap_usd": 2291968, "name": "V-ID Token", "network": "eth", "shortcut": "VIDT", @@ -21999,7 +21968,7 @@ "Github": "https://github.com/Viewly/", "Homepage": "https://view.ly/" }, - "marketcap_usd": 181214, + "marketcap_usd": 111416, "name": "Viewly", "network": "eth", "shortcut": "VIEW", @@ -22018,7 +21987,7 @@ "links": { "Homepage": "https://ico.vikky.io" }, - "marketcap_usd": 5880, + "marketcap_usd": 2884, "name": "VikkyToken", "network": "eth", "shortcut": "VIKKY", @@ -22097,7 +22066,7 @@ "Github": "https://github.com/vetri-global/", "Homepage": "https://vetri.global/" }, - "marketcap_usd": 1616028, + "marketcap_usd": 774323, "name": "VETRI", "network": "eth", "shortcut": "VLD", @@ -22174,7 +22143,7 @@ "links": { "Homepage": "https://vnx.io/" }, - "marketcap_usd": 2216134, + "marketcap_usd": 2700131, "name": "VNX Exchange", "network": "eth", "shortcut": "VNXLU", @@ -22213,7 +22182,7 @@ "links": { "Homepage": "https://voise.it" }, - "marketcap_usd": 107425, + "marketcap_usd": 84742, "name": "Voise", "network": "eth", "shortcut": "VOISE", @@ -22252,7 +22221,7 @@ "Github": "https://github.com/VeriSafe", "Homepage": "https://verisafe.io/" }, - "marketcap_usd": 106572, + "marketcap_usd": 63339, "name": "VeriSafe", "network": "eth", "shortcut": "VSF", @@ -22271,7 +22240,7 @@ "links": { "Homepage": "https://www.vdice.io" }, - "marketcap_usd": 58830, + "marketcap_usd": 32561, "name": "Vdice", "network": "eth", "shortcut": "VSL", @@ -22329,7 +22298,7 @@ "links": { "Homepage": "https://wab.network" }, - "marketcap_usd": 41380, + "marketcap_usd": 15237, "name": "WABnetwork", "network": "eth", "shortcut": "WAB", @@ -22348,7 +22317,7 @@ "links": { "Homepage": "https://taelpay.com" }, - "marketcap_usd": 9264155, + "marketcap_usd": 4344189, "name": "Tael", "network": "eth", "shortcut": "WABI", @@ -22467,7 +22436,7 @@ "Github": "https://github.com/WrappedBTC", "Homepage": "https://wbtc.network" }, - "marketcap_usd": 7919374, + "marketcap_usd": 4685643, "name": "Wrapped Bitcoin", "network": "eth", "shortcut": "WBTC", @@ -22525,7 +22494,7 @@ "links": { "Homepage": "https://webcoin.today" }, - "marketcap_usd": 49763, + "marketcap_usd": 31291, "name": "Webcoin", "network": "eth", "shortcut": "WEB", @@ -22623,7 +22592,7 @@ "links": { "Homepage": "https://wings.ai" }, - "marketcap_usd": 1516389, + "marketcap_usd": 982826, "name": "WINGS", "network": "eth", "shortcut": "WINGS", @@ -22720,7 +22689,7 @@ "links": { "Homepage": "https://wepower.network" }, - "marketcap_usd": 4695103, + "marketcap_usd": 2371102, "name": "WePower Token", "network": "eth", "shortcut": "WPR", @@ -22739,7 +22708,7 @@ "links": { "Homepage": "https://worldcore.eu" }, - "marketcap_usd": 33868, + "marketcap_usd": 15788, "name": "Worldcore", "network": "eth", "shortcut": "WRC", @@ -22799,7 +22768,7 @@ "Github": "https://github.com/waltonchain", "Homepage": "http://www.waltonchain.org" }, - "marketcap_usd": 31798260, + "marketcap_usd": 12497973, "name": "Waltonchain", "network": "eth", "shortcut": "WTC", @@ -22878,7 +22847,7 @@ "links": { "Homepage": "https://x8currency.com" }, - "marketcap_usd": 325954, + "marketcap_usd": 179816, "name": "X8X", "network": "eth", "shortcut": "X8X", @@ -22897,7 +22866,7 @@ "links": { "Homepage": "http://www.xaurum.org" }, - "marketcap_usd": 2873850, + "marketcap_usd": 2325315, "name": "Xaurum", "network": "eth", "shortcut": "XAUR", @@ -22936,7 +22905,7 @@ "Github": "https://github.com/blitzpredict", "Homepage": "https://www.blitzpredict.io" }, - "marketcap_usd": 104778, + "marketcap_usd": 57032, "name": "BlitzPredict", "network": "eth", "shortcut": "XBP", @@ -22975,7 +22944,7 @@ "links": { "Homepage": "https://www.swisscryptotokens.ch/" }, - "marketcap_usd": 8474166, + "marketcap_usd": 8838079, "name": "CryptoFranc", "network": "eth", "shortcut": "XCHF", @@ -23033,7 +23002,7 @@ "links": { "Homepage": "https://www.xinfin.io" }, - "marketcap_usd": 7705360, + "marketcap_usd": 3779547, "name": "XinFin Network", "network": "eth", "shortcut": "XDCE", @@ -23052,7 +23021,7 @@ "links": { "Homepage": "https://proxeus.com" }, - "marketcap_usd": 813643, + "marketcap_usd": 416236, "name": "Proxeus", "network": "eth", "shortcut": "XES", @@ -23071,7 +23040,7 @@ "links": { "Homepage": "https://www.atom-solutions.jp/en/xetchange.php" }, - "marketcap_usd": 143145268, + "marketcap_usd": 59329506, "name": "ETERNAL TOKEN", "network": "eth", "shortcut": "XET", @@ -23266,7 +23235,7 @@ "Github": "https://github.com/XMaxPlatform", "Homepage": "https://www.xmx.com" }, - "marketcap_usd": 18455037, + "marketcap_usd": 6136193, "name": "XMax", "network": "eth", "shortcut": "XMX", @@ -23286,7 +23255,7 @@ "Github": "https://github.com/InkProtocol/", "Homepage": "https://paywithink.com" }, - "marketcap_usd": 145611, + "marketcap_usd": 84689, "name": "Ink Protocol", "network": "eth", "shortcut": "XNK", @@ -23343,7 +23312,7 @@ "links": { "Homepage": "http://www.xov.io" }, - "marketcap_usd": 5117, + "marketcap_usd": 2922, "name": "XOVBank", "network": "eth", "shortcut": "XOV", @@ -23382,7 +23351,7 @@ "Github": "https://github.com/Bit-Nation/", "Homepage": "https://bitnation.co" }, - "marketcap_usd": 58355, + "marketcap_usd": 29066, "name": "Pangea Arbitration Token", "network": "eth", "shortcut": "XPAT", @@ -23478,7 +23447,7 @@ "links": { "Homepage": "https://xyo.network" }, - "marketcap_usd": 3262435, + "marketcap_usd": 2130075, "name": "XYO", "network": "eth", "shortcut": "XYO", @@ -23497,7 +23466,7 @@ "links": { "Homepage": "http://www.yeefoundation.com" }, - "marketcap_usd": 1412773, + "marketcap_usd": 572572, "name": "Yee Token", "network": "eth", "shortcut": "YEE", @@ -23537,7 +23506,7 @@ "Github": "https://github.com/zapproject", "Homepage": "https://zap.store" }, - "marketcap_usd": 1148121, + "marketcap_usd": 477216, "name": "ZAP", "network": "eth", "shortcut": "ZAP", @@ -23556,7 +23525,7 @@ "links": { "Homepage": "https://0chain.net" }, - "marketcap_usd": 3191698, + "marketcap_usd": 1562937, "name": "0chain", "network": "eth", "shortcut": "ZCN", @@ -23594,7 +23563,7 @@ "links": { "Homepage": "https://zsc.io/" }, - "marketcap_usd": 341729, + "marketcap_usd": 138817, "name": "Zeusshield", "network": "eth", "shortcut": "ZCS", @@ -23653,7 +23622,7 @@ "Github": "https://github.com/ZEUS-coin", "Homepage": "https://zeusfundme.com/" }, - "marketcap_usd": 24925, + "marketcap_usd": 11113, "name": "ZeusNetwork", "network": "eth", "shortcut": "ZEUS", @@ -23692,7 +23661,7 @@ "links": { "Homepage": "https://zinc.work" }, - "marketcap_usd": 27480, + "marketcap_usd": 13526, "name": "ZINC", "network": "eth", "shortcut": "ZINC", @@ -23711,7 +23680,7 @@ "links": { "Homepage": "http://zipper.io" }, - "marketcap_usd": 1902506, + "marketcap_usd": 832717, "name": "Zipper", "network": "eth", "shortcut": "ZIP", @@ -23730,7 +23699,7 @@ "links": { "Homepage": "https://zippie.org" }, - "marketcap_usd": 447681, + "marketcap_usd": 247680, "name": "Zippie", "network": "eth", "shortcut": "ZIPT", @@ -23769,7 +23738,7 @@ "links": { "Homepage": "https://zla.io" }, - "marketcap_usd": 391670, + "marketcap_usd": 173715, "name": "Zilla", "network": "eth", "shortcut": "ZLA", @@ -23808,7 +23777,7 @@ "links": { "Homepage": "https://www.zmine.com" }, - "marketcap_usd": 201911, + "marketcap_usd": 119170, "name": "ZMINE", "network": "eth", "shortcut": "ZMN", @@ -23827,7 +23796,7 @@ "links": { "Homepage": "https://zper.io" }, - "marketcap_usd": 770692, + "marketcap_usd": 875263, "name": "ZPER", "network": "eth", "shortcut": "ZPR", @@ -23847,7 +23816,7 @@ "Github": "https://github.com/0xProject", "Homepage": "https://0xproject.com" }, - "marketcap_usd": 158516655, + "marketcap_usd": 93561343, "name": "0x Project", "network": "eth", "shortcut": "ZRX", @@ -23885,7 +23854,7 @@ "links": { "Homepage": "https://0xcert.org" }, - "marketcap_usd": 1076392, + "marketcap_usd": 345228, "name": "0xcert Protocol Token", "network": "eth", "shortcut": "ZXC", @@ -24005,7 +23974,7 @@ "Github": "https://github.com/carVertical", "Homepage": "https://www.carvertical.com" }, - "marketcap_usd": 1373534, + "marketcap_usd": 646814, "name": "carVertical", "network": "eth", "shortcut": "cV", @@ -24963,7 +24932,7 @@ "Github": "https://github.com/eosdac", "Homepage": "https://eosdac.io/" }, - "marketcap_usd": 13346826, + "marketcap_usd": 3605923, "name": "eosDAC", "network": "eth", "shortcut": "eosDAC", @@ -26220,7 +26189,7 @@ "links": { "Homepage": "https://akroma.io" }, - "marketcap_usd": 6676, + "marketcap_usd": 3044, "name": "Akroma", "shortcut": "AKA", "t1_enabled": "yes", @@ -26283,7 +26252,7 @@ "links": { "Homepage": "https://atheios.com" }, - "marketcap_usd": 6248, + "marketcap_usd": 3713, "name": "Atheios", "shortcut": "ATH", "t1_enabled": "yes", @@ -26326,7 +26295,7 @@ "Github": "https://github.com/auxiliumglobal", "Homepage": "https://auxilium.global" }, - "marketcap_usd": 232527, + "marketcap_usd": 170925, "name": "Auxilium", "shortcut": "AUX", "t1_enabled": "soon", @@ -26344,7 +26313,7 @@ "links": { "Homepage": "https://callisto.network" }, - "marketcap_usd": 2484504, + "marketcap_usd": 1219815, "name": "Callisto", "shortcut": "CLO", "t1_enabled": "yes", @@ -26386,7 +26355,7 @@ "links": { "Homepage": "https://egem.io" }, - "marketcap_usd": 74246, + "marketcap_usd": 42310, "name": "EtherGem", "shortcut": "EGEM", "t1_enabled": "yes", @@ -26407,7 +26376,7 @@ "links": { "Homepage": "https://ellaism.org" }, - "marketcap_usd": 25863, + "marketcap_usd": 17421, "name": "Ellaism", "shortcut": "ELLA", "t1_enabled": "yes", @@ -26471,7 +26440,7 @@ "links": { "Homepage": "https://ethersocial.org" }, - "marketcap_usd": 145227, + "marketcap_usd": 94783, "name": "Ethersocial Network", "shortcut": "ESN", "t1_enabled": "yes", @@ -26492,7 +26461,7 @@ "links": { "Homepage": "https://ethereumclassic.github.io" }, - "marketcap_usd": 925416572, + "marketcap_usd": 539764555, "name": "Ethereum Classic", "shortcut": "ETC", "t1_enabled": "yes", @@ -26509,7 +26478,7 @@ "links": { "Homepage": "https://www.ethereum.org" }, - "marketcap_usd": 25920996137, + "marketcap_usd": 12903677844, "name": "Ethereum", "shortcut": "ETH", "t1_enabled": "yes", @@ -26526,7 +26495,7 @@ "links": { "Homepage": "https://ether1.org" }, - "marketcap_usd": 228370, + "marketcap_usd": 143343, "name": "Ether-1", "shortcut": "ETHO", "t1_enabled": "yes", @@ -26547,7 +26516,7 @@ "links": { "Homepage": "https://einc.io" }, - "marketcap_usd": 55116, + "marketcap_usd": 16821, "name": "EtherInc", "shortcut": "ETI", "t1_enabled": "yes", @@ -26589,7 +26558,7 @@ "links": { "Homepage": "https://expanse.tech" }, - "marketcap_usd": 744602, + "marketcap_usd": 371204, "name": "Expanse", "shortcut": "EXP", "t1_enabled": "yes", @@ -26610,7 +26579,7 @@ "links": { "Homepage": "https://gochain.io" }, - "marketcap_usd": 12549604, + "marketcap_usd": 4848386, "name": "GoChain", "shortcut": "GO", "t1_enabled": "yes", @@ -26631,7 +26600,7 @@ "links": { "Homepage": "https://hpb.io" }, - "marketcap_usd": 8673315, + "marketcap_usd": 2644553, "name": "High Performance Blockchain", "shortcut": "HPB", "t1_enabled": "yes", @@ -26652,7 +26621,7 @@ "links": { "Homepage": "https://metadium.com" }, - "marketcap_usd": 9001045, + "marketcap_usd": 7497948, "name": "Metadium", "shortcut": "META", "t1_enabled": "yes", @@ -26715,7 +26684,7 @@ "links": { "Homepage": "https://pirl.io" }, - "marketcap_usd": 474659, + "marketcap_usd": 301462, "name": "Pirl", "shortcut": "PIRL", "t1_enabled": "yes", @@ -26799,7 +26768,7 @@ "links": { "Homepage": "https://ubiqsmart.com" }, - "marketcap_usd": 4172282, + "marketcap_usd": 1968570, "name": "Ubiq", "shortcut": "UBQ", "t1_enabled": "yes", @@ -26842,7 +26811,7 @@ "Github": "https://github.com/input-output-hk/cardano-sl", "Homepage": "https://www.cardano.org" }, - "marketcap_usd": 1328814701, + "marketcap_usd": 672071442, "name": "Cardano", "shortcut": "ADA", "t1_enabled": "no", @@ -26876,7 +26845,7 @@ "Github": "https://github.com/EOSIO/eos", "Homepage": "https://eos.io" }, - "marketcap_usd": 3380617147, + "marketcap_usd": 1817735198, "name": "EOS", "shortcut": "EOS", "t1_enabled": "no", @@ -26894,7 +26863,7 @@ "Github": "https://github.com/LiskHQ/lisk", "Homepage": "https://lisk.io/" }, - "marketcap_usd": 171754397, + "marketcap_usd": 106336194, "name": "Lisk", "shortcut": "LSK", "t1_enabled": "yes", @@ -26912,7 +26881,7 @@ "Github": "https://github.com/maidsafe", "Homepage": "https://maidsafe.net" }, - "marketcap_usd": 38621521, + "marketcap_usd": 21706202, "name": "MaidSafeCoin", "shortcut": "MAID", "t1_enabled": "yes", @@ -26925,7 +26894,7 @@ "Github": "https://github.com/OmniLayer", "Homepage": "https://www.omnilayer.org" }, - "marketcap_usd": 806799, + "marketcap_usd": 558309, "name": "Omni", "shortcut": "OMNI", "t1_enabled": "yes", @@ -26938,7 +26907,7 @@ "Github": "https://github.com/ontio/ontology", "Homepage": "https://ont.io" }, - "marketcap_usd": 457438616, + "marketcap_usd": 210641476, "name": "Ontology", "shortcut": "ONT", "t1_enabled": "no", @@ -26950,7 +26919,7 @@ "links": { "Homepage": "https://tether.to" }, - "marketcap_usd": 4637165054, + "marketcap_usd": 4655051268, "name": "Tether", "shortcut": "USDT", "t1_enabled": "yes", @@ -26963,7 +26932,7 @@ "Github": "https://github.com/wanchain/go-wanchain", "Homepage": "https://wanchain.org" }, - "marketcap_usd": 26073873, + "marketcap_usd": 10683819, "name": "Wanchain", "shortcut": "WAN", "t1_enabled": "yes", @@ -26981,7 +26950,7 @@ "Github": "https://github.com/stellar/stellar-core", "Homepage": "https://www.stellar.org" }, - "marketcap_usd": 1254569540, + "marketcap_usd": 745537578, "name": "Stellar", "shortcut": "XLM", "t1_enabled": "yes", @@ -27003,7 +26972,7 @@ "Github": "https://github.com/monero-project/monero", "Homepage": "https://getmonero.org" }, - "marketcap_usd": 1254051585, + "marketcap_usd": 634185955, "name": "Monero", "shortcut": "XMR", "t1_enabled": "no", @@ -27021,7 +26990,7 @@ "Github": "https://github.com/ripple/rippled", "Homepage": "https://ripple.com" }, - "marketcap_usd": 10732323902, + "marketcap_usd": 6509252831, "name": "Ripple", "shortcut": "XRP", "t1_enabled": "no", @@ -27047,7 +27016,7 @@ "Github": "https://github.com/tezos/tezos", "Homepage": "https://tezos.com" }, - "marketcap_usd": 2045788875, + "marketcap_usd": 1001121819, "name": "Tezos", "shortcut": "XTZ", "t1_enabled": "no", @@ -27089,7 +27058,7 @@ "links": { "Homepage": "https://www.dimcoin.io" }, - "marketcap_usd": 295457, + "marketcap_usd": 284935, "name": "DIMCOIN", "shortcut": "DIM", "t1_enabled": "yes", @@ -27111,7 +27080,7 @@ "links": { "Homepage": "https://www.dimcoin.io" }, - "marketcap_usd": 295457, + "marketcap_usd": 284935, "name": "DIM TOKEN", "shortcut": "DIMTOK", "t1_enabled": "yes", @@ -27174,7 +27143,7 @@ "links": { "Homepage": "https://nem.io" }, - "marketcap_usd": 466507162, + "marketcap_usd": 300648795, "name": "NEM", "shortcut": "XEM", "t1_enabled": "yes", @@ -27193,12 +27162,12 @@ } }, "info": { - "marketcap_supported": "92.35 %", - "marketcap_usd": 235723762431, + "marketcap_supported": "91.24 %", + "marketcap_usd": 138673984862, "t1_coins": 1049, - "t2_coins": 1162, - "total_marketcap_usd": 255254453733, - "updated_at": 1582827094, - "updated_at_readable": "Thu Feb 27 19:11:34 2020" + "t2_coins": 1159, + "total_marketcap_usd": 151981454022, + "updated_at": 1584441141, + "updated_at_readable": "Tue Mar 17 11:32:21 2020" } } diff --git a/common/defs/support.json b/common/defs/support.json index 6b9e8ec55..f141b4b1b 100644 --- a/common/defs/support.json +++ b/common/defs/support.json @@ -8,7 +8,6 @@ "bitcoin:BTCP": true, "bitcoin:BTG": true, "bitcoin:BTX": true, - "bitcoin:CPC": true, "bitcoin:DASH": true, "bitcoin:DGB": true, "bitcoin:DOGE": true, @@ -43,7 +42,6 @@ "bitcoin:XZC": true, "bitcoin:ZCR": true, "bitcoin:ZEC": true, - "bitcoin:ZEN": true, "bitcoin:ZNY": true, "bitcoin:tDASH": true, "bitcoin:tLTC": true, @@ -1691,9 +1689,7 @@ "nem:XEM": "1.6.2" }, "unsupported": { - "bitcoin:CPC": "not implemented", "bitcoin:TRC": "address_type collides with Bitcoin", - "bitcoin:ZEN": "not implemented", "erc20:etc:PLAY": "(AUTO) duplicate key", "erc20:eth:A18:ba7d": "(AUTO) duplicate key", "erc20:eth:A18:bde8": "(AUTO) duplicate key", @@ -1735,7 +1731,6 @@ "erc20:eth:COIN:eb54": "(AUTO) duplicate key", "erc20:eth:COSS:6529": "(AUTO) duplicate key", "erc20:eth:COSS:9e96": "(AUTO) duplicate key", - "erc20:eth:CPC": "duplicate key with bitcoin:CPC", "erc20:eth:CPT:88d5": "(AUTO) duplicate key", "erc20:eth:CPT:9b62": "(AUTO) duplicate key", "erc20:eth:CTT:1a47": "(AUTO) duplicate key", @@ -1924,7 +1919,6 @@ "bitcoin:BTCP": "2.0.7", "bitcoin:BTG": "2.0.7", "bitcoin:BTX": "2.0.8", - "bitcoin:CPC": "2.0.10", "bitcoin:CPU": "2.1.4", "bitcoin:CRW": "2.1.7", "bitcoin:DASH": "2.0.5", @@ -1974,7 +1968,6 @@ "bitcoin:ZCR": "2.1.7", "bitcoin:ZEC": "2.0.8", "bitcoin:ZEL": "2.1.4", - "bitcoin:ZEN": "2.0.8", "bitcoin:ZNY": "2.1.1", "bitcoin:tDASH": "2.0.8", "bitcoin:tGRS": "2.0.8", @@ -3564,7 +3557,6 @@ "erc20:eth:COIN:eb54": "(AUTO) duplicate key", "erc20:eth:COSS:6529": "(AUTO) duplicate key", "erc20:eth:COSS:9e96": "(AUTO) duplicate key", - "erc20:eth:CPC": "duplicate key with bitcoin:CPC", "erc20:eth:CPT:88d5": "(AUTO) duplicate key", "erc20:eth:CPT:9b62": "(AUTO) duplicate key", "erc20:eth:CTT:1a47": "(AUTO) duplicate key", diff --git a/common/defs/wallets.json b/common/defs/wallets.json index b6a5683ce..38678b702 100644 --- a/common/defs/wallets.json +++ b/common/defs/wallets.json @@ -28,9 +28,6 @@ "Electrum-BTX": "https://github.com/LIMXTEC/electrum-btx", "Magnum": "https://magnumwallet.co" }, - "bitcoin:CPC": { - "Capricoin Mobile Wallet": "https://wallet.capricoin.org" - }, "bitcoin:CPU": { "Electrum-CPU": "https://cpuchain.org/download-page.html" }, diff --git a/common/protob/messages-bitcoin.proto b/common/protob/messages-bitcoin.proto index eb119a17a..a5effcaf8 100644 --- a/common/protob/messages-bitcoin.proto +++ b/common/protob/messages-bitcoin.proto @@ -130,10 +130,10 @@ message SignTx { optional uint32 version = 4 [default=1]; // transaction version optional uint32 lock_time = 5 [default=0]; // transaction lock_time optional uint32 expiry = 6; // only for Decred and Zcash - optional bool overwintered = 7; // only for Zcash - optional uint32 version_group_id = 8; // only for Zcash, nVersionGroupId when overwintered is set - optional uint32 timestamp = 9; // only for Peercoin, Capricoin - optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID when overwintered is set + // optional bool overwintered = 7; // deprecated - only for Zcash + optional uint32 version_group_id = 8; // only for Zcash, nVersionGroupId + optional uint32 timestamp = 9; // only for Peercoin + optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID } /** @@ -196,10 +196,10 @@ message TxAck { optional bytes extra_data = 8; // only for Dash, Zcash optional uint32 extra_data_len = 9; // only for Dash, Zcash optional uint32 expiry = 10; // only for Decred and Zcash - optional bool overwintered = 11; // only for Zcash - optional uint32 version_group_id = 12; // only for Zcash, nVersionGroupId when overwintered is set - optional uint32 timestamp = 13; // only for Peercoin, Capricoin - optional uint32 branch_id = 14; // only for Zcash, BRANCH_ID when overwintered is set + // optional bool overwintered = 11; // deprecated - only for Zcash + optional uint32 version_group_id = 12; // only for Zcash, nVersionGroupId + optional uint32 timestamp = 13; // only for Peercoin + optional uint32 branch_id = 14; // only for Zcash, BRANCH_ID /** * Structure representing transaction input */ @@ -214,8 +214,8 @@ message TxAck { optional uint64 amount = 8; // amount of previous transaction output (for segwit only) optional uint32 decred_tree = 9; // only for Decred optional uint32 decred_script_version = 10; // only for Decred - optional bytes prev_block_hash_bip115 = 11; // block hash of previous transaction output (for bip115 implementation) - optional uint32 prev_block_height_bip115 = 12; // block height of previous transaction output (for bip115 implementation) + // optional bytes prev_block_hash_bip115 = 11; // BIP-115 support dropped + // optional uint32 prev_block_height_bip115 = 12; // BIP-115 support dropped } /** * Structure representing compiled transaction output @@ -236,8 +236,8 @@ message TxAck { optional MultisigRedeemScriptType multisig = 5; // defines multisig address; script_type must be PAYTOMULTISIG optional bytes op_return_data = 6; // defines op_return data; script_type must be PAYTOOPRETURN, amount must be 0 optional uint32 decred_script_version = 7; // only for Decred - optional bytes block_hash_bip115 = 8; // block hash of existing block (recommended current_block - 300) (for bip115 implementation) - optional uint32 block_height_bip115 = 9; // block height of existing block (recommended current_block - 300) (for bip115 implementation) + // optional bytes block_hash_bip115 = 8; // BIP-115 support dropped + // optional uint32 block_height_bip115 = 9; // BIP-115 support dropped enum OutputScriptType { PAYTOADDRESS = 0; // used for all addresses (bitcoin, p2sh, witness) PAYTOSCRIPTHASH = 1; // p2sh address (deprecated; use PAYTOADDRESS) diff --git a/common/tools/coin_info.py b/common/tools/coin_info.py index b87cb2919..36042af40 100755 --- a/common/tools/coin_info.py +++ b/common/tools/coin_info.py @@ -136,7 +136,6 @@ BTC_CHECKS = [ check_key("decred", bool), check_key("fork_id", int, nullable=True), check_key("force_bip143", bool), - check_key("bip115", bool), check_key("default_fee_b", dict), check_key("dust_limit", int), check_key("blocktime_seconds", int), diff --git a/common/tools/coindef.py b/common/tools/coindef.py index 50eb50c79..207601387 100644 --- a/common/tools/coindef.py +++ b/common/tools/coindef.py @@ -33,7 +33,6 @@ class CoinDef(p.MessageType): 29: ("github", p.UnicodeType, 0), 30: ("maintainer", p.UnicodeType, 0), 31: ("blocktime_seconds", p.UVarintType, 0), - 32: ("bip115", p.BoolType, 0), 33: ("cooldown", p.UVarintType, 0), } @@ -60,7 +59,6 @@ class CoinDef(p.MessageType): decred: bool = None, fork_id: int = None, force_bip143: bool = None, - bip115: bool = None, dust_limit: int = None, uri_prefix: str = None, min_address_length: int = None, @@ -96,7 +94,6 @@ class CoinDef(p.MessageType): self.decred = decred self.fork_id = fork_id self.force_bip143 = force_bip143 - self.bip115 = bip115 self.dust_limit = dust_limit self.uri_prefix = uri_prefix self.min_address_length = min_address_length diff --git a/core/src/apps/binance/layout.py b/core/src/apps/binance/layout.py index e2a7422fd..89b430cc5 100644 --- a/core/src/apps/binance/layout.py +++ b/core/src/apps/binance/layout.py @@ -13,7 +13,7 @@ from trezor.ui.text import Text from . import helpers -from apps.common.confirm import hold_to_confirm +from apps.common.confirm import require_hold_to_confirm from apps.common.layout import split_address @@ -38,7 +38,9 @@ async def require_confirm_transfer(ctx, msg: BinanceTransferMsg): for txoutput in msg.outputs: pages.extend(make_input_output_pages(txoutput, "output")) - return await hold_to_confirm(ctx, Paginated(pages), ButtonRequestType.ConfirmOutput) + return await require_hold_to_confirm( + ctx, Paginated(pages), ButtonRequestType.ConfirmOutput + ) async def require_confirm_cancel(ctx, msg: BinanceCancelMsg): @@ -52,7 +54,7 @@ async def require_confirm_cancel(ctx, msg: BinanceCancelMsg): page2.normal("Order ID:") page2.bold(msg.refid) - return await hold_to_confirm( + return await require_hold_to_confirm( ctx, Paginated([page1, page2]), ButtonRequestType.SignTx ) @@ -77,6 +79,6 @@ async def require_confirm_order(ctx, msg: BinanceOrderMsg): page3.normal("Price:") page3.bold(format_amount(msg.price, helpers.DECIMALS)) - return await hold_to_confirm( + return await require_hold_to_confirm( ctx, Paginated([page1, page2, page3]), ButtonRequestType.SignTx ) diff --git a/core/src/apps/cardano/layout/__init__.py b/core/src/apps/cardano/layout/__init__.py index 53c2a7fb4..f5f8fae0a 100644 --- a/core/src/apps/cardano/layout/__init__.py +++ b/core/src/apps/cardano/layout/__init__.py @@ -6,7 +6,7 @@ from trezor.ui.scroll import Paginated from trezor.ui.text import Text from trezor.utils import chunks -from apps.common.confirm import confirm, hold_to_confirm +from apps.common.confirm import require_confirm, require_hold_to_confirm def format_coin_amount(amount): @@ -32,7 +32,7 @@ async def confirm_sending(ctx, amount, to): t.bold(line) pages.append(t) - return await confirm(ctx, Paginated(pages)) + await require_confirm(ctx, Paginated(pages)) async def confirm_transaction(ctx, amount, fee, network_name): @@ -46,4 +46,4 @@ async def confirm_transaction(ctx, amount, fee, network_name): t2.normal("Network:") t2.bold(network_name) - return await hold_to_confirm(ctx, Paginated([t1, t2])) + await require_hold_to_confirm(ctx, Paginated([t1, t2])) diff --git a/core/src/apps/cardano/sign_tx.py b/core/src/apps/cardano/sign_tx.py index e32eaa1a9..60dd41547 100644 --- a/core/src/apps/cardano/sign_tx.py +++ b/core/src/apps/cardano/sign_tx.py @@ -47,19 +47,15 @@ async def show_tx( network_name: str, raw_inputs: list, raw_outputs: list, -) -> bool: +) -> None: for index, output in enumerate(outputs): if is_change(raw_outputs[index].address_n, raw_inputs): continue - if not await confirm_sending(ctx, outcoins[index], output): - return False + await confirm_sending(ctx, outcoins[index], output) total_amount = sum(outcoins) - if not await confirm_transaction(ctx, total_amount, fee, network_name): - return False - - return True + await confirm_transaction(ctx, total_amount, fee, network_name) async def request_transaction(ctx, tx_req: CardanoTxRequest, index: int): @@ -114,7 +110,7 @@ async def sign_tx(ctx, msg): raise wire.ProcessError("Signing failed") # display the transaction in UI - if not await show_tx( + await show_tx( ctx, transaction.output_addresses, transaction.outgoing_coins, @@ -122,8 +118,7 @@ async def sign_tx(ctx, msg): transaction.network_name, transaction.inputs, transaction.outputs, - ): - raise wire.ActionCancelled("Signing cancelled") + ) return tx diff --git a/core/src/apps/common/coininfo.py b/core/src/apps/common/coininfo.py index c6dd6709f..1851e434d 100644 --- a/core/src/apps/common/coininfo.py +++ b/core/src/apps/common/coininfo.py @@ -26,10 +26,12 @@ class CoinInfo: segwit: bool, fork_id: int, force_bip143: bool, - bip115: bool, decred: bool, negative_fee: bool, curve_name: str, + extra_data: bool, + timestamp: bool, + overwintered: bool, confidential_assets: dict, ): self.coin_name = coin_name @@ -48,10 +50,12 @@ class CoinInfo: self.segwit = segwit self.fork_id = fork_id self.force_bip143 = force_bip143 - self.bip115 = bip115 self.decred = decred self.negative_fee = negative_fee self.curve_name = curve_name + self.extra_data = extra_data + self.timestamp = timestamp + self.overwintered = overwintered self.confidential_assets = confidential_assets if curve_name == "secp256k1-groestl": self.b58_hash = groestl512d_32 @@ -98,10 +102,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Regtest": @@ -122,10 +128,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Testnet": @@ -146,10 +154,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) if not utils.BITCOIN_ONLY: @@ -173,10 +183,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Axe": @@ -197,10 +209,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bellcoin": @@ -221,10 +235,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "BitZeny": @@ -245,10 +261,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bcash": @@ -269,10 +287,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=0, force_bip143=True, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bcash Testnet": @@ -293,10 +313,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=0, force_bip143=True, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bgold": @@ -317,10 +339,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=79, force_bip143=True, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bgold Testnet": @@ -341,10 +365,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=79, force_bip143=True, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bprivate": @@ -365,10 +391,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=42, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Brhodium": @@ -389,10 +417,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Bitcore": @@ -413,10 +443,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "CPUchain": @@ -437,34 +469,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, - decred=False, - negative_fee=False, - curve_name='secp256k1', - confidential_assets=None, - ) - elif name == "Capricoin": - return CoinInfo( - coin_name=name, - coin_shortcut="CPC", - decimals=8, - address_type=28, - address_type_p2sh=35, - maxfee_kb=2000000, - signed_message_header="Capricoin Signed Message:\n", - xpub_magic=0x0488b21e, - xpub_magic_segwit_p2sh=None, - xpub_magic_segwit_native=None, - bech32_prefix=None, - cashaddr_prefix=None, - slip44=289, - segwit=False, - fork_id=None, - force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Crown": @@ -485,10 +495,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Dash": @@ -509,10 +521,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=True, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Dash Testnet": @@ -533,10 +547,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=True, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Decred": @@ -557,10 +573,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=True, negative_fee=False, curve_name='secp256k1-decred', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Decred Testnet": @@ -581,10 +599,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=True, negative_fee=False, curve_name='secp256k1-decred', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "DigiByte": @@ -605,10 +625,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Dogecoin": @@ -629,10 +651,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Elements": @@ -653,10 +677,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets={'address_prefix': 4, 'blech32_prefix': 'el'}, ) elif name == "Feathercoin": @@ -677,10 +703,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Florincoin": @@ -701,10 +729,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Fujicoin": @@ -725,10 +755,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Gincoin": @@ -749,10 +781,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "GameCredits": @@ -773,10 +807,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Groestlcoin": @@ -797,10 +833,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1-groestl', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Groestlcoin Testnet": @@ -821,10 +859,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1-groestl', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Hatch": @@ -845,10 +885,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Hatch Testnet": @@ -869,34 +911,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, - decred=False, - negative_fee=False, - curve_name='secp256k1', - confidential_assets=None, - ) - elif name == "Horizen": - return CoinInfo( - coin_name=name, - coin_shortcut="ZEN", - decimals=8, - address_type=8329, - address_type_p2sh=8342, - maxfee_kb=2000000, - signed_message_header="Zcash Signed Message:\n", - xpub_magic=0x0488b21e, - xpub_magic_segwit_p2sh=None, - xpub_magic_segwit_native=None, - bech32_prefix=None, - cashaddr_prefix=None, - slip44=121, - segwit=False, - fork_id=None, - force_bip143=False, - bip115=True, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Komodo": @@ -917,10 +937,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=True, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=True, confidential_assets=None, ) elif name == "Koto": @@ -941,10 +963,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Litecoin": @@ -965,10 +989,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Litecoin Testnet": @@ -989,10 +1015,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "MetaverseETP": @@ -1013,10 +1041,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Monacoin": @@ -1037,10 +1067,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "MonetaryUnit": @@ -1061,10 +1093,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "NIX": @@ -1085,10 +1119,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Namecoin": @@ -1109,10 +1145,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "PIVX": @@ -1133,10 +1171,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "PIVX Testnet": @@ -1157,10 +1197,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Particl": @@ -1181,10 +1223,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Particl Testnet": @@ -1205,10 +1249,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Peercoin": @@ -1229,10 +1275,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=True, + overwintered=False, confidential_assets=None, ) elif name == "Peercoin Testnet": @@ -1253,10 +1301,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=True, + overwintered=False, confidential_assets=None, ) elif name == "Pesetacoin": @@ -1277,10 +1327,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Polis": @@ -1301,10 +1353,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Primecoin": @@ -1325,10 +1379,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Qtum": @@ -1349,10 +1405,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Qtum Testnet": @@ -1373,10 +1431,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Ravencoin": @@ -1397,10 +1457,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Ritocoin": @@ -1421,10 +1483,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "SmartCash": @@ -1445,10 +1509,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1-smart', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "SmartCash Testnet": @@ -1469,10 +1535,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1-smart', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Stakenet": @@ -1493,10 +1561,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Syscoin": @@ -1517,10 +1587,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Unobtanium": @@ -1541,10 +1613,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "VIPSTARCOIN": @@ -1565,10 +1639,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Vertcoin": @@ -1589,10 +1665,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Viacoin": @@ -1613,10 +1691,12 @@ def by_name(name: str) -> CoinInfo: segwit=True, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "ZCore": @@ -1637,10 +1717,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Zcash": @@ -1661,10 +1743,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=True, + timestamp=False, + overwintered=True, confidential_assets=None, ) elif name == "Zcash Testnet": @@ -1685,10 +1769,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=True, + timestamp=False, + overwintered=True, confidential_assets=None, ) elif name == "Zcoin": @@ -1709,10 +1795,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "Zcoin Testnet": @@ -1733,10 +1821,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) elif name == "ZelCash": @@ -1757,10 +1847,12 @@ def by_name(name: str) -> CoinInfo: segwit=False, fork_id=None, force_bip143=False, - bip115=False, decred=False, negative_fee=False, curve_name='secp256k1', + extra_data=False, + timestamp=False, + overwintered=False, confidential_assets=None, ) raise ValueError('Unknown coin name "%s"' % name) diff --git a/core/src/apps/common/coininfo.py.mako b/core/src/apps/common/coininfo.py.mako index 14f8784a4..53effc64c 100644 --- a/core/src/apps/common/coininfo.py.mako +++ b/core/src/apps/common/coininfo.py.mako @@ -26,10 +26,12 @@ class CoinInfo: segwit: bool, fork_id: int, force_bip143: bool, - bip115: bool, decred: bool, negative_fee: bool, curve_name: str, + extra_data: bool, + timestamp: bool, + overwintered: bool, confidential_assets: dict, ): self.coin_name = coin_name @@ -48,10 +50,12 @@ class CoinInfo: self.segwit = segwit self.fork_id = fork_id self.force_bip143 = force_bip143 - self.bip115 = bip115 self.decred = decred self.negative_fee = negative_fee self.curve_name = curve_name + self.extra_data = extra_data + self.timestamp = timestamp + self.overwintered = overwintered self.confidential_assets = confidential_assets if curve_name == "secp256k1-groestl": self.b58_hash = groestl512d_32 @@ -106,10 +110,12 @@ ATTRIBUTES = ( ("segwit", bool), ("fork_id", black_repr), ("force_bip143", bool), - ("bip115", bool), ("decred", bool), ("negative_fee", bool), ("curve_name", lambda r: repr(r.replace("_", "-"))), + ("extra_data", bool), + ("timestamp", bool), + ("overwintered", bool), ("confidential_assets", optional_dict), ) @@ -118,6 +124,9 @@ btc_names = ["Bitcoin", "Testnet", "Regtest"] coins_btc = [c for c in supported_on("trezor2", bitcoin) if c.name in btc_names] coins_alt = [c for c in supported_on("trezor2", bitcoin) if c.name not in btc_names] +for c in coins_btc + coins_alt: + c.overwintered = bool(c.consensus_branch_id) + %>\ def by_name(name: str) -> CoinInfo: if False: diff --git a/core/src/apps/common/confirm.py b/core/src/apps/common/confirm.py index 5602e9d12..b8ec7866c 100644 --- a/core/src/apps/common/confirm.py +++ b/core/src/apps/common/confirm.py @@ -84,6 +84,7 @@ async def hold_to_confirm( confirm: str = HoldToConfirm.DEFAULT_CONFIRM, confirm_style: ButtonStyleType = HoldToConfirm.DEFAULT_CONFIRM_STYLE, loader_style: LoaderStyleType = HoldToConfirm.DEFAULT_LOADER_STYLE, + cancel: bool = True, ) -> bool: await ctx.call(ButtonRequest(code=code), ButtonAck) @@ -93,11 +94,11 @@ async def hold_to_confirm( assert isinstance(content, Paginated) content.pages[-1] = HoldToConfirm( - content.pages[-1], confirm, confirm_style, loader_style + content.pages[-1], confirm, confirm_style, loader_style, cancel ) dialog = content # type: ui.Layout else: - dialog = HoldToConfirm(content, confirm, confirm_style, loader_style) + dialog = HoldToConfirm(content, confirm, confirm_style, loader_style, cancel) return await ctx.wait(dialog) is CONFIRMED diff --git a/core/src/apps/common/writers.py b/core/src/apps/common/writers.py index ec23c2518..118757d36 100644 --- a/core/src/apps/common/writers.py +++ b/core/src/apps/common/writers.py @@ -78,11 +78,18 @@ def write_uint64_be(w: Writer, n: int) -> int: return 8 -def write_bytes(w: Writer, b: bytes) -> int: +def write_bytes_unchecked(w: Writer, b: bytes) -> int: w.extend(b) return len(b) -def write_bytes_reversed(w: Writer, b: bytes) -> int: +def write_bytes_fixed(w: Writer, b: bytes, length: int) -> int: + ensure(len(b) == length) + w.extend(b) + return length + + +def write_bytes_reversed(w: Writer, b: bytes, length: int) -> int: + ensure(len(b) == length) w.extend(bytes(reversed(b))) - return len(b) + return length diff --git a/core/src/apps/eos/actions/__init__.py b/core/src/apps/eos/actions/__init__.py index 8adf5ccfb..8f43ac747 100644 --- a/core/src/apps/eos/actions/__init__.py +++ b/core/src/apps/eos/actions/__init__.py @@ -68,7 +68,7 @@ async def process_action( writers.write_action_common(sha, action.common) writers.write_variant32(sha, len(w)) - writers.write_bytes(sha, w) + writers.write_bytes_unchecked(sha, w) async def process_unknown_action( @@ -78,7 +78,7 @@ async def process_unknown_action( writers.write_variant32(checksum, action.unknown.data_size) checksum.extend(action.unknown.data_chunk) - writers.write_bytes(w, action.unknown.data_chunk) + writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left = action.unknown.data_size - len(action.unknown.data_chunk) while bytes_left != 0: @@ -90,7 +90,7 @@ async def process_unknown_action( raise ValueError("Bad response. Unknown struct expected.") checksum.extend(action.unknown.data_chunk) - writers.write_bytes(w, action.unknown.data_chunk) + writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left -= len(action.unknown.data_chunk) if bytes_left < 0: diff --git a/core/src/apps/eos/sign_tx.py b/core/src/apps/eos/sign_tx.py index db82da859..e47bc23b5 100644 --- a/core/src/apps/eos/sign_tx.py +++ b/core/src/apps/eos/sign_tx.py @@ -34,7 +34,7 @@ async def sign_tx( await _init(ctx, sha, msg) await _actions(ctx, sha, msg.num_actions) writers.write_variant32(sha, 0) - writers.write_bytes(sha, bytearray(32)) + writers.write_bytes_unchecked(sha, bytearray(32)) digest = sha.get_digest() signature = secp256k1.sign( @@ -45,7 +45,7 @@ async def sign_tx( async def _init(ctx: wire.Context, sha: HashWriter, msg: EosSignTx) -> None: - writers.write_bytes(sha, msg.chain_id) + writers.write_bytes_unchecked(sha, msg.chain_id) writers.write_header(sha, msg.header) writers.write_variant32(sha, 0) writers.write_variant32(sha, msg.num_actions) diff --git a/core/src/apps/eos/writers.py b/core/src/apps/eos/writers.py index 81ea92912..fc6cf589a 100644 --- a/core/src/apps/eos/writers.py +++ b/core/src/apps/eos/writers.py @@ -1,5 +1,5 @@ from apps.common.writers import ( - write_bytes, + write_bytes_unchecked, write_uint8, write_uint16_le, write_uint32_le, @@ -31,7 +31,7 @@ def write_auth(w: Writer, auth: EosAuthorization) -> None: write_variant32(w, len(auth.keys)) for key in auth.keys: write_variant32(w, key.type) - write_bytes(w, key.key) + write_bytes_unchecked(w, key.key) write_uint16_le(w, key.weight) write_variant32(w, len(auth.accounts)) @@ -60,7 +60,7 @@ def write_action_transfer(w: Writer, msg: EosActionTransfer) -> None: write_uint64_le(w, msg.receiver) write_asset(w, msg.quantity) write_variant32(w, len(msg.memo)) - write_bytes(w, msg.memo) + write_bytes_unchecked(w, msg.memo) def write_action_buyram(w: Writer, msg: EosActionBuyRam) -> None: @@ -162,4 +162,4 @@ def write_variant32(w: Writer, value: int) -> None: variant.append(b) if value == 0: break - write_bytes(w, bytes(variant)) + write_bytes_unchecked(w, bytes(variant)) diff --git a/core/src/apps/ethereum/tokens.py b/core/src/apps/ethereum/tokens.py index 9249cafcd..37c26cbc9 100644 --- a/core/src/apps/ethereum/tokens.py +++ b/core/src/apps/ethereum/tokens.py @@ -542,6 +542,8 @@ def token_by_chain_address(chain_id, address): return (chain_id, address, "CPAL", 8) # eth / CreatorPAL elif address == b"\x0e\xbb\x61\x42\x04\xe4\x7c\x09\xb6\xc3\xfe\xb9\xaa\xec\xad\x8e\xe0\x60\xe2\x3e": return (chain_id, address, "CPAY", 0) # eth / Cryptopay + elif address == b"\xfa\xe4\xee\x59\xcd\xd8\x6e\x3b\xe9\xe8\xb9\x0b\x53\xaa\x86\x63\x27\xd7\xc0\x90": + return (chain_id, address, "CPC", 18) # eth / CPChain elif address == b"\xb7\x87\xd4\xea\xc8\x89\x97\x30\xbb\x8c\x57\xfc\x3c\x99\x8c\x49\xc5\x24\x4e\xc0": return (chain_id, address, "CPEX", 8) # eth / CoinPulseToken elif address == b"\x70\x64\xaa\xb3\x9a\x0f\xcf\x72\x21\xc3\x39\x67\x19\xd0\x91\x7a\x65\xe3\x55\x15": diff --git a/core/src/apps/management/reset_device/layout.py b/core/src/apps/management/reset_device/layout.py index 93aa99354..b6a5606e5 100644 --- a/core/src/apps/management/reset_device/layout.py +++ b/core/src/apps/management/reset_device/layout.py @@ -11,7 +11,7 @@ from trezor.ui.num_input import NumInput from trezor.ui.scroll import Paginated from trezor.ui.text import Text -from apps.common.confirm import confirm, hold_to_confirm, require_confirm +from apps.common.confirm import confirm, require_confirm, require_hold_to_confirm from apps.common.layout import show_success if __debug__: @@ -127,7 +127,9 @@ async def _show_share_words(ctx, share_words, share_index=None, group_index=None utils.ensure(share_words == shares_words_check) # confirm the share - await hold_to_confirm(ctx, paginated, ButtonRequestType.ResetDevice) + await require_hold_to_confirm( + ctx, paginated, ButtonRequestType.ResetDevice, cancel=False + ) def _split_share_into_pages(share_words): diff --git a/core/src/apps/nem/writers.py b/core/src/apps/nem/writers.py index cd0e28c5a..f049a8512 100644 --- a/core/src/apps/nem/writers.py +++ b/core/src/apps/nem/writers.py @@ -1,6 +1,6 @@ from trezor.messages.NEMTransactionCommon import NEMTransactionCommon -from apps.common.writers import write_bytes, write_uint32_le, write_uint64_le +from apps.common.writers import write_bytes_unchecked, write_uint32_le, write_uint64_le def serialize_tx_common( @@ -26,4 +26,4 @@ def serialize_tx_common( def write_bytes_with_len(w, buf: bytes): write_uint32_le(w, len(buf)) - write_bytes(w, buf) + write_bytes_unchecked(w, buf) diff --git a/core/src/apps/ripple/serialize.py b/core/src/apps/ripple/serialize.py index be0cea854..b54e9b61b 100644 --- a/core/src/apps/ripple/serialize.py +++ b/core/src/apps/ripple/serialize.py @@ -63,9 +63,9 @@ def write(w: bytearray, field: dict, value): elif field["type"] == FIELD_TYPE_AMOUNT: w.extend(serialize_amount(value)) elif field["type"] == FIELD_TYPE_ACCOUNT: - write_bytes(w, helpers.decode_address(value)) + write_bytes_varint(w, helpers.decode_address(value)) elif field["type"] == FIELD_TYPE_VL: - write_bytes(w, value) + write_bytes_varint(w, value) else: raise ValueError("Unknown field type") @@ -91,7 +91,7 @@ def serialize_amount(value: int) -> bytearray: return b -def write_bytes(w: bytearray, value: bytes): +def write_bytes_varint(w: bytearray, value: bytes): """Serialize a variable length bytes.""" write_varint(w, len(value)) w.extend(value) diff --git a/core/src/apps/stellar/operations/serialize.py b/core/src/apps/stellar/operations/serialize.py index 10b34f38c..2ab3e8e5d 100644 --- a/core/src/apps/stellar/operations/serialize.py +++ b/core/src/apps/stellar/operations/serialize.py @@ -119,7 +119,7 @@ def write_set_options_op(w, msg: StellarSetOptionsOp): elif msg.signer_type in consts.SIGN_TYPES: writers.write_bool(w, True) writers.write_uint32(w, msg.signer_type) - writers.write_bytes(w, msg.signer_key) + writers.write_bytes_unchecked(w, msg.signer_key) writers.write_uint32(w, msg.signer_weight) else: raise ProcessError("Stellar: unknown signer type") @@ -146,10 +146,10 @@ def _write_asset_code(w, asset_type: int, asset_code: str): return # nothing is needed elif asset_type == consts.ASSET_TYPE_ALPHANUM4: # pad with zeros to 4 chars - writers.write_bytes(w, code + bytearray([0] * (4 - len(code)))) + writers.write_bytes_unchecked(w, code + bytearray([0] * (4 - len(code)))) elif asset_type == consts.ASSET_TYPE_ALPHANUM12: # pad with zeros to 12 chars - writers.write_bytes(w, code + bytearray([0] * (12 - len(code)))) + writers.write_bytes_unchecked(w, code + bytearray([0] * (12 - len(code)))) else: raise ProcessError("Stellar: invalid asset type") diff --git a/core/src/apps/stellar/sign_tx.py b/core/src/apps/stellar/sign_tx.py index c77b99e81..13e3ad121 100644 --- a/core/src/apps/stellar/sign_tx.py +++ b/core/src/apps/stellar/sign_tx.py @@ -47,8 +47,8 @@ async def _final(ctx, w: bytearray, msg: StellarSignTx): async def _init(ctx, w: bytearray, pubkey: bytes, msg: StellarSignTx): network_passphrase_hash = sha256(msg.network_passphrase).digest() - writers.write_bytes(w, network_passphrase_hash) - writers.write_bytes(w, consts.TX_TYPE) + writers.write_bytes_unchecked(w, network_passphrase_hash) + writers.write_bytes_unchecked(w, consts.TX_TYPE) address = helpers.address_from_public_key(pubkey) accounts_match = msg.source_account == address @@ -103,7 +103,7 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx): memo_confirm_text = str(msg.memo_id) elif msg.memo_type in (consts.MEMO_TYPE_HASH, consts.MEMO_TYPE_RETURN): # Hash/Return: 32 byte hash - writers.write_bytes(w, bytearray(msg.memo_hash)) + writers.write_bytes_unchecked(w, bytearray(msg.memo_hash)) memo_confirm_text = hexlify(msg.memo_hash).decode() else: raise ProcessError("Stellar invalid memo type") diff --git a/core/src/apps/stellar/writers.py b/core/src/apps/stellar/writers.py index 0846d148f..72f25492b 100644 --- a/core/src/apps/stellar/writers.py +++ b/core/src/apps/stellar/writers.py @@ -1,6 +1,6 @@ from .helpers import public_key_from_address -from apps.common.writers import write_bytes, write_uint32_be, write_uint64_be +from apps.common.writers import write_bytes_unchecked, write_uint32_be, write_uint64_be write_uint32 = write_uint32_be write_uint64 = write_uint64_be @@ -16,11 +16,11 @@ def write_string(w, s: AnyStr) -> None: else: buf = s write_uint32(w, len(buf)) - write_bytes(w, buf) + write_bytes_unchecked(w, buf) # if len isn't a multiple of 4, add padding bytes reminder = len(buf) % 4 if reminder: - write_bytes(w, bytes([0] * (4 - reminder))) + write_bytes_unchecked(w, bytes([0] * (4 - reminder))) def write_bool(w, val: bool): @@ -33,4 +33,4 @@ def write_bool(w, val: bool): def write_pubkey(w, address: str): # first 4 bytes of an address are the type, there's only one type (0) write_uint32(w, 0) - write_bytes(w, public_key_from_address(address)) + write_bytes_unchecked(w, public_key_from_address(address)) diff --git a/core/src/apps/tezos/helpers.py b/core/src/apps/tezos/helpers.py index 9e63953d4..a2f0fec28 100644 --- a/core/src/apps/tezos/helpers.py +++ b/core/src/apps/tezos/helpers.py @@ -3,7 +3,7 @@ from micropython import const from trezor.crypto import base58 from apps.common import HARDENED -from apps.common.writers import write_uint8 +from apps.common.writers import write_bytes_unchecked, write_uint8 TEZOS_AMOUNT_DECIMALS = const(6) TEZOS_ED25519_ADDRESS_PREFIX = "tz1" @@ -96,3 +96,7 @@ def write_bool(w: bytearray, boolean: bool): write_uint8(w, 255) else: write_uint8(w, 0) + + +def write_instruction(w: bytearray, instruction: str) -> int: + write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction]) diff --git a/core/src/apps/tezos/sign_tx.py b/core/src/apps/tezos/sign_tx.py index fb1e2305a..3fcb06ce4 100644 --- a/core/src/apps/tezos/sign_tx.py +++ b/core/src/apps/tezos/sign_tx.py @@ -7,7 +7,7 @@ from trezor.messages import TezosBallotType, TezosContractType from trezor.messages.TezosSignedTx import TezosSignedTx from apps.common import paths -from apps.common.writers import write_bytes, write_uint8, write_uint32_be +from apps.common.writers import write_bytes_unchecked, write_uint8, write_uint32_be from apps.tezos import CURVE, helpers, layout PROPOSAL_LENGTH = const(32) @@ -157,13 +157,13 @@ def _get_ballot(ballot): def _get_operation_bytes(w: bytearray, msg): - write_bytes(w, msg.branch) + write_bytes_unchecked(w, msg.branch) # when the account sends first operation in lifetime, # we need to reveal its public key if msg.reveal is not None: _encode_common(w, msg.reveal, "reveal") - write_bytes(w, msg.reveal.public_key) + write_bytes_unchecked(w, msg.reveal.public_key) # transaction operation if msg.transaction is not None: @@ -194,7 +194,7 @@ def _get_operation_bytes(w: bytearray, msg): _encode_common(w, msg.origination, "origination") _encode_zarith(w, msg.origination.balance) _encode_data_with_bool_prefix(w, msg.origination.delegate) - write_bytes(w, msg.origination.script) + write_bytes_unchecked(w, msg.origination.script) # delegation operation elif msg.delegation is not None: @@ -214,7 +214,7 @@ def _encode_common(w: bytearray, operation, str_operation): "delegation": 110, } write_uint8(w, operation_tags[str_operation]) - write_bytes(w, operation.source) + write_bytes_unchecked(w, operation.source) _encode_zarith(w, operation.fee) _encode_zarith(w, operation.counter) _encode_zarith(w, operation.gas_limit) @@ -223,13 +223,13 @@ def _encode_common(w: bytearray, operation, str_operation): def _encode_contract_id(w: bytearray, contract_id): write_uint8(w, contract_id.tag) - write_bytes(w, contract_id.hash) + write_bytes_unchecked(w, contract_id.hash) def _encode_data_with_bool_prefix(w: bytearray, data): if data: helpers.write_bool(w, True) - write_bytes(w, data) + write_bytes_unchecked(w, data) else: helpers.write_bool(w, False) @@ -250,20 +250,20 @@ def _encode_proposal(w: bytearray, proposal): proposal_tag = 5 write_uint8(w, proposal_tag) - write_bytes(w, proposal.source) + write_bytes_unchecked(w, proposal.source) write_uint32_be(w, proposal.period) write_uint32_be(w, len(proposal.proposals) * PROPOSAL_LENGTH) for proposal_hash in proposal.proposals: - write_bytes(w, proposal_hash) + write_bytes_unchecked(w, proposal_hash) def _encode_ballot(w: bytearray, ballot): ballot_tag = 6 write_uint8(w, ballot_tag) - write_bytes(w, ballot.source) + write_bytes_unchecked(w, ballot.source) write_uint32_be(w, ballot.period) - write_bytes(w, ballot.proposal) + write_bytes_unchecked(w, ballot.proposal) write_uint8(w, ballot.ballot) @@ -295,16 +295,16 @@ def _encode_manager_common(w: bytearray, sequence_length, operation, to_contract write_uint32_be(w, argument_length) write_uint8(w, helpers.MICHELSON_SEQUENCE_TAG) write_uint32_be(w, sequence_length) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["DROP"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["NIL"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["operation"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES[operation]) + helpers.write_instruction(w, "DROP") + helpers.write_instruction(w, "NIL") + helpers.write_instruction(w, "operation") + helpers.write_instruction(w, operation) if to_contract is True: - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["address"]) + helpers.write_instruction(w, "address") else: - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["key_hash"]) + helpers.write_instruction(w, "key_hash") if operation == "PUSH": - write_bytes(w, bytes([10])) # byte sequence + write_bytes_unchecked(w, bytes([10])) # byte sequence if to_contract is True: write_uint32_be(w, SMART_CONTRACT_ADDRESS_LENGTH) else: @@ -319,14 +319,14 @@ def _encode_manager_to_implicit_transfer(w: bytearray, manager_transfer): sequence_length = MICHELSON_LENGTH + len(value_natural) _encode_manager_common(w, sequence_length, "PUSH") - write_bytes(w, manager_transfer.destination.hash) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["IMPLICIT_ACCOUNT"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["PUSH"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["mutez"]) + write_bytes_unchecked(w, manager_transfer.destination.hash) + helpers.write_instruction(w, "IMPLICIT_ACCOUNT") + helpers.write_instruction(w, "PUSH") + helpers.write_instruction(w, "mutez") _encode_natural(w, manager_transfer.amount) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["UNIT"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["TRANSFER_TOKENS"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["CONS"]) + helpers.write_instruction(w, "UNIT") + helpers.write_instruction(w, "TRANSFER_TOKENS") + helpers.write_instruction(w, "CONS") # smart_contract_delegation @@ -334,17 +334,17 @@ def _encode_manager_delegation(w: bytearray, delegate): MICHELSON_LENGTH = 42 # length is fixed this time(no variable length fields) _encode_manager_common(w, MICHELSON_LENGTH, "PUSH") - write_bytes(w, delegate) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["SOME"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["SET_DELEGATE"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["CONS"]) + write_bytes_unchecked(w, delegate) + helpers.write_instruction(w, "SOME") + helpers.write_instruction(w, "SET_DELEGATE") + helpers.write_instruction(w, "CONS") def _encode_manager_delegation_remove(w: bytearray): MICHELSON_LENGTH = 14 # length is fixed this time(no variable length fields) _encode_manager_common(w, MICHELSON_LENGTH, "NONE") - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["SET_DELEGATE"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["CONS"]) + helpers.write_instruction(w, "SET_DELEGATE") + helpers.write_instruction(w, "CONS") def _encode_manager_to_manager_transfer(w: bytearray, manager_transfer): @@ -356,12 +356,12 @@ def _encode_manager_to_manager_transfer(w: bytearray, manager_transfer): _encode_manager_common(w, sequence_length, "PUSH", to_contract=True) _encode_contract_id(w, manager_transfer.destination) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["CONTRACT"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["unit"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["ASSERT_SOME"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["PUSH"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["mutez"]) + helpers.write_instruction(w, "CONTRACT") + helpers.write_instruction(w, "unit") + helpers.write_instruction(w, "ASSERT_SOME") + helpers.write_instruction(w, "PUSH") + helpers.write_instruction(w, "mutez") _encode_natural(w, manager_transfer.amount) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["UNIT"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["TRANSFER_TOKENS"]) - write_bytes(w, helpers.MICHELSON_INSTRUCTION_BYTES["CONS"]) + helpers.write_instruction(w, "UNIT") + helpers.write_instruction(w, "TRANSFER_TOKENS") + helpers.write_instruction(w, "CONS") diff --git a/core/src/apps/wallet/sign_tx/helpers.py b/core/src/apps/wallet/sign_tx/helpers.py index 8621c2564..12eafb375 100644 --- a/core/src/apps/wallet/sign_tx/helpers.py +++ b/core/src/apps/wallet/sign_tx/helpers.py @@ -1,6 +1,7 @@ import gc -from trezor.messages import InputScriptType +from trezor import utils +from trezor.messages import FailureType, InputScriptType, OutputScriptType from trezor.messages.RequestType import ( TXEXTRADATA, TXFINISHED, @@ -14,10 +15,40 @@ from trezor.messages.TxInputType import TxInputType from trezor.messages.TxOutputBinType import TxOutputBinType from trezor.messages.TxOutputType import TxOutputType from trezor.messages.TxRequest import TxRequest -from trezor.utils import obj_eq + +from .signing import SigningError +from .writers import TX_HASH_SIZE from apps.common.coininfo import CoinInfo +if False: + from typing import Union + +MULTISIG_INPUT_SCRIPT_TYPES = ( + InputScriptType.SPENDMULTISIG, + InputScriptType.SPENDP2SHWITNESS, + InputScriptType.SPENDWITNESS, +) +MULTISIG_OUTPUT_SCRIPT_TYPES = ( + OutputScriptType.PAYTOMULTISIG, + OutputScriptType.PAYTOP2SHWITNESS, + OutputScriptType.PAYTOWITNESS, +) + +CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES = { + OutputScriptType.PAYTOADDRESS: InputScriptType.SPENDADDRESS, + OutputScriptType.PAYTOMULTISIG: InputScriptType.SPENDMULTISIG, + OutputScriptType.PAYTOP2SHWITNESS: InputScriptType.SPENDP2SHWITNESS, + OutputScriptType.PAYTOWITNESS: InputScriptType.SPENDWITNESS, +} +INTERNAL_INPUT_SCRIPT_TYPES = tuple(CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES.values()) +CHANGE_OUTPUT_SCRIPT_TYPES = tuple(CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES.keys()) + +SEGWIT_INPUT_SCRIPT_TYPES = { + InputScriptType.SPENDP2SHWITNESS, + InputScriptType.SPENDWITNESS, +} + # Machine instructions # === @@ -27,7 +58,7 @@ class UiConfirmOutput: self.output = output self.coin = coin - __eq__ = obj_eq + __eq__ = utils.obj_eq class UiConfirmTotal: @@ -36,7 +67,7 @@ class UiConfirmTotal: self.fee = fee self.coin = coin - __eq__ = obj_eq + __eq__ = utils.obj_eq class UiConfirmFeeOverThreshold: @@ -44,21 +75,21 @@ class UiConfirmFeeOverThreshold: self.fee = fee self.coin = coin - __eq__ = obj_eq + __eq__ = utils.obj_eq class UiConfirmForeignAddress: def __init__(self, address_n: list): self.address_n = address_n - __eq__ = obj_eq + __eq__ = utils.obj_eq class UiConfirmNonDefaultLocktime: def __init__(self, lock_time: int): self.lock_time = lock_time - __eq__ = obj_eq + __eq__ = utils.obj_eq def confirm_output(output: TxOutputType, coin: CoinInfo): @@ -81,14 +112,14 @@ def confirm_nondefault_locktime(lock_time: int): return (yield UiConfirmNonDefaultLocktime(lock_time)) -def request_tx_meta(tx_req: TxRequest, tx_hash: bytes = None): +def request_tx_meta(tx_req: TxRequest, coin: CoinInfo, tx_hash: bytes = None): tx_req.request_type = TXMETA tx_req.details.tx_hash = tx_hash tx_req.details.request_index = None ack = yield tx_req tx_req.serialized = None gc.collect() - return sanitize_tx_meta(ack.tx) + return sanitize_tx_meta(ack.tx, coin) def request_tx_extra_data( @@ -107,17 +138,17 @@ def request_tx_extra_data( return ack.tx.extra_data -def request_tx_input(tx_req: TxRequest, i: int, tx_hash: bytes = None): +def request_tx_input(tx_req: TxRequest, i: int, coin: CoinInfo, tx_hash: bytes = None): tx_req.request_type = TXINPUT tx_req.details.request_index = i tx_req.details.tx_hash = tx_hash ack = yield tx_req tx_req.serialized = None gc.collect() - return sanitize_tx_input(ack.tx) + return sanitize_tx_input(ack.tx, coin) -def request_tx_output(tx_req: TxRequest, i: int, tx_hash: bytes = None): +def request_tx_output(tx_req: TxRequest, i: int, coin: CoinInfo, tx_hash: bytes = None): tx_req.request_type = TXOUTPUT tx_req.details.request_index = i tx_req.details.tx_hash = tx_hash @@ -125,9 +156,9 @@ def request_tx_output(tx_req: TxRequest, i: int, tx_hash: bytes = None): tx_req.serialized = None gc.collect() if tx_hash is None: - return sanitize_tx_output(ack.tx) + return sanitize_tx_output(ack.tx, coin) else: - return sanitize_tx_binoutput(ack.tx) + return sanitize_tx_binoutput(ack.tx, coin) def request_tx_finish(tx_req: TxRequest): @@ -142,42 +173,129 @@ def request_tx_finish(tx_req: TxRequest): # === -def sanitize_sign_tx(tx: SignTx) -> SignTx: +def sanitize_sign_tx(tx: SignTx, coin: CoinInfo) -> SignTx: tx.version = tx.version if tx.version is not None else 1 tx.lock_time = tx.lock_time if tx.lock_time is not None else 0 tx.inputs_count = tx.inputs_count if tx.inputs_count is not None else 0 tx.outputs_count = tx.outputs_count if tx.outputs_count is not None else 0 tx.coin_name = tx.coin_name if tx.coin_name is not None else "Bitcoin" - tx.expiry = tx.expiry if tx.expiry is not None else 0 - tx.overwintered = tx.overwintered if tx.overwintered is not None else False - tx.timestamp = tx.timestamp if tx.timestamp is not None else 0 + if coin.decred or coin.overwintered: + tx.expiry = tx.expiry if tx.expiry is not None else 0 + elif tx.expiry: + raise SigningError(FailureType.DataError, "Expiry not enabled on this coin.") + if coin.timestamp and not tx.timestamp: + raise SigningError(FailureType.DataError, "Timestamp must be set.") + elif not coin.timestamp and tx.timestamp: + raise SigningError(FailureType.DataError, "Timestamp not enabled on this coin.") return tx -def sanitize_tx_meta(tx: TransactionType) -> TransactionType: +def sanitize_tx_meta(tx: TransactionType, coin: CoinInfo) -> TransactionType: tx.version = tx.version if tx.version is not None else 1 tx.lock_time = tx.lock_time if tx.lock_time is not None else 0 tx.inputs_cnt = tx.inputs_cnt if tx.inputs_cnt is not None else 0 tx.outputs_cnt = tx.outputs_cnt if tx.outputs_cnt is not None else 0 - tx.extra_data_len = tx.extra_data_len if tx.extra_data_len is not None else 0 - tx.expiry = tx.expiry if tx.expiry is not None else 0 - tx.overwintered = tx.overwintered if tx.overwintered is not None else False - tx.timestamp = tx.timestamp if tx.timestamp is not None else 0 + if coin.extra_data: + tx.extra_data_len = tx.extra_data_len if tx.extra_data_len is not None else 0 + elif tx.extra_data_len: + raise SigningError( + FailureType.DataError, "Extra data not enabled on this coin." + ) + if coin.decred or coin.overwintered: + tx.expiry = tx.expiry if tx.expiry is not None else 0 + elif tx.expiry: + raise SigningError(FailureType.DataError, "Expiry not enabled on this coin.") + if coin.timestamp and not tx.timestamp: + raise SigningError(FailureType.DataError, "Timestamp must be set.") + elif not coin.timestamp and tx.timestamp: + raise SigningError(FailureType.DataError, "Timestamp not enabled on this coin.") return tx -def sanitize_tx_input(tx: TransactionType) -> TxInputType: +def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType: txi = tx.inputs[0] if txi.script_type is None: txi.script_type = InputScriptType.SPENDADDRESS if txi.sequence is None: txi.sequence = 0xFFFFFFFF + if txi.prev_hash is None or len(txi.prev_hash) != TX_HASH_SIZE: + raise SigningError(FailureType.DataError, "Provided prev_hash is invalid.") + if txi.multisig and txi.script_type not in MULTISIG_INPUT_SCRIPT_TYPES: + raise SigningError( + FailureType.DataError, "Multisig field provided but not expected.", + ) + if txi.address_n and txi.script_type not in INTERNAL_INPUT_SCRIPT_TYPES: + raise SigningError( + FailureType.DataError, "Input's address_n provided but not expected.", + ) + if not coin.decred and txi.decred_tree is not None: + raise SigningError( + FailureType.DataError, + "Decred details provided but Decred coin not specified.", + ) + if txi.script_type in SEGWIT_INPUT_SCRIPT_TYPES: + if not coin.segwit: + raise SigningError( + FailureType.DataError, "Segwit not enabled on this coin", + ) + if txi.amount is None: + raise SigningError( + FailureType.DataError, "Segwit input without amount", + ) + + _sanitize_decred(txi, coin) return txi -def sanitize_tx_output(tx: TransactionType) -> TxOutputType: - return tx.outputs[0] +def sanitize_tx_output(tx: TransactionType, coin: CoinInfo) -> TxOutputType: + txo = tx.outputs[0] + if txo.multisig and txo.script_type not in MULTISIG_OUTPUT_SCRIPT_TYPES: + raise SigningError( + FailureType.DataError, "Multisig field provided but not expected.", + ) + if txo.address_n and txo.script_type not in CHANGE_OUTPUT_SCRIPT_TYPES: + raise SigningError( + FailureType.DataError, "Output's address_n provided but not expected.", + ) + if txo.script_type == OutputScriptType.PAYTOOPRETURN: + # op_return output + if txo.amount != 0: + raise SigningError( + FailureType.DataError, "OP_RETURN output with non-zero amount" + ) + if txo.address or txo.address_n or txo.multisig: + raise SigningError( + FailureType.DataError, "OP_RETURN output with address or multisig" + ) + else: + if txo.op_return_data: + raise SigningError( + FailureType.DataError, + "OP RETURN data provided but not OP RETURN script type.", + ) + if txo.address_n and txo.address: + raise SigningError( + FailureType.DataError, "Both address and address_n provided." + ) + if not txo.address_n and not txo.address: + raise SigningError(FailureType.DataError, "Missing address") + + _sanitize_decred(txo, coin) + + return txo -def sanitize_tx_binoutput(tx: TransactionType) -> TxOutputBinType: - return tx.bin_outputs[0] +def sanitize_tx_binoutput(tx: TransactionType, coin: CoinInfo) -> TxOutputBinType: + txo_bin = tx.bin_outputs[0] + _sanitize_decred(txo_bin, coin) + return txo_bin + + +def _sanitize_decred( + tx: Union[TxInputType, TxOutputType, TxOutputBinType], coin: CoinInfo +): + if not coin.decred and tx.decred_script_version is not None: + raise SigningError( + FailureType.DataError, + "Decred details provided but Decred coin not specified.", + ) diff --git a/core/src/apps/wallet/sign_tx/multisig.py b/core/src/apps/wallet/sign_tx/multisig.py index aa474e786..5cbf62f2e 100644 --- a/core/src/apps/wallet/sign_tx/multisig.py +++ b/core/src/apps/wallet/sign_tx/multisig.py @@ -5,7 +5,7 @@ from trezor.messages.HDNodeType import HDNodeType from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from trezor.utils import HashWriter, ensure -from apps.wallet.sign_tx.writers import write_bytes, write_uint32 +from apps.wallet.sign_tx.writers import write_bytes_fixed, write_uint32 class MultisigError(ValueError): @@ -59,8 +59,8 @@ def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes: write_uint32(h, d.depth) write_uint32(h, d.fingerprint) write_uint32(h, d.child_num) - write_bytes(h, d.chain_code) - write_bytes(h, d.public_key) + write_bytes_fixed(h, d.chain_code, 32) + write_bytes_fixed(h, d.public_key, 33) return h.get_digest() diff --git a/core/src/apps/wallet/sign_tx/scripts.py b/core/src/apps/wallet/sign_tx/scripts.py index fcf3cedf9..b1495c785 100644 --- a/core/src/apps/wallet/sign_tx/scripts.py +++ b/core/src/apps/wallet/sign_tx/scripts.py @@ -5,9 +5,9 @@ from apps.common.coininfo import CoinInfo from apps.common.writers import empty_bytearray from apps.wallet.sign_tx.multisig import multisig_get_pubkey_count, multisig_get_pubkeys from apps.wallet.sign_tx.writers import ( - write_bytes, + write_bytes_fixed, + write_bytes_unchecked, write_op_push, - write_scriptnum, write_varint, ) @@ -53,20 +53,6 @@ def output_script_p2sh(scripthash: bytes) -> bytearray: return s -def script_replay_protection_bip115( - block_hash: bytes, block_height: bytes -) -> bytearray: - if block_hash is None or block_height is None: - return bytearray() - utils.ensure(len(block_hash) == 32) - s = bytearray(33) - s[0] = 0x20 # 32 bytes for block hash - s[1:33] = block_hash # block hash - write_scriptnum(s, block_height) - s.append(0xB4) # OP_CHECKBLOCKATHEIGHT - return s - - # SegWit: Native P2WPKH or P2WSH # === # https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh @@ -88,12 +74,13 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray: # Either: # 00 14 <20-byte-key-hash> # 00 20 <32-byte-script-hash> - utils.ensure(len(witprog) == 20 or len(witprog) == 32) + length = len(witprog) + utils.ensure(length == 20 or length == 32) - w = empty_bytearray(3 + len(witprog)) + w = empty_bytearray(3 + length) w.append(0x00) # witness version byte - w.append(len(witprog)) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes - write_bytes(w, witprog) # pub key hash + w.append(length) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes + write_bytes_fixed(w, witprog, length) # pub key hash return w @@ -114,7 +101,7 @@ def input_script_p2wpkh_in_p2sh(pubkeyhash: bytes) -> bytearray: w.append(0x16) # length of the data w.append(0x00) # witness version byte w.append(0x14) # P2WPKH witness program (pub key hash length) - write_bytes(w, pubkeyhash) # pub key hash + write_bytes_fixed(w, pubkeyhash, 20) # pub key hash return w @@ -137,7 +124,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray: w.append(0x22) # length of the data w.append(0x00) # witness version byte w.append(0x20) # P2WSH witness program (redeem script hash length) - write_bytes(w, script_hash) + write_bytes_fixed(w, script_hash, 32) return w @@ -291,12 +278,12 @@ def output_script_paytoopreturn(data: bytes) -> bytearray: def append_signature(w: bytearray, signature: bytes, sighash: int) -> bytearray: write_op_push(w, len(signature) + 1) - write_bytes(w, signature) + write_bytes_unchecked(w, signature) w.append(sighash) return w def append_pubkey(w: bytearray, pubkey: bytes) -> bytearray: write_op_push(w, len(pubkey)) - write_bytes(w, pubkey) + write_bytes_unchecked(w, pubkey) return w diff --git a/core/src/apps/wallet/sign_tx/segwit_bip143.py b/core/src/apps/wallet/sign_tx/segwit_bip143.py index e25a8ff33..40c26db7f 100644 --- a/core/src/apps/wallet/sign_tx/segwit_bip143.py +++ b/core/src/apps/wallet/sign_tx/segwit_bip143.py @@ -9,13 +9,14 @@ from apps.common.coininfo import CoinInfo from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh from apps.wallet.sign_tx.writers import ( + TX_HASH_SIZE, get_tx_hash, - write_bytes, + write_bytes_fixed, + write_bytes_prefixed, write_bytes_reversed, write_tx_output, write_uint32, write_uint64, - write_varint, ) @@ -30,7 +31,7 @@ class Bip143: self.h_outputs = HashWriter(sha256()) def add_prevouts(self, txi: TxInputType): - write_bytes_reversed(self.h_prevouts, txi.prev_hash) + write_bytes_reversed(self.h_prevouts, txi.prev_hash, TX_HASH_SIZE) write_uint32(self.h_prevouts, txi.prev_index) def add_sequence(self, txi: TxInputType): @@ -58,22 +59,24 @@ class Bip143: ) -> bytes: h_preimage = HashWriter(sha256()) - ensure(not tx.overwintered) + ensure(not coin.overwintered) write_uint32(h_preimage, tx.version) # nVersion - write_bytes(h_preimage, self.get_prevouts_hash(coin)) # hashPrevouts - write_bytes(h_preimage, self.get_sequence_hash(coin)) # hashSequence + # hashPrevouts + write_bytes_fixed(h_preimage, self.get_prevouts_hash(coin), TX_HASH_SIZE) + # hashSequence + write_bytes_fixed(h_preimage, self.get_sequence_hash(coin), TX_HASH_SIZE) - write_bytes_reversed(h_preimage, txi.prev_hash) # outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # outpoint write_uint32(h_preimage, txi.prev_index) # outpoint script_code = self.derive_script_code(txi, pubkeyhash) # scriptCode - write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # amount write_uint32(h_preimage, txi.sequence) # nSequence - write_bytes(h_preimage, self.get_outputs_hash(coin)) # hashOutputs + # hashOutputs + write_bytes_fixed(h_preimage, self.get_outputs_hash(coin), TX_HASH_SIZE) write_uint32(h_preimage, tx.lock_time) # nLockTime write_uint32(h_preimage, sighash) # nHashType diff --git a/core/src/apps/wallet/sign_tx/signing.py b/core/src/apps/wallet/sign_tx/signing.py index 55cfbbe9a..33232b981 100644 --- a/core/src/apps/wallet/sign_tx/signing.py +++ b/core/src/apps/wallet/sign_tx/signing.py @@ -55,9 +55,7 @@ class SigningError(ValueError): # - check inputs, previous transactions, and outputs # - ask for confirmations # - check fee -async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): - coin = coins.by_name(tx.coin_name) - +async def check_tx_fee(tx: SignTx, keychain: seed.Keychain, coin: coininfo.CoinInfo): # h_first is used to make sure the inputs and outputs streamed in Phase 1 # are the same as in Phase 2. it is thus not required to fully hash the # tx, as the SignTx info is streamed only once @@ -66,7 +64,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): if not utils.BITCOIN_ONLY and coin.decred: hash143 = decred.DecredPrefixHasher(tx) # pseudo BIP-0143 prefix hashing tx_ser = TxRequestSerializedType() - elif not utils.BITCOIN_ONLY and tx.overwintered: + elif not utils.BITCOIN_ONLY and coin.overwintered: if tx.version == 3: branch_id = tx.branch_id or 0x5BA81B19 # Overwinter hash143 = zcash.Zip143(branch_id) # ZIP-0143 transaction hashing @@ -81,11 +79,11 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): else: hash143 = segwit_bip143.Bip143() # BIP-0143 transaction hashing - multifp = multisig.MultisigFingerprint() # control checksum of multisig inputs + multisig_fp = multisig.MultisigFingerprint() # control checksum of multisig inputs weight = tx_weight.TxWeightCalculator(tx.inputs_count, tx.outputs_count) total_in = 0 # sum of input amounts - segwit_in = 0 # sum of segwit input amounts + bip143_in = 0 # sum of segwit input amounts total_out = 0 # sum of output amounts change_out = 0 # change output amount wallet_path = [] # common prefix of input paths @@ -99,7 +97,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): for i in range(tx.inputs_count): progress.advance() # STAGE_REQUEST_1_INPUT - txi = await helpers.request_tx_input(tx_req, i) + txi = await helpers.request_tx_input(tx_req, i, coin) wallet_path = input_extract_wallet_path(txi, wallet_path) writers.write_tx_input_check(h_first, txi) weight.add_input(txi) @@ -110,7 +108,9 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): await helpers.confirm_foreign_address(txi.address_n) if txi.multisig: - multifp.add(txi.multisig) + multisig_fp.add(txi.multisig) + else: + multisig_fp.mismatch = True if txi.script_type in ( InputScriptType.SPENDWITNESS, @@ -123,20 +123,20 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): if not txi.amount: raise SigningError(FailureType.DataError, "Segwit input without amount") segwit[i] = True - segwit_in += txi.amount + bip143_in += txi.amount total_in += txi.amount elif txi.script_type in ( InputScriptType.SPENDADDRESS, InputScriptType.SPENDMULTISIG, ): - if coin.force_bip143 or (not utils.BITCOIN_ONLY and tx.overwintered): + if not utils.BITCOIN_ONLY and (coin.force_bip143 or coin.overwintered): if not txi.amount: raise SigningError( FailureType.DataError, "Expected input with amount" ) segwit[i] = False - segwit_in += txi.amount + bip143_in += txi.amount total_in += txi.amount else: segwit[i] = False @@ -150,7 +150,8 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): if not utils.BITCOIN_ONLY and coin.decred: w_txi = writers.empty_bytearray(8 if i == 0 else 0 + 9 + len(txi.prev_hash)) if i == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi, get_tx_header(coin, tx)) + # decred doesn't support segwit + write_tx_header(w_txi, coin, tx, False) writers.write_tx_input_decred(w_txi, txi) tx_ser.serialized_tx = w_txi tx_req.serialized = tx_ser @@ -160,12 +161,12 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): for o in range(tx.outputs_count): # STAGE_REQUEST_3_OUTPUT - txo = await helpers.request_tx_output(tx_req, o) + txo = await helpers.request_tx_output(tx_req, o, coin) txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, keychain) weight.add_output(txo_bin.script_pubkey) - if change_out == 0 and output_is_change(txo, wallet_path, segwit_in, multifp): + if change_out == 0 and output_is_change(txo, wallet_path, multisig_fp): # output is change and does not need confirmation change_out = txo.amount elif not await helpers.confirm_output(txo, coin): @@ -195,7 +196,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): fee = total_in - total_out - if coin.negative_fee: + if not utils.BITCOIN_ONLY and coin.negative_fee: pass # bypass check for negative fee coins, required for reward TX else: if fee < 0: @@ -216,25 +217,32 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain): if not utils.BITCOIN_ONLY and coin.decred: hash143.add_locktime_expiry(tx) - return h_first, hash143, segwit, total_in, wallet_path + return h_first, hash143, segwit, bip143_in, wallet_path, multisig_fp async def sign_tx(tx: SignTx, keychain: seed.Keychain): - tx = helpers.sanitize_sign_tx(tx) + coin_name = tx.coin_name if tx.coin_name is not None else "Bitcoin" + coin = coins.by_name(coin_name) + tx = helpers.sanitize_sign_tx(tx, coin) progress.init(tx.inputs_count, tx.outputs_count) # Phase 1 - h_first, hash143, segwit, authorized_in, wallet_path = await check_tx_fee( - tx, keychain - ) + ( + h_first, + hash143, + segwit, + authorized_bip143_in, + wallet_path, + multisig_fp, + ) = await check_tx_fee(tx, keychain, coin) # Phase 2 # - sign inputs # - check that nothing changed - coin = coins.by_name(tx.coin_name) + any_segwit = True in segwit.values() tx_ser = TxRequestSerializedType() txo_bin = TxOutputBinType() @@ -253,13 +261,15 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): if segwit[i_sign]: # STAGE_REQUEST_SEGWIT_INPUT - txi_sign = await helpers.request_tx_input(tx_req, i_sign) + txi_sign = await helpers.request_tx_input(tx_req, i_sign, coin) if not input_is_segwit(txi_sign): raise SigningError( FailureType.ProcessError, "Transaction has changed during signing" ) input_check_wallet_path(txi_sign, wallet_path) + # NOTE: No need to check the multisig fingerprint, because we won't be signing + # the script here. Signatures are produced in STAGE_REQUEST_SEGWIT_WITNESS. key_sign = keychain.derive(txi_sign.address_n, coin.curve_name) key_sign_pub = key_sign.public_key() @@ -269,27 +279,28 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 7 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi, get_tx_header(coin, tx, True)) + write_tx_header(w_txi, coin, tx, True) writers.write_tx_input(w_txi, txi_sign) tx_ser.serialized_tx = w_txi tx_ser.signature_index = None tx_ser.signature = None tx_req.serialized = tx_ser - elif coin.force_bip143 or (not utils.BITCOIN_ONLY and tx.overwintered): + elif not utils.BITCOIN_ONLY and (coin.force_bip143 or coin.overwintered): # STAGE_REQUEST_SEGWIT_INPUT - txi_sign = await helpers.request_tx_input(tx_req, i_sign) + txi_sign = await helpers.request_tx_input(tx_req, i_sign, coin) input_check_wallet_path(txi_sign, wallet_path) + input_check_multisig_fingerprint(txi_sign, multisig_fp) is_bip143 = ( txi_sign.script_type == InputScriptType.SPENDADDRESS or txi_sign.script_type == InputScriptType.SPENDMULTISIG ) - if not is_bip143 or txi_sign.amount > authorized_in: + if not is_bip143 or txi_sign.amount > authorized_bip143_in: raise SigningError( FailureType.ProcessError, "Transaction has changed during signing" ) - authorized_in -= txi_sign.amount + authorized_bip143_in -= txi_sign.amount key_sign = keychain.derive(txi_sign.address_n, coin.curve_name) key_sign_pub = key_sign.public_key() @@ -318,16 +329,17 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 5 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi_sign, get_tx_header(coin, tx)) + write_tx_header(w_txi_sign, coin, tx, any_segwit) writers.write_tx_input(w_txi_sign, txi_sign) tx_ser.serialized_tx = w_txi_sign tx_req.serialized = tx_ser elif not utils.BITCOIN_ONLY and coin.decred: - txi_sign = await helpers.request_tx_input(tx_req, i_sign) + txi_sign = await helpers.request_tx_input(tx_req, i_sign, coin) input_check_wallet_path(txi_sign, wallet_path) + input_check_multisig_fingerprint(txi_sign, multisig_fp) key_sign = keychain.derive(txi_sign.address_n, coin.curve_name) key_sign_pub = key_sign.public_key() @@ -352,8 +364,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): for ii in range(tx.inputs_count): if ii == i_sign: - writers.write_varint(h_witness, len(prev_pkscript)) - writers.write_bytes(h_witness, prev_pkscript) + writers.write_bytes_prefixed(h_witness, prev_pkscript) else: writers.write_varint(h_witness, 0) @@ -363,8 +374,8 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): h_sign = utils.HashWriter(blake256()) writers.write_uint32(h_sign, decred.DECRED_SIGHASHALL) - writers.write_bytes(h_sign, prefix_hash) - writers.write_bytes(h_sign, witness_hash) + writers.write_bytes_fixed(h_sign, prefix_hash, writers.TX_HASH_SIZE) + writers.write_bytes_fixed(h_sign, witness_hash, writers.TX_HASH_SIZE) sig_hash = writers.get_tx_hash(h_sign, double=coin.sign_hash_double) signature = ecdsa_sign(key_sign, sig_hash) @@ -383,7 +394,9 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): ) if i_sign == 0: - writers.write_bytes(w_txi_sign, hash143.get_last_output_bytes()) + writers.write_bytes_unchecked( + w_txi_sign, hash143.get_last_output_bytes() + ) writers.write_uint32(w_txi_sign, tx.lock_time) writers.write_uint32(w_txi_sign, tx.expiry) writers.write_varint(w_txi_sign, tx.inputs_count) @@ -398,25 +411,20 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): # same as h_first, checked before signing the digest h_second = utils.HashWriter(sha256()) - if not utils.BITCOIN_ONLY and tx.overwintered: - writers.write_uint32( - h_sign, tx.version | zcash.OVERWINTERED - ) # nVersion | fOverwintered - writers.write_uint32(h_sign, tx.version_group_id) # nVersionGroupId - else: - writers.write_uint32(h_sign, tx.version) # nVersion - if tx.timestamp: - writers.write_uint32(h_sign, tx.timestamp) + writers.write_uint32(h_sign, tx.version) # nVersion + if not utils.BITCOIN_ONLY and coin.timestamp: + writers.write_uint32(h_sign, tx.timestamp) writers.write_varint(h_sign, tx.inputs_count) for i in range(tx.inputs_count): # STAGE_REQUEST_4_INPUT - txi = await helpers.request_tx_input(tx_req, i) + txi = await helpers.request_tx_input(tx_req, i, coin) input_check_wallet_path(txi, wallet_path) writers.write_tx_input_check(h_second, txi) if i == i_sign: txi_sign = txi + input_check_multisig_fingerprint(txi_sign, multisig_fp) key_sign = keychain.derive(txi.address_n, coin.curve_name) key_sign_pub = key_sign.public_key() # for the signing process the script_sig is equal @@ -430,11 +438,6 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): txi_sign.script_sig = scripts.output_script_p2pkh( addresses.ecdsa_hash_pubkey(key_sign_pub, coin) ) - if coin.bip115: - txi_sign.script_sig += scripts.script_replay_protection_bip115( - txi_sign.prev_block_hash_bip115, - txi_sign.prev_block_height_bip115, - ) else: raise SigningError( FailureType.ProcessError, "Unknown transaction type" @@ -447,17 +450,13 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): for o in range(tx.outputs_count): # STAGE_REQUEST_4_OUTPUT - txo = await helpers.request_tx_output(tx_req, o) + txo = await helpers.request_tx_output(tx_req, o, coin) txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, keychain) writers.write_tx_output(h_second, txo_bin) writers.write_tx_output(h_sign, txo_bin) writers.write_uint32(h_sign, tx.lock_time) - if not utils.BITCOIN_ONLY and tx.overwintered: - writers.write_uint32(h_sign, tx.expiry) # expiryHeight - writers.write_varint(h_sign, 0) # nJoinSplit - writers.write_uint32(h_sign, get_hash_type(coin)) # check the control digests @@ -486,7 +485,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 5 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi_sign, get_tx_header(coin, tx)) + write_tx_header(w_txi_sign, coin, tx, any_segwit) writers.write_tx_input(w_txi_sign, txi_sign) tx_ser.serialized_tx = w_txi_sign @@ -498,7 +497,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): for o in range(tx.outputs_count): progress.advance() # STAGE_REQUEST_5_OUTPUT - txo = await helpers.request_tx_output(tx_req, o) + txo = await helpers.request_tx_output(tx_req, o, coin) txo_bin.amount = txo.amount txo_bin.script_pubkey = output_derive_script(txo, coin, keychain) @@ -514,20 +513,19 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): tx_req.serialized = tx_ser - any_segwit = True in segwit.values() - for i in range(tx.inputs_count): progress.advance() if segwit[i]: # STAGE_REQUEST_SEGWIT_WITNESS - txi = await helpers.request_tx_input(tx_req, i) + txi = await helpers.request_tx_input(tx_req, i, coin) input_check_wallet_path(txi, wallet_path) + input_check_multisig_fingerprint(txi, multisig_fp) - if not input_is_segwit(txi) or txi.amount > authorized_in: + if not input_is_segwit(txi) or txi.amount > authorized_bip143_in: raise SigningError( FailureType.ProcessError, "Transaction has changed during signing" ) - authorized_in -= txi.amount + authorized_bip143_in -= txi.amount key_sign = keychain.derive(txi.address_n, coin.curve_name) key_sign_pub = key_sign.public_key() @@ -565,7 +563,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): writers.write_uint32(tx_ser.serialized_tx, tx.lock_time) - if not utils.BITCOIN_ONLY and tx.overwintered: + if not utils.BITCOIN_ONLY and coin.overwintered: if tx.version == 3: writers.write_uint32(tx_ser.serialized_tx, tx.expiry) # expiryHeight writers.write_varint(tx_ser.serialized_tx, 0) # nJoinSplit @@ -590,14 +588,19 @@ async def get_prevtx_output_value( total_out = 0 # sum of output amounts # STAGE_REQUEST_2_PREV_META - tx = await helpers.request_tx_meta(tx_req, prev_hash) + tx = await helpers.request_tx_meta(tx_req, coin, prev_hash) + + if tx.outputs_cnt <= prev_index: + raise SigningError( + FailureType.ProcessError, "Not enough outputs in previous transaction." + ) if not utils.BITCOIN_ONLY and coin.decred: txh = utils.HashWriter(blake256()) else: txh = utils.HashWriter(sha256()) - if not utils.BITCOIN_ONLY and tx.overwintered: + if not utils.BITCOIN_ONLY and coin.overwintered: writers.write_uint32( txh, tx.version | zcash.OVERWINTERED ) # nVersion | fOverwintered @@ -606,14 +609,14 @@ async def get_prevtx_output_value( writers.write_uint32(txh, tx.version | decred.DECRED_SERIALIZE_NO_WITNESS) else: writers.write_uint32(txh, tx.version) # nVersion - if tx.timestamp: + if not utils.BITCOIN_ONLY and coin.timestamp: writers.write_uint32(txh, tx.timestamp) writers.write_varint(txh, tx.inputs_cnt) for i in range(tx.inputs_cnt): # STAGE_REQUEST_2_PREV_INPUT - txi = await helpers.request_tx_input(tx_req, i, prev_hash) + txi = await helpers.request_tx_input(tx_req, i, coin, prev_hash) if not utils.BITCOIN_ONLY and coin.decred: writers.write_tx_input_decred(txh, txi) else: @@ -623,7 +626,7 @@ async def get_prevtx_output_value( for o in range(tx.outputs_cnt): # STAGE_REQUEST_2_PREV_OUTPUT - txo_bin = await helpers.request_tx_output(tx_req, o, prev_hash) + txo_bin = await helpers.request_tx_output(tx_req, o, coin, prev_hash) writers.write_tx_output(txh, txo_bin) if o == prev_index: total_out += txo_bin.amount @@ -640,15 +643,16 @@ async def get_prevtx_output_value( writers.write_uint32(txh, tx.lock_time) - if not utils.BITCOIN_ONLY and (tx.overwintered or coin.decred): + if not utils.BITCOIN_ONLY and (coin.overwintered or coin.decred): writers.write_uint32(txh, tx.expiry) - ofs = 0 - while ofs < tx.extra_data_len: - size = min(1024, tx.extra_data_len - ofs) - data = await helpers.request_tx_extra_data(tx_req, ofs, size, prev_hash) - writers.write_bytes(txh, data) - ofs += len(data) + if not utils.BITCOIN_ONLY and coin.extra_data: + ofs = 0 + while ofs < tx.extra_data_len: + size = min(1024, tx.extra_data_len - ofs) + data = await helpers.request_tx_extra_data(tx_req, ofs, size, prev_hash) + writers.write_bytes_unchecked(txh, data) + ofs += len(data) if ( writers.get_tx_hash(txh, double=coin.sign_hash_double, reverse=True) @@ -672,22 +676,21 @@ def get_hash_type(coin: coininfo.CoinInfo) -> int: return hashtype -def get_tx_header(coin: coininfo.CoinInfo, tx: SignTx, segwit: bool = False): - w_txi = bytearray() - if not utils.BITCOIN_ONLY and tx.overwintered: - writers.write_uint32( - w_txi, tx.version | zcash.OVERWINTERED - ) # nVersion | fOverwintered - writers.write_uint32(w_txi, tx.version_group_id) # nVersionGroupId +def write_tx_header( + w: writers.Writer, coin: coininfo.CoinInfo, tx: SignTx, segwit: bool +) -> None: + if not utils.BITCOIN_ONLY and coin.overwintered: + # nVersion | fOverwintered + writers.write_uint32(w, tx.version | zcash.OVERWINTERED) + writers.write_uint32(w, tx.version_group_id) # nVersionGroupId else: - writers.write_uint32(w_txi, tx.version) # nVersion - if tx.timestamp: - writers.write_uint32(w_txi, tx.timestamp) + writers.write_uint32(w, tx.version) # nVersion + if not utils.BITCOIN_ONLY and coin.timestamp: + writers.write_uint32(w, tx.timestamp) if segwit: - writers.write_varint(w_txi, 0x00) # segwit witness marker - writers.write_varint(w_txi, 0x01) # segwit witness flag - writers.write_varint(w_txi, tx.inputs_count) - return w_txi + writers.write_varint(w, 0x00) # segwit witness marker + writers.write_varint(w, 0x01) # segwit witness flag + writers.write_varint(w, tx.inputs_count) # TX Outputs @@ -699,29 +702,21 @@ def output_derive_script( ) -> bytes: if o.script_type == OutputScriptType.PAYTOOPRETURN: - # op_return output - if o.amount != 0: - raise SigningError( - FailureType.DataError, "OP_RETURN output with non-zero amount" - ) return scripts.output_script_paytoopreturn(o.op_return_data) if o.address_n: # change output - if o.address: - raise SigningError(FailureType.DataError, "Address in change output") o.address = get_address_for_change(o, coin, keychain) - else: - if not o.address: - raise SigningError(FailureType.DataError, "Missing address") if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix): # p2wpkh or p2wsh witprog = addresses.decode_bech32_address(coin.bech32_prefix, o.address) return scripts.output_script_native_p2wpkh_or_p2wsh(witprog) - if coin.cashaddr_prefix is not None and o.address.startswith( - coin.cashaddr_prefix + ":" + if ( + not utils.BITCOIN_ONLY + and coin.cashaddr_prefix is not None + and o.address.startswith(coin.cashaddr_prefix + ":") ): prefix, addr = o.address.split(":") version, data = cashaddr.decode(prefix, addr) @@ -742,20 +737,12 @@ def output_derive_script( # p2pkh pubkeyhash = address_type.strip(coin.address_type, raw_address) script = scripts.output_script_p2pkh(pubkeyhash) - if coin.bip115: - script += scripts.script_replay_protection_bip115( - o.block_hash_bip115, o.block_height_bip115 - ) return script elif address_type.check(coin.address_type_p2sh, raw_address): # p2sh scripthash = address_type.strip(coin.address_type_p2sh, raw_address) script = scripts.output_script_p2sh(scripthash) - if coin.bip115: - script += scripts.script_replay_protection_bip115( - o.block_hash_bip115, o.block_height_bip115 - ) return script raise SigningError(FailureType.DataError, "Invalid address type") @@ -764,32 +751,20 @@ def output_derive_script( def get_address_for_change( o: TxOutputType, coin: coininfo.CoinInfo, keychain: seed.Keychain ): - if o.script_type == OutputScriptType.PAYTOADDRESS: - input_script_type = InputScriptType.SPENDADDRESS - elif o.script_type == OutputScriptType.PAYTOMULTISIG: - input_script_type = InputScriptType.SPENDMULTISIG - elif o.script_type == OutputScriptType.PAYTOWITNESS: - input_script_type = InputScriptType.SPENDWITNESS - elif o.script_type == OutputScriptType.PAYTOP2SHWITNESS: - input_script_type = InputScriptType.SPENDP2SHWITNESS - else: + try: + input_script_type = helpers.CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES[o.script_type] + except KeyError: raise SigningError(FailureType.DataError, "Invalid script type") node = keychain.derive(o.address_n, coin.curve_name) return addresses.get_address(input_script_type, coin, node, o.multisig) def output_is_change( - o: TxOutputType, - wallet_path: list, - segwit_in: int, - multifp: multisig.MultisigFingerprint, + o: TxOutputType, wallet_path: list, multisig_fp: multisig.MultisigFingerprint, ) -> bool: - if o.multisig and not multifp.matches(o.multisig): + if o.script_type not in helpers.CHANGE_OUTPUT_SCRIPT_TYPES: return False - if output_is_segwit(o) and o.amount > segwit_in: - # if the output is segwit, make sure it doesn't spend more than what the - # segwit inputs paid. this is to prevent user being tricked into - # creating ANYONECANSPEND outputs before full segwit activation. + if o.multisig and not multisig_fp.matches(o.multisig): return False return ( wallet_path is not None @@ -799,13 +774,6 @@ def output_is_change( ) -def output_is_segwit(o: TxOutputType) -> bool: - return ( - o.script_type == OutputScriptType.PAYTOWITNESS - or o.script_type == OutputScriptType.PAYTOP2SHWITNESS - ) - - # Tx Inputs # === @@ -880,6 +848,18 @@ def input_check_wallet_path(txi: TxInputType, wallet_path: list) -> list: ) +def input_check_multisig_fingerprint( + txi: TxInputType, multisig_fp: multisig.MultisigFingerprint +) -> None: + if multisig_fp.mismatch is False: + # All inputs in Phase 1 had matching multisig fingerprints, allowing a multisig change-output. + if not txi.multisig or not multisig_fp.matches(txi.multisig): + # This input no longer has a matching multisig fingerprint. + raise SigningError( + FailureType.ProcessError, "Transaction has changed during signing" + ) + + def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes: sig = secp256k1.sign(node.private_key(), digest) sigder = der.encode_seq((sig[1:33], sig[33:65])) diff --git a/core/src/apps/wallet/sign_tx/writers.py b/core/src/apps/wallet/sign_tx/writers.py index e8214cd6b..5482457cf 100644 --- a/core/src/apps/wallet/sign_tx/writers.py +++ b/core/src/apps/wallet/sign_tx/writers.py @@ -1,3 +1,5 @@ +from micropython import const + from trezor.crypto.hashlib import sha256 from trezor.messages.TxInputType import TxInputType from trezor.messages.TxOutputBinType import TxOutputBinType @@ -5,29 +7,39 @@ from trezor.utils import ensure from apps.common.writers import ( # noqa: F401 empty_bytearray, - write_bytes, + write_bytes_fixed, write_bytes_reversed, + write_bytes_unchecked, write_uint8, write_uint16_le, write_uint32_le, write_uint64_le, ) +if False: + from apps.common.writers import Writer + write_uint16 = write_uint16_le write_uint32 = write_uint32_le write_uint64 = write_uint64_le +TX_HASH_SIZE = const(32) + + +def write_bytes_prefixed(w: Writer, b: bytes) -> None: + write_varint(w, len(b)) + write_bytes_unchecked(w, b) + def write_tx_input(w, i: TxInputType): - write_bytes_reversed(w, i.prev_hash) + write_bytes_reversed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) - write_varint(w, len(i.script_sig)) - write_bytes(w, i.script_sig) + write_bytes_prefixed(w, i.script_sig) write_uint32(w, i.sequence) def write_tx_input_check(w, i: TxInputType): - write_bytes(w, i.prev_hash) + write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) write_uint32(w, i.script_type) write_uint32(w, len(i.address_n)) @@ -38,7 +50,7 @@ def write_tx_input_check(w, i: TxInputType): def write_tx_input_decred(w, i: TxInputType): - write_bytes_reversed(w, i.prev_hash) + write_bytes_reversed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index or 0) write_uint8(w, i.decred_tree or 0) write_uint32(w, i.sequence) @@ -48,16 +60,14 @@ def write_tx_input_decred_witness(w, i: TxInputType): write_uint64(w, i.amount or 0) write_uint32(w, 0) # block height fraud proof write_uint32(w, 0xFFFFFFFF) # block index fraud proof - write_varint(w, len(i.script_sig)) - write_bytes(w, i.script_sig) + write_bytes_prefixed(w, i.script_sig) def write_tx_output(w, o: TxOutputBinType): write_uint64(w, o.amount) if o.decred_script_version is not None: write_uint16(w, o.decred_script_version) - write_varint(w, len(o.script_pubkey)) - write_bytes(w, o.script_pubkey) + write_bytes_prefixed(w, o.script_pubkey) def write_op_push(w, n: int): @@ -95,28 +105,6 @@ def write_varint(w, n: int): w.append((n >> 24) & 0xFF) -def write_scriptnum(w, n: int): - ensure(n >= 0 and n <= 0xFFFFFFFF) - if n < 0x100: - w.append(1) - w.append(n & 0xFF) - elif n < 0x10000: - w.append(2) - w.append(n & 0xFF) - w.append((n >> 8) & 0xFF) - elif n < 0x1000000: - w.append(3) - w.append(n & 0xFF) - w.append((n >> 8) & 0xFF) - w.append((n >> 16) & 0xFF) - else: - w.append(4) - w.append(n & 0xFF) - w.append((n >> 8) & 0xFF) - w.append((n >> 16) & 0xFF) - w.append((n >> 24) & 0xFF) - - def get_tx_hash(w, double: bool = False, reverse: bool = False) -> bytes: d = w.get_digest() if double: diff --git a/core/src/apps/wallet/sign_tx/zcash.py b/core/src/apps/wallet/sign_tx/zcash.py index a192922a2..4f5c8e6ff 100644 --- a/core/src/apps/wallet/sign_tx/zcash.py +++ b/core/src/apps/wallet/sign_tx/zcash.py @@ -12,13 +12,14 @@ from apps.common.coininfo import CoinInfo from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh from apps.wallet.sign_tx.writers import ( + TX_HASH_SIZE, get_tx_hash, - write_bytes, + write_bytes_fixed, + write_bytes_prefixed, write_bytes_reversed, write_tx_output, write_uint32, write_uint64, - write_varint, ) OVERWINTERED = const(0x80000000) @@ -53,7 +54,7 @@ class Zip143: self.h_outputs = HashWriter(blake2b(outlen=32, personal=b"ZcashOutputsHash")) def add_prevouts(self, txi: TxInputType): - write_bytes_reversed(self.h_prevouts, txi.prev_hash) + write_bytes_reversed(self.h_prevouts, txi.prev_hash, TX_HASH_SIZE) write_uint32(self.h_prevouts, txi.prev_index) def add_sequence(self, txi: TxInputType): @@ -85,27 +86,30 @@ class Zip143: ) ) - ensure(tx.overwintered) + ensure(coin.overwintered) ensure(tx.version == 3) write_uint32( h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - write_bytes(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts - write_bytes(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence - write_bytes(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs - write_bytes(h_preimage, b"\x00" * 32) # 6. hashJoinSplits + # 3. hashPrevouts + write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE) + # 4. hashSequence + write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE) + # 5. hashOutputs + write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE) + # 6. hashJoinSplits + write_bytes_fixed(h_preimage, b"\x00" * TX_HASH_SIZE, TX_HASH_SIZE) write_uint32(h_preimage, tx.lock_time) # 7. nLockTime write_uint32(h_preimage, tx.expiry) # 8. expiryHeight write_uint32(h_preimage, sighash) # 9. nHashType - write_bytes_reversed(h_preimage, txi.prev_hash) # 10a. outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # 10a. outpoint write_uint32(h_preimage, txi.prev_index) script_code = derive_script_code(txi, pubkeyhash) # 10b. scriptCode - write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 10c. value @@ -132,30 +136,35 @@ class Zip243(Zip143): ) ) - ensure(tx.overwintered) + ensure(coin.overwintered) ensure(tx.version == 4) write_uint32( h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - write_bytes(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts - write_bytes(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence - write_bytes(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs - write_bytes(h_preimage, b"\x00" * 32) # 6. hashJoinSplits - write_bytes(h_preimage, b"\x00" * 32) # 7. hashShieldedSpends - write_bytes(h_preimage, b"\x00" * 32) # 8. hashShieldedOutputs + # 3. hashPrevouts + write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE) + # 4. hashSequence + write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE) + # 5. hashOutputs + write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE) + + zero_hash = b"\x00" * TX_HASH_SIZE + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 6. hashJoinSplits + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 7. hashShieldedSpends + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 8. hashShieldedOutputs + write_uint32(h_preimage, tx.lock_time) # 9. nLockTime write_uint32(h_preimage, tx.expiry) # 10. expiryHeight write_uint64(h_preimage, 0) # 11. valueBalance write_uint32(h_preimage, sighash) # 12. nHashType - write_bytes_reversed(h_preimage, txi.prev_hash) # 13a. outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # 13a. outpoint write_uint32(h_preimage, txi.prev_index) script_code = derive_script_code(txi, pubkeyhash) # 13b. scriptCode - write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 13c. value diff --git a/core/src/trezor/messages/SignTx.py b/core/src/trezor/messages/SignTx.py index 67e5b3ebc..2977808ea 100644 --- a/core/src/trezor/messages/SignTx.py +++ b/core/src/trezor/messages/SignTx.py @@ -21,7 +21,6 @@ class SignTx(p.MessageType): version: int = None, lock_time: int = None, expiry: int = None, - overwintered: bool = None, version_group_id: int = None, timestamp: int = None, branch_id: int = None, @@ -32,7 +31,6 @@ class SignTx(p.MessageType): self.version = version self.lock_time = lock_time self.expiry = expiry - self.overwintered = overwintered self.version_group_id = version_group_id self.timestamp = timestamp self.branch_id = branch_id @@ -46,7 +44,6 @@ class SignTx(p.MessageType): 4: ('version', p.UVarintType, 0), # default=1 5: ('lock_time', p.UVarintType, 0), # default=0 6: ('expiry', p.UVarintType, 0), - 7: ('overwintered', p.BoolType, 0), 8: ('version_group_id', p.UVarintType, 0), 9: ('timestamp', p.UVarintType, 0), 10: ('branch_id', p.UVarintType, 0), diff --git a/core/src/trezor/messages/TransactionType.py b/core/src/trezor/messages/TransactionType.py index 0d239f6bd..b2aaaf1ec 100644 --- a/core/src/trezor/messages/TransactionType.py +++ b/core/src/trezor/messages/TransactionType.py @@ -28,7 +28,6 @@ class TransactionType(p.MessageType): extra_data: bytes = None, extra_data_len: int = None, expiry: int = None, - overwintered: bool = None, version_group_id: int = None, timestamp: int = None, branch_id: int = None, @@ -43,7 +42,6 @@ class TransactionType(p.MessageType): self.extra_data = extra_data self.extra_data_len = extra_data_len self.expiry = expiry - self.overwintered = overwintered self.version_group_id = version_group_id self.timestamp = timestamp self.branch_id = branch_id @@ -61,7 +59,6 @@ class TransactionType(p.MessageType): 8: ('extra_data', p.BytesType, 0), 9: ('extra_data_len', p.UVarintType, 0), 10: ('expiry', p.UVarintType, 0), - 11: ('overwintered', p.BoolType, 0), 12: ('version_group_id', p.UVarintType, 0), 13: ('timestamp', p.UVarintType, 0), 14: ('branch_id', p.UVarintType, 0), diff --git a/core/src/trezor/messages/TxInputType.py b/core/src/trezor/messages/TxInputType.py index ebe66e776..bd7d4c6f2 100644 --- a/core/src/trezor/messages/TxInputType.py +++ b/core/src/trezor/messages/TxInputType.py @@ -27,8 +27,6 @@ class TxInputType(p.MessageType): amount: int = None, decred_tree: int = None, decred_script_version: int = None, - prev_block_hash_bip115: bytes = None, - prev_block_height_bip115: int = None, ) -> None: self.address_n = address_n if address_n is not None else [] self.prev_hash = prev_hash @@ -40,8 +38,6 @@ class TxInputType(p.MessageType): self.amount = amount self.decred_tree = decred_tree self.decred_script_version = decred_script_version - self.prev_block_hash_bip115 = prev_block_hash_bip115 - self.prev_block_height_bip115 = prev_block_height_bip115 @classmethod def get_fields(cls) -> Dict: @@ -56,6 +52,4 @@ class TxInputType(p.MessageType): 8: ('amount', p.UVarintType, 0), 9: ('decred_tree', p.UVarintType, 0), 10: ('decred_script_version', p.UVarintType, 0), - 11: ('prev_block_hash_bip115', p.BytesType, 0), - 12: ('prev_block_height_bip115', p.UVarintType, 0), } diff --git a/core/src/trezor/messages/TxOutputType.py b/core/src/trezor/messages/TxOutputType.py index bac572506..20edacf61 100644 --- a/core/src/trezor/messages/TxOutputType.py +++ b/core/src/trezor/messages/TxOutputType.py @@ -24,8 +24,6 @@ class TxOutputType(p.MessageType): multisig: MultisigRedeemScriptType = None, op_return_data: bytes = None, decred_script_version: int = None, - block_hash_bip115: bytes = None, - block_height_bip115: int = None, ) -> None: self.address = address self.address_n = address_n if address_n is not None else [] @@ -34,8 +32,6 @@ class TxOutputType(p.MessageType): self.multisig = multisig self.op_return_data = op_return_data self.decred_script_version = decred_script_version - self.block_hash_bip115 = block_hash_bip115 - self.block_height_bip115 = block_height_bip115 @classmethod def get_fields(cls) -> Dict: @@ -47,6 +43,4 @@ class TxOutputType(p.MessageType): 5: ('multisig', MultisigRedeemScriptType, 0), 6: ('op_return_data', p.BytesType, 0), 7: ('decred_script_version', p.UVarintType, 0), - 8: ('block_hash_bip115', p.BytesType, 0), - 9: ('block_height_bip115', p.UVarintType, 0), } diff --git a/core/src/trezor/ui/confirm.py b/core/src/trezor/ui/confirm.py index 9641f4e3e..b519f7723 100644 --- a/core/src/trezor/ui/confirm.py +++ b/core/src/trezor/ui/confirm.py @@ -241,19 +241,27 @@ class HoldToConfirm(ui.Layout): confirm: str = DEFAULT_CONFIRM, confirm_style: ButtonStyleType = DEFAULT_CONFIRM_STYLE, loader_style: LoaderStyleType = DEFAULT_LOADER_STYLE, + cancel: bool = True, ): self.content = content self.loader = Loader(loader_style) self.loader.on_start = self._on_loader_start # type: ignore - self.confirm = Button(ui.grid(17, n_x=4, cells_x=3), confirm, confirm_style) + if cancel: + self.confirm = Button(ui.grid(17, n_x=4, cells_x=3), confirm, confirm_style) + else: + self.confirm = Button(ui.grid(4, n_x=1), confirm, confirm_style) self.confirm.on_press_start = self._on_press_start # type: ignore self.confirm.on_press_end = self._on_press_end # type: ignore self.confirm.on_click = self._on_click # type: ignore - self.cancel = Button(ui.grid(16, n_x=4), res.load(ui.ICON_CANCEL), ButtonAbort) - self.cancel.on_click = self.on_cancel # type: ignore + self.cancel = None + if cancel: + self.cancel = Button( + ui.grid(16, n_x=4), res.load(ui.ICON_CANCEL), ButtonAbort + ) + self.cancel.on_click = self.on_cancel # type: ignore def _on_press_start(self) -> None: self.loader.start() @@ -278,7 +286,8 @@ class HoldToConfirm(ui.Layout): else: self.content.dispatch(event, x, y) self.confirm.dispatch(event, x, y) - self.cancel.dispatch(event, x, y) + if self.cancel: + self.cancel.dispatch(event, x, y) def on_confirm(self) -> None: raise ui.Result(CONFIRMED) diff --git a/core/tests/test_apps.wallet.address.py b/core/tests/test_apps.wallet.address.py index d7df64013..ad42e47ca 100644 --- a/core/tests/test_apps.wallet.address.py +++ b/core/tests/test_apps.wallet.address.py @@ -71,7 +71,7 @@ class TestAddress(unittest.TestCase): # pubkey OP_CHECKSIG script = unhexlify('210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac') h = HashWriter(sha256()) - write_bytes(h, script) + write_bytes_unchecked(h, script) address = address_p2wsh( h.get_digest(), diff --git a/core/tests/test_apps.wallet.sign_tx.writers.py b/core/tests/test_apps.wallet.sign_tx.writers.py new file mode 100644 index 000000000..7f8a2a985 --- /dev/null +++ b/core/tests/test_apps.wallet.sign_tx.writers.py @@ -0,0 +1,54 @@ +from common import * + +from trezor.messages.TxInputType import TxInputType +from trezor.messages import InputScriptType + +from apps.common import coins +from apps.common.seed import Keychain +from apps.wallet.sign_tx import writers + + +class TestWriters(unittest.TestCase): + def test_tx_input(self): + inp = TxInputType( + address_n=[0], + amount=390000, + prev_hash=unhexlify( + "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882" + ), + prev_index=0, + sequence=0xffffffff, + script_sig=b"0123456789", + ) + + b = bytearray() + writers.write_tx_input(b, inp) + self.assertEqual(len(b), 32 + 4 + 1 + 10 + 4) + + for bad_prevhash in (b"", b"x", b"hello", b"x" * 33): + inp.prev_hash = bad_prevhash + self.assertRaises(AssertionError, writers.write_tx_input, b, inp) + + def test_tx_input_check(self): + inp = TxInputType( + address_n=[0], + amount=390000, + prev_hash=unhexlify( + "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882" + ), + prev_index=0, + script_type=InputScriptType.SPENDWITNESS, + sequence=0xffffffff, + script_sig=b"0123456789", + ) + + b = bytearray() + writers.write_tx_input_check(b, inp) + self.assertEqual(len(b), 32 + 4 + 4 + 4 + 4 + 4 + 8) + + for bad_prevhash in (b"", b"x", b"hello", b"x" * 33): + inp.prev_hash = bad_prevhash + self.assertRaises(AssertionError, writers.write_tx_input_check, b, inp) + +if __name__ == "__main__": + unittest.main() diff --git a/core/tests/test_apps.wallet.signtx.scripts.py b/core/tests/test_apps.wallet.signtx.scripts.py deleted file mode 100644 index 9ec833cfc..000000000 --- a/core/tests/test_apps.wallet.signtx.scripts.py +++ /dev/null @@ -1,20 +0,0 @@ -from common import * - -from apps.wallet.sign_tx.scripts import script_replay_protection_bip115 - -class TestSigntxScripts(unittest.TestCase): - # pylint: disable=C0301 - - def test_script_replay_protection_bip115(self): - vectors=[ - ('206ec9b310745775c20cbe5bae8751daeb7f086cf913399d4f7634ef2a0000000003122005b4', '6ec9b310745775c20cbe5bae8751daeb7f086cf913399d4f7634ef2a00000000', 335890), - ('20caaa71b60cf893c1604b38e5af1bdc322dbb31818239088647272d1400000000030e2005b4', 'caaa71b60cf893c1604b38e5af1bdc322dbb31818239088647272d1400000000', 335886), - ] - for out, hsh, height in vectors: - hsh = unhexlify(hsh) - res = hexlify(script_replay_protection_bip115(hsh, height)).decode() - self.assertEqual(out, res) - - -if __name__ == '__main__': - unittest.main() diff --git a/core/tests/test_apps.wallet.zcash.zip143.py b/core/tests/test_apps.wallet.zcash.zip143.py index 4ee999479..8c7d3eaba 100644 --- a/core/tests/test_apps.wallet.zcash.zip143.py +++ b/core/tests/test_apps.wallet.zcash.zip143.py @@ -151,7 +151,6 @@ class TestZcashZip143(unittest.TestCase): version=v["version"], lock_time=v["lock_time"], expiry=v["expiry"], - overwintered=(v["version"] >= 3), version_group_id=v["version_group_id"], ) zip143 = Zip143(0x5ba81b19) # Overwinter diff --git a/core/tests/test_apps.wallet.zcash.zip243.py b/core/tests/test_apps.wallet.zcash.zip243.py index 776179b85..b4ed1e079 100644 --- a/core/tests/test_apps.wallet.zcash.zip243.py +++ b/core/tests/test_apps.wallet.zcash.zip243.py @@ -185,7 +185,6 @@ class TestZcashZip243(unittest.TestCase): version=v["version"], lock_time=v["lock_time"], expiry=v["expiry"], - overwintered=(v["version"] >= 3), version_group_id=v["version_group_id"], ) zip243 = Zip243(0x76b809bb) # Sapling diff --git a/core/tests/unittest.py b/core/tests/unittest.py index 4cb339fe3..a78a68d03 100644 --- a/core/tests/unittest.py +++ b/core/tests/unittest.py @@ -119,11 +119,12 @@ class TestCase: return AssertRaisesContext(exc) try: func(*args, **kwargs) - ensure(False, "%r not raised" % exc) except Exception as e: if isinstance(e, exc): return raise + else: + ensure(False, "%r not raised" % exc) def assertListEqual(self, x, y, msg=''): if len(x) != len(y): diff --git a/legacy/firmware/coin_info.c.mako b/legacy/firmware/coin_info.c.mako index 56e8771b6..0bf75df24 100644 --- a/legacy/firmware/coin_info.c.mako +++ b/legacy/firmware/coin_info.c.mako @@ -46,6 +46,9 @@ const CoinInfo coins[COINS_COUNT] = { .negative_fee = ${c_bool(c.negative_fee)}, .curve_name = ${c.curve_name.upper()}_NAME, .curve = &${c.curve_name}_info, + .extra_data = ${c_bool(c.extra_data)}, + .timestamp = ${c_bool(c.timestamp)}, + .overwintered = ${c_bool(c.consensus_branch_id)}, }, % endfor }; diff --git a/legacy/firmware/coins.h b/legacy/firmware/coins.h index 1b15dc15a..4bb924f78 100644 --- a/legacy/firmware/coins.h +++ b/legacy/firmware/coins.h @@ -49,6 +49,9 @@ typedef struct _CoinInfo { bool negative_fee; const char *curve_name; const curve_info *curve; + bool extra_data; + bool timestamp; + bool overwintered; } CoinInfo; #include "coin_info.h" diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 65d621eab..b3b662019 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -102,6 +102,13 @@ void fsm_msgSignTx(const SignTx *msg) { const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name); if (!coin) return; + + CHECK_PARAM((coin->decred || coin->overwintered) || !msg->has_expiry, + _("Expiry not enabled on this coin.")) + CHECK_PARAM(coin->timestamp || !msg->has_timestamp, + _("Timestamp not enabled on this coin.")) + CHECK_PARAM(!coin->timestamp || msg->timestamp, _("Timestamp must be set.")) + const HDNode *node = fsm_getDerivedNode(coin->curve_name, NULL, 0, NULL); if (!node) return; diff --git a/legacy/firmware/protob/messages-bitcoin.options b/legacy/firmware/protob/messages-bitcoin.options index f04d01f93..e444b86c3 100644 --- a/legacy/firmware/protob/messages-bitcoin.options +++ b/legacy/firmware/protob/messages-bitcoin.options @@ -31,12 +31,10 @@ TransactionType.extra_data max_size:1024 TxInputType.address_n max_count:8 TxInputType.prev_hash max_size:32 TxInputType.script_sig max_size:1650 -TxInputType.prev_block_hash_bip115 max_size:32 TxOutputType.address max_size:130 TxOutputType.address_n max_count:8 TxOutputType.op_return_data max_size:80 -TxOutputType.block_hash_bip115 max_size:32 TxOutputBinType.script_pubkey max_size:520 diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 28277c043..e18f7c51d 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -41,7 +41,9 @@ enum { STAGE_REQUEST_2_PREV_META, STAGE_REQUEST_2_PREV_INPUT, STAGE_REQUEST_2_PREV_OUTPUT, +#if !BITCOIN_ONLY STAGE_REQUEST_2_PREV_EXTRADATA, +#endif STAGE_REQUEST_3_OUTPUT, STAGE_REQUEST_4_INPUT, STAGE_REQUEST_4_OUTPUT, @@ -66,11 +68,10 @@ static uint8_t hash_prevouts[32], hash_sequence[32], hash_outputs[32]; static uint8_t decred_hash_prefix[32]; #endif static uint8_t hash_check[32]; -static uint64_t to_spend, authorized_amount, spending, change_spend; +static uint64_t to_spend, authorized_bip143_in, spending, change_spend; static uint32_t version = 1; static uint32_t lock_time = 0; static uint32_t expiry = 0; -static bool overwintered = false; static uint32_t version_group_id = 0; static uint32_t timestamp = 0; #if !BITCOIN_ONLY @@ -269,6 +270,8 @@ void send_req_2_prev_output(void) { msg_write(MessageType_MessageType_TxRequest, &resp); } +#if !BITCOIN_ONLY + void send_req_2_prev_extradata(uint32_t chunk_offset, uint32_t chunk_len) { signing_stage = STAGE_REQUEST_2_PREV_EXTRADATA; resp.has_request_type = true; @@ -285,6 +288,8 @@ void send_req_2_prev_extradata(uint32_t chunk_offset, uint32_t chunk_len) { msg_write(MessageType_MessageType_TxRequest, &resp); } +#endif + void send_req_3_output(void) { signing_stage = STAGE_REQUEST_3_OUTPUT; resp.has_request_type = true; @@ -484,22 +489,26 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, memcpy(&root, _root, sizeof(HDNode)); version = msg->version; lock_time = msg->lock_time; - expiry = msg->expiry; #if !BITCOIN_ONLY - overwintered = msg->has_overwintered && msg->overwintered; - version_group_id = msg->version_group_id; - timestamp = msg->timestamp; - branch_id = msg->branch_id; - // set default values for Zcash if branch_id is unset - if (overwintered && (branch_id == 0)) { - switch (version) { - case 3: - branch_id = 0x5BA81B19; // Overwinter - break; - case 4: - branch_id = 0x76B809BB; // Sapling - break; + expiry = (coin->decred || coin->overwintered) ? msg->expiry : 0; + timestamp = coin->timestamp ? msg->timestamp : 0; + if (coin->overwintered) { + version_group_id = msg->version_group_id; + branch_id = msg->branch_id; + if (branch_id == 0) { + // set default values for Zcash if branch_id is unset + switch (version) { + case 3: + branch_id = 0x5BA81B19; // Overwinter + break; + case 4: + branch_id = 0x76B809BB; // Sapling + break; + } } + } else { + version_group_id = 0; + branch_id = 0; } #endif @@ -520,7 +529,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, to_spend = 0; spending = 0; change_spend = 0; - authorized_amount = 0; + authorized_bip143_in = 0; memzero(&input, sizeof(TxInputType)); memzero(&resp, sizeof(TxRequest)); @@ -536,7 +545,8 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, next_nonsegwit_input = 0xffffffff; tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, - coin->curve->hasher_sign, overwintered, version_group_id, timestamp); + coin->curve->hasher_sign, coin->overwintered, version_group_id, + timestamp); #if !BITCOIN_ONLY if (coin->decred) { @@ -544,7 +554,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, to.is_decred = true; tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, - coin->curve->hasher_sign, overwintered, version_group_id, + coin->curve->hasher_sign, coin->overwintered, version_group_id, timestamp); ti.version |= (DECRED_SERIALIZE_NO_WITNESS << 16); ti.is_decred = true; @@ -553,7 +563,7 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, // segwit hashes for hashPrevouts and hashSequence #if !BITCOIN_ONLY - if (overwintered) { + if (coin->overwintered) { hasher_InitParam(&hasher_prevouts, HASHER_BLAKE2B_PERSONAL, "ZcashPrevoutHash", 16); hasher_InitParam(&hasher_sequence, HASHER_BLAKE2B_PERSONAL, @@ -577,6 +587,171 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin, #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +static bool is_multisig_input_script_type(const TxInputType *txinput) { + if (txinput->script_type == InputScriptType_SPENDMULTISIG || + txinput->script_type == InputScriptType_SPENDP2SHWITNESS || + txinput->script_type == InputScriptType_SPENDWITNESS) { + return true; + } + return false; +} + +static bool is_multisig_output_script_type(const TxOutputType *txoutput) { + if (txoutput->script_type == OutputScriptType_PAYTOMULTISIG || + txoutput->script_type == OutputScriptType_PAYTOP2SHWITNESS || + txoutput->script_type == OutputScriptType_PAYTOWITNESS) { + return true; + } + return false; +} + +static bool is_internal_input_script_type(const TxInputType *txinput) { + if (txinput->script_type == InputScriptType_SPENDADDRESS || + txinput->script_type == InputScriptType_SPENDMULTISIG || + txinput->script_type == InputScriptType_SPENDP2SHWITNESS || + txinput->script_type == InputScriptType_SPENDWITNESS) { + return true; + } + return false; +} + +static bool is_change_output_script_type(const TxOutputType *txoutput) { + if (txoutput->script_type == OutputScriptType_PAYTOADDRESS || + txoutput->script_type == OutputScriptType_PAYTOMULTISIG || + txoutput->script_type == OutputScriptType_PAYTOP2SHWITNESS || + txoutput->script_type == OutputScriptType_PAYTOWITNESS) { + return true; + } + return false; +} + +static bool is_segwit_input_script_type(const TxInputType *txinput) { + if (txinput->script_type == InputScriptType_SPENDP2SHWITNESS || + txinput->script_type == InputScriptType_SPENDWITNESS) { + return true; + } + return false; +} + +static bool signing_validate_input(const TxInputType *txinput) { + if (txinput->prev_hash.size != 32) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Encountered invalid prevhash")); + signing_abort(); + return false; + } + if (txinput->has_multisig && !is_multisig_input_script_type(txinput)) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Multisig field provided but not expected.")); + signing_abort(); + return false; + } + if (txinput->address_n_count > 0 && !is_internal_input_script_type(txinput)) { + fsm_sendFailure(FailureType_Failure_DataError, + "Input's address_n provided but not expected."); + signing_abort(); + return false; + } + if (!coin->decred && txinput->has_decred_script_version) { + fsm_sendFailure( + FailureType_Failure_DataError, + _("Decred details provided but Decred coin not specified.")); + signing_abort(); + return false; + } + +#if !BITCOIN_ONLY + if (coin->force_bip143 || coin->overwintered) { + if (!txinput->has_amount) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Expected input with amount")); + signing_abort(); + return false; + } + } +#endif + + if (is_segwit_input_script_type(txinput)) { + if (!coin->has_segwit) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Segwit not enabled on this coin")); + signing_abort(); + return false; + } + if (!txinput->has_amount) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Segwit input without amount")); + signing_abort(); + return false; + } + } + + return true; +} + +static bool signing_validate_output(TxOutputType *txoutput) { + if (txoutput->has_multisig && !is_multisig_output_script_type(txoutput)) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Multisig field provided but not expected.")); + signing_abort(); + return false; + } + + if (txoutput->address_n_count > 0 && + !is_change_output_script_type(txoutput)) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Output's address_n provided but not expected.")); + signing_abort(); + return false; + } + + if (txoutput->script_type == OutputScriptType_PAYTOOPRETURN) { + if (txoutput->has_address || (txoutput->address_n_count > 0) || + txoutput->has_multisig) { + fsm_sendFailure(FailureType_Failure_DataError, + _("OP_RETURN output with address or multisig")); + signing_abort(); + return false; + } + if (txoutput->amount != 0) { + fsm_sendFailure(FailureType_Failure_DataError, + _("OP_RETURN output with non-zero amount")); + signing_abort(); + return false; + } + } else { + if (txoutput->has_op_return_data) { + fsm_sendFailure( + FailureType_Failure_DataError, + _("OP RETURN data provided but not OP RETURN script type.")); + signing_abort(); + return false; + } + if (txoutput->has_address && txoutput->address_n_count > 0) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Both address and address_n provided.")); + signing_abort(); + return false; + } else if (!txoutput->has_address && txoutput->address_n_count == 0) { + fsm_sendFailure(FailureType_Failure_DataError, _("Missing address")); + signing_abort(); + return false; + } + } + return true; +} + +static bool signing_validate_bin_output(TxOutputBinType *tx_bin_output) { + if (!coin->decred && tx_bin_output->has_decred_script_version) { + fsm_sendFailure( + FailureType_Failure_DataError, + _("Decred details provided but Decred coin not specified.")); + signing_abort(); + return false; + } + return true; +} + static bool signing_check_input(const TxInputType *txinput) { /* compute multisig fingerprint */ /* (if all input share the same fingerprint, outputs having the same @@ -655,12 +830,6 @@ static bool signing_check_output(TxOutputType *txoutput) { // check for change address bool is_change = false; if (txoutput->address_n_count > 0) { - if (txoutput->has_address) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Address in change output")); - signing_abort(); - return false; - } /* * For multisig check that all inputs are multisig */ @@ -674,17 +843,10 @@ static bool signing_check_output(TxOutputType *txoutput) { } else { is_change = check_change_bip32_path(txoutput); } - /* - * only allow segwit change if amount is smaller than what segwit inputs - * paid. this was added during the times segwit was not yet fully activated - * to make sure the user is not tricked to use witness change output - * instead of regular one therefore creating ANYONECANSPEND output - */ - if ((txoutput->script_type == OutputScriptType_PAYTOWITNESS || - txoutput->script_type == OutputScriptType_PAYTOP2SHWITNESS) && - txoutput->amount > authorized_amount) { - is_change = false; - } + } + + if (!is_change_output_script_type(txoutput)) { + is_change = false; } if (is_change) { @@ -989,21 +1151,20 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { // idx1: index to sign uint8_t hash[32] = {0}; - if (txinput->script_type == InputScriptType_SPENDWITNESS || - txinput->script_type == InputScriptType_SPENDP2SHWITNESS) { + if (is_segwit_input_script_type(txinput)) { if (!compile_input_script_sig(txinput)) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input")); signing_abort(); return false; } - if (txinput->amount > authorized_amount) { + if (txinput->amount > authorized_bip143_in) { fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); return false; } - authorized_amount -= txinput->amount; + authorized_bip143_in -= txinput->amount; signing_hash_bip143(txinput, hash); @@ -1100,7 +1261,10 @@ void signing_txack(TransactionType *tx) { switch (signing_stage) { case STAGE_REQUEST_1_INPUT: - signing_check_input(&tx->inputs[0]); + if (!signing_validate_input(&tx->inputs[0]) || + !signing_check_input(&tx->inputs[0])) { + return; + } tx_weight += tx_input_weight(coin, &tx->inputs[0]); #if !BITCOIN_ONLY @@ -1123,50 +1287,25 @@ void signing_txack(TransactionType *tx) { } #endif - if (coin->force_bip143 || overwintered) { - if (!tx->inputs[0].has_amount) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Expected input with amount")); - signing_abort(); - return; - } +#if !BITCOIN_ONLY + if (coin->force_bip143 || coin->overwintered) { if (to_spend + tx->inputs[0].amount < to_spend) { fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); return; } to_spend += tx->inputs[0].amount; - authorized_amount += tx->inputs[0].amount; + authorized_bip143_in += tx->inputs[0].amount; phase1_request_next_input(); - } else { + } else +#endif + { // remember the first non-segwit input -- this is the first input // we need to sign during phase2 if (next_nonsegwit_input == 0xffffffff) next_nonsegwit_input = idx1; send_req_2_prev_meta(); } - } else if (tx->inputs[0].script_type == InputScriptType_SPENDWITNESS || - tx->inputs[0].script_type == - InputScriptType_SPENDP2SHWITNESS) { -#if !BITCOIN_ONLY - if (coin->decred) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Decred does not support Segwit")); - signing_abort(); - return; - } -#endif - if (!coin->has_segwit) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Segwit not enabled on this coin")); - signing_abort(); - return; - } - if (!tx->inputs[0].has_amount) { - fsm_sendFailure(FailureType_Failure_DataError, - _("Segwit input without amount")); - signing_abort(); - return; - } + } else if (is_segwit_input_script_type(&tx->inputs[0])) { if (to_spend + tx->inputs[0].amount < to_spend) { fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); @@ -1190,7 +1329,7 @@ void signing_txack(TransactionType *tx) { to.is_segwit = true; #endif to_spend += tx->inputs[0].amount; - authorized_amount += tx->inputs[0].amount; + authorized_bip143_in += tx->inputs[0].amount; phase1_request_next_input(); } else { fsm_sendFailure(FailureType_Failure_DataError, @@ -1206,6 +1345,30 @@ void signing_txack(TransactionType *tx) { signing_abort(); return; } + if (!coin->extra_data && tx->extra_data_len > 0) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Extra data not enabled on this coin.")); + signing_abort(); + return; + } + if (!coin->decred && !coin->overwintered && tx->has_expiry) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Expiry not enabled on this coin.")); + signing_abort(); + return; + } + if (!coin->timestamp && tx->has_timestamp) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Timestamp not enabled on this coin.")); + signing_abort(); + return; + } + if (coin->timestamp && !tx->timestamp) { + fsm_sendFailure(FailureType_Failure_DataError, + _("Timestamp must be set.")); + signing_abort(); + return; + } if (tx->inputs_cnt + tx->outputs_cnt < tx->inputs_cnt) { fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); @@ -1213,7 +1376,7 @@ void signing_txack(TransactionType *tx) { } tx_init(&tp, tx->inputs_cnt, tx->outputs_cnt, tx->version, tx->lock_time, tx->expiry, tx->extra_data_len, coin->curve->hasher_sign, - tx->overwintered, tx->version_group_id, tx->timestamp); + coin->overwintered, tx->version_group_id, tx->timestamp); #if !BITCOIN_ONLY if (coin->decred) { tp.version |= (DECRED_SERIALIZE_NO_WITNESS << 16); @@ -1230,6 +1393,9 @@ void signing_txack(TransactionType *tx) { } return; case STAGE_REQUEST_2_PREV_INPUT: + if (!signing_validate_input(&tx->inputs[0])) { + return; + } progress = (idx1 * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION; if (!tx_serialize_input_hash(&tp, tx->inputs)) { @@ -1247,6 +1413,9 @@ void signing_txack(TransactionType *tx) { } return; case STAGE_REQUEST_2_PREV_OUTPUT: + if (!signing_validate_bin_output(&tx->bin_outputs[0])) { + return; + } progress = (idx1 * progress_step + (tp.inputs_len + idx2) * progress_meta_step) >> PROGRESS_PRECISION; @@ -1264,9 +1433,9 @@ void signing_txack(TransactionType *tx) { } #if !BITCOIN_ONLY if (coin->decred && tx->bin_outputs[0].decred_script_version > 0) { - fsm_sendFailure( - FailureType_Failure_DataError, - _("Decred script version does not match previous output")); + fsm_sendFailure(FailureType_Failure_DataError, + _("Decred script version does " + "not match previous output")); signing_abort(); return; } @@ -1277,14 +1446,19 @@ void signing_txack(TransactionType *tx) { /* Check prevtx of next input */ idx2++; send_req_2_prev_output(); - } else if (tp.extra_data_len > 0) { // has extra data +#if !BITCOIN_ONLY + } else if (coin->extra_data && tp.extra_data_len > 0) { // has extra data send_req_2_prev_extradata(0, MIN(1024, tp.extra_data_len)); return; +#endif } else { /* prevtx is done */ - signing_check_prevtx_hash(); + if (!signing_check_prevtx_hash()) { + return; + } } return; +#if !BITCOIN_ONLY case STAGE_REQUEST_2_PREV_EXTRADATA: if (!tx_serialize_extra_data_hash(&tp, tx->extra_data.bytes, tx->extra_data.size)) { @@ -1299,23 +1473,30 @@ void signing_txack(TransactionType *tx) { tp.extra_data_received, MIN(1024, tp.extra_data_len - tp.extra_data_received)); } else { - signing_check_prevtx_hash(); + if (!signing_check_prevtx_hash()) { + return; + } } return; +#endif case STAGE_REQUEST_3_OUTPUT: - if (!signing_check_output(&tx->outputs[0])) { + if (!signing_validate_output(&tx->outputs[0]) || + !signing_check_output(&tx->outputs[0])) { return; } tx_weight += tx_output_weight(coin, &tx->outputs[0]); phase1_request_next_output(); return; case STAGE_REQUEST_4_INPUT: + if (!signing_validate_input(&tx->inputs[0])) { + return; + } progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION); if (idx2 == 0) { tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, - coin->curve->hasher_sign, overwintered, version_group_id, + coin->curve->hasher_sign, coin->overwintered, version_group_id, timestamp); hasher_Reset(&hasher_check); } @@ -1365,6 +1546,9 @@ void signing_txack(TransactionType *tx) { } return; case STAGE_REQUEST_4_OUTPUT: + if (!signing_validate_output(&tx->outputs[0])) { + return; + } progress = 500 + ((signatures * progress_step + (inputs_count + idx2) * progress_meta_step) >> PROGRESS_PRECISION); @@ -1405,13 +1589,16 @@ void signing_txack(TransactionType *tx) { return; case STAGE_REQUEST_SEGWIT_INPUT: + if (!signing_validate_input(&tx->inputs[0])) { + return; + } resp.has_serialized = true; resp.serialized.has_signature_index = false; resp.serialized.has_signature = false; resp.serialized.has_serialized_tx = true; if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG || tx->inputs[0].script_type == InputScriptType_SPENDADDRESS) { - if (!(coin->force_bip143 || overwintered)) { + if (!(coin->force_bip143 || coin->overwintered)) { fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); @@ -1423,17 +1610,17 @@ void signing_txack(TransactionType *tx) { signing_abort(); return; } - if (tx->inputs[0].amount > authorized_amount) { + if (tx->inputs[0].amount > authorized_bip143_in) { fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); return; } - authorized_amount -= tx->inputs[0].amount; + authorized_bip143_in -= tx->inputs[0].amount; uint8_t hash[32] = {0}; #if !BITCOIN_ONLY - if (overwintered) { + if (coin->overwintered) { switch (version) { case 3: signing_hash_zip143(&tx->inputs[0], hash); @@ -1511,6 +1698,9 @@ void signing_txack(TransactionType *tx) { return; case STAGE_REQUEST_5_OUTPUT: + if (!signing_validate_output(&tx->outputs[0])) { + return; + } if (compile_output(coin, &root, tx->outputs, &bin_output, false) <= 0) { fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile output")); @@ -1534,6 +1724,9 @@ void signing_txack(TransactionType *tx) { return; case STAGE_REQUEST_SEGWIT_WITNESS: + if (!signing_validate_input(&tx->inputs[0])) { + return; + } if (!signing_sign_segwit_input(&tx->inputs[0])) { return; } @@ -1553,20 +1746,23 @@ void signing_txack(TransactionType *tx) { #if !BITCOIN_ONLY case STAGE_REQUEST_DECRED_WITNESS: + if (!signing_validate_input(&tx->inputs[0])) { + return; + } progress = 500 + ((signatures * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION); if (idx1 == 0) { // witness tx_init(&to, inputs_count, outputs_count, version, lock_time, expiry, 0, - coin->curve->hasher_sign, overwintered, version_group_id, + coin->curve->hasher_sign, coin->overwintered, version_group_id, timestamp); to.is_decred = true; } // witness hash tx_init(&ti, inputs_count, outputs_count, version, lock_time, expiry, 0, - coin->curve->hasher_sign, overwintered, version_group_id, + coin->curve->hasher_sign, coin->overwintered, version_group_id, timestamp); ti.version |= (DECRED_SERIALIZE_WITNESS_SIGNING << 16); ti.is_decred = true; diff --git a/legacy/firmware/transaction.c b/legacy/firmware/transaction.c index 551f38eb6..450a165d1 100644 --- a/legacy/firmware/transaction.c +++ b/legacy/firmware/transaction.c @@ -199,7 +199,8 @@ int compile_output(const CoinInfo *coin, const HDNode *root, TxOutputType *in, if (in->script_type == OutputScriptType_PAYTOOPRETURN) { // only 0 satoshi allowed for OP_RETURN - if (in->amount != 0) { + if (in->amount != 0 || in->has_address || (in->address_n_count > 0) || + in->has_multisig) { return 0; // failed to compile output } if (needs_confirm) { @@ -503,17 +504,22 @@ uint32_t tx_serialize_script(uint32_t size, const uint8_t *data, uint8_t *out) { uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out) { int r = 4; +#if !BITCOIN_ONLY if (tx->overwintered) { uint32_t ver = tx->version | TX_OVERWINTERED; memcpy(out, &ver, 4); memcpy(out + 4, &(tx->version_group_id), 4); r += 4; - } else { + } else +#endif + { memcpy(out, &(tx->version), 4); +#if !BITCOIN_ONLY if (tx->timestamp) { memcpy(out + r, &(tx->timestamp), 4); r += 4; } +#endif if (tx->is_segwit) { memcpy(out + r, segwit_header, 2); r += 2; @@ -524,16 +530,21 @@ uint32_t tx_serialize_header(TxStruct *tx, uint8_t *out) { uint32_t tx_serialize_header_hash(TxStruct *tx) { int r = 4; +#if !BITCOIN_ONLY if (tx->overwintered) { uint32_t ver = tx->version | TX_OVERWINTERED; hasher_Update(&(tx->hasher), (const uint8_t *)&ver, 4); hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->version_group_id), 4); r += 4; - } else { + } else +#endif + { hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->version), 4); +#if !BITCOIN_ONLY if (tx->timestamp) { hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->timestamp), 4); } +#endif if (tx->is_segwit) { hasher_Update(&(tx->hasher), segwit_header, 2); r += 2; @@ -558,10 +569,13 @@ uint32_t tx_serialize_input(TxStruct *tx, const TxInputType *input, r += 32; memcpy(out + r, &input->prev_index, 4); r += 4; +#if !BITCOIN_ONLY if (tx->is_decred) { uint8_t tree = input->decred_tree & 0xFF; out[r++] = tree; - } else { + } else +#endif + { r += tx_serialize_script(input->script_sig.size, input->script_sig.bytes, out + r); } @@ -584,11 +598,14 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input) { r += tx_serialize_header_hash(tx); } r += tx_prevout_hash(&(tx->hasher), input); +#if !BITCOIN_ONLY if (tx->is_decred) { uint8_t tree = input->decred_tree & 0xFF; hasher_Update(&(tx->hasher), (const uint8_t *)&(tree), 1); r++; - } else { + } else +#endif + { r += tx_script_hash(&(tx->hasher), input->script_sig.size, input->script_sig.bytes); } @@ -600,6 +617,7 @@ uint32_t tx_serialize_input_hash(TxStruct *tx, const TxInputType *input) { return r; } +#if !BITCOIN_ONLY uint32_t tx_serialize_decred_witness(TxStruct *tx, const TxInputType *input, uint8_t *out) { static const uint64_t amount = 0; @@ -651,6 +669,7 @@ uint32_t tx_serialize_decred_witness_hash(TxStruct *tx, return r; } +#endif uint32_t tx_serialize_middle(TxStruct *tx, uint8_t *out) { return ser_length(tx->outputs_len, out); @@ -662,6 +681,7 @@ uint32_t tx_serialize_middle_hash(TxStruct *tx) { uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out) { memcpy(out, &(tx->lock_time), 4); +#if !BITCOIN_ONLY if (tx->overwintered) { if (tx->version == 3) { memcpy(out + 4, &(tx->expiry), 4); @@ -680,11 +700,13 @@ uint32_t tx_serialize_footer(TxStruct *tx, uint8_t *out) { memcpy(out + 4, &(tx->expiry), 4); return 8; } +#endif return 4; } uint32_t tx_serialize_footer_hash(TxStruct *tx) { hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->lock_time), 4); +#if !BITCOIN_ONLY if (tx->overwintered) { hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4); hasher_Update(&(tx->hasher), (const uint8_t *)"\x00", 1); // nJoinSplit @@ -694,6 +716,7 @@ uint32_t tx_serialize_footer_hash(TxStruct *tx) { hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4); return 8; } +#endif return 4; } @@ -713,11 +736,13 @@ uint32_t tx_serialize_output(TxStruct *tx, const TxOutputBinType *output, } memcpy(out + r, &output->amount, 8); r += 8; +#if !BITCOIN_ONLY if (tx->is_decred) { uint16_t script_version = output->decred_script_version & 0xFFFF; memcpy(out + r, &script_version, 2); r += 2; } +#endif r += tx_serialize_script(output->script_pubkey.size, output->script_pubkey.bytes, out + r); tx->have_outputs++; @@ -750,6 +775,7 @@ uint32_t tx_serialize_output_hash(TxStruct *tx, const TxOutputBinType *output) { return r; } +#if !BITCOIN_ONLY uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, uint32_t datalen) { if (tx->have_inputs < tx->inputs_len) { @@ -769,6 +795,7 @@ uint32_t tx_serialize_extra_data_hash(TxStruct *tx, const uint8_t *data, tx->size += datalen; return datalen; } +#endif void tx_init(TxStruct *tx, uint32_t inputs_len, uint32_t outputs_len, uint32_t version, uint32_t lock_time, uint32_t expiry, @@ -902,6 +929,7 @@ uint32_t tx_output_weight(const CoinInfo *coin, const TxOutputType *txoutput) { return 4 * (size + output_script_size); } +#if !BITCOIN_ONLY uint32_t tx_decred_witness_weight(const TxInputType *txinput) { uint32_t input_script_size = tx_input_script_size(txinput); uint32_t size = TXSIZE_DECRED_WITNESS + ser_length_size(input_script_size) + @@ -909,3 +937,4 @@ uint32_t tx_decred_witness_weight(const TxInputType *txinput) { return 4 * size; } +#endif diff --git a/python/docs/transaction-format.md b/python/docs/transaction-format.md index 126761bfe..61a4e8029 100644 --- a/python/docs/transaction-format.md +++ b/python/docs/transaction-format.md @@ -60,8 +60,6 @@ message TxInputType { optional uint64 amount = 8; // amount of previous transaction output optional uint32 decred_tree = 9; // only for Decred optional uint32 decred_script_version = 10; // only for Decred - optional bytes prev_block_hash_bip115 = 11; // block hash of previous transaction output (for bip115 implementation) - optional uint32 prev_block_height_bip115 = 12; // block height of previous transaction output (for bip115 implementation) } ``` @@ -73,7 +71,7 @@ The field `script_sig` must not be set. The field `multisig` can be used for multisig inputs. Documenting the multisig structure is TBD. With regular inputs, `multisig` must not be set. -`decred` and `bip115` fields must only be set when relevant to your currency. +`decred` fields must only be set when relevant to your currency. ### Outputs @@ -94,8 +92,6 @@ message TxOutputType { optional MultisigRedeemScriptType multisig = 5; // multisig output definition optional bytes op_return_data = 6; // defines op_return data optional uint32 decred_script_version = 7; // only for Decred - optional bytes block_hash_bip115 = 8; // block hash of existing block (recommended current_block - 300) (for bip115 implementation) - optional uint32 block_height_bip115 = 9; // block height of existing block (recommended current_block - 300) (for bip115 implementation) ``` @@ -112,7 +108,7 @@ For `OP_RETURN` outputs, `script_type` must be set to `"PAYTOOPRETURN"` and `op_return_data` must be filled appropriately. `address_n` and `address` must not be set. -`decred` and `bip115` fields must only be set when relevant to your currency. +`decred` fields must only be set when relevant to your currency. ### Transaction metadata @@ -130,7 +126,7 @@ message SignTx { optional uint32 expiry = 6; // only for Decred and Zcash optional bool overwintered = 7; // only for Zcash optional uint32 version_group_id = 8; // only for Zcash, nVersionGroupId when overwintered is set - optional uint32 timestamp = 9; // only for Capricoin, transaction timestamp + optional uint32 timestamp = 9; // only for Peercoin, transaction timestamp optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID when overwintered is set } ``` @@ -164,7 +160,7 @@ message TransactionType { optional uint32 expiry = 10; // only for Decred and Zcash optional bool overwintered = 11; // only for Zcash optional uint32 version_group_id = 12; // only for Zcash, nVersionGroupId when overwintered is set - optional uint32 timestamp = 13; // only for Capricoin, transaction timestamp + optional uint32 timestamp = 13; // only for Peercoin, transaction timestamp optional uint32 branch_id = 14; // only for Zcash, BRANCH_ID when overwintered is set } ``` diff --git a/python/src/trezorlib/messages/SignTx.py b/python/src/trezorlib/messages/SignTx.py index c34c04bb1..905f019b0 100644 --- a/python/src/trezorlib/messages/SignTx.py +++ b/python/src/trezorlib/messages/SignTx.py @@ -21,7 +21,6 @@ class SignTx(p.MessageType): version: int = None, lock_time: int = None, expiry: int = None, - overwintered: bool = None, version_group_id: int = None, timestamp: int = None, branch_id: int = None, @@ -32,7 +31,6 @@ class SignTx(p.MessageType): self.version = version self.lock_time = lock_time self.expiry = expiry - self.overwintered = overwintered self.version_group_id = version_group_id self.timestamp = timestamp self.branch_id = branch_id @@ -46,7 +44,6 @@ class SignTx(p.MessageType): 4: ('version', p.UVarintType, 0), # default=1 5: ('lock_time', p.UVarintType, 0), # default=0 6: ('expiry', p.UVarintType, 0), - 7: ('overwintered', p.BoolType, 0), 8: ('version_group_id', p.UVarintType, 0), 9: ('timestamp', p.UVarintType, 0), 10: ('branch_id', p.UVarintType, 0), diff --git a/python/src/trezorlib/messages/TransactionType.py b/python/src/trezorlib/messages/TransactionType.py index c3eb7698d..c3949337b 100644 --- a/python/src/trezorlib/messages/TransactionType.py +++ b/python/src/trezorlib/messages/TransactionType.py @@ -28,7 +28,6 @@ class TransactionType(p.MessageType): extra_data: bytes = None, extra_data_len: int = None, expiry: int = None, - overwintered: bool = None, version_group_id: int = None, timestamp: int = None, branch_id: int = None, @@ -43,7 +42,6 @@ class TransactionType(p.MessageType): self.extra_data = extra_data self.extra_data_len = extra_data_len self.expiry = expiry - self.overwintered = overwintered self.version_group_id = version_group_id self.timestamp = timestamp self.branch_id = branch_id @@ -61,7 +59,6 @@ class TransactionType(p.MessageType): 8: ('extra_data', p.BytesType, 0), 9: ('extra_data_len', p.UVarintType, 0), 10: ('expiry', p.UVarintType, 0), - 11: ('overwintered', p.BoolType, 0), 12: ('version_group_id', p.UVarintType, 0), 13: ('timestamp', p.UVarintType, 0), 14: ('branch_id', p.UVarintType, 0), diff --git a/python/src/trezorlib/messages/TxInputType.py b/python/src/trezorlib/messages/TxInputType.py index 8050e2284..baf95b572 100644 --- a/python/src/trezorlib/messages/TxInputType.py +++ b/python/src/trezorlib/messages/TxInputType.py @@ -27,8 +27,6 @@ class TxInputType(p.MessageType): amount: int = None, decred_tree: int = None, decred_script_version: int = None, - prev_block_hash_bip115: bytes = None, - prev_block_height_bip115: int = None, ) -> None: self.address_n = address_n if address_n is not None else [] self.prev_hash = prev_hash @@ -40,8 +38,6 @@ class TxInputType(p.MessageType): self.amount = amount self.decred_tree = decred_tree self.decred_script_version = decred_script_version - self.prev_block_hash_bip115 = prev_block_hash_bip115 - self.prev_block_height_bip115 = prev_block_height_bip115 @classmethod def get_fields(cls) -> Dict: @@ -56,6 +52,4 @@ class TxInputType(p.MessageType): 8: ('amount', p.UVarintType, 0), 9: ('decred_tree', p.UVarintType, 0), 10: ('decred_script_version', p.UVarintType, 0), - 11: ('prev_block_hash_bip115', p.BytesType, 0), - 12: ('prev_block_height_bip115', p.UVarintType, 0), } diff --git a/python/src/trezorlib/messages/TxOutputType.py b/python/src/trezorlib/messages/TxOutputType.py index 466a6ce62..e6bf62d57 100644 --- a/python/src/trezorlib/messages/TxOutputType.py +++ b/python/src/trezorlib/messages/TxOutputType.py @@ -24,8 +24,6 @@ class TxOutputType(p.MessageType): multisig: MultisigRedeemScriptType = None, op_return_data: bytes = None, decred_script_version: int = None, - block_hash_bip115: bytes = None, - block_height_bip115: int = None, ) -> None: self.address = address self.address_n = address_n if address_n is not None else [] @@ -34,8 +32,6 @@ class TxOutputType(p.MessageType): self.multisig = multisig self.op_return_data = op_return_data self.decred_script_version = decred_script_version - self.block_hash_bip115 = block_hash_bip115 - self.block_height_bip115 = block_height_bip115 @classmethod def get_fields(cls) -> Dict: @@ -47,6 +43,4 @@ class TxOutputType(p.MessageType): 5: ('multisig', MultisigRedeemScriptType, 0), 6: ('op_return_data', p.BytesType, 0), 7: ('decred_script_version', p.UVarintType, 0), - 8: ('block_hash_bip115', p.BytesType, 0), - 9: ('block_height_bip115', p.UVarintType, 0), } diff --git a/tests/REGISTERED_MARKERS b/tests/REGISTERED_MARKERS index 0870190c4..20acd029c 100644 --- a/tests/REGISTERED_MARKERS +++ b/tests/REGISTERED_MARKERS @@ -1,7 +1,6 @@ altcoin slow binance -capricoin cardano decred eos diff --git a/tests/device_tests/test_msg_signtx.py b/tests/device_tests/test_msg_signtx.py index 1750f3a22..d158cab97 100644 --- a/tests/device_tests/test_msg_signtx.py +++ b/tests/device_tests/test_msg_signtx.py @@ -857,3 +857,120 @@ class TestMsgSigntx: ) check_sign_tx(client, "Testnet", [inp1], [out1, out_change]) + + @pytest.mark.skip_ui + def test_not_enough_vouts(self, client): + cache = TxCache("Bitcoin") + prev_tx = cache[TXHASH_157041] + + # tx has two vouts + assert len(prev_tx.bin_outputs) == 2 + + # vout[0] and vout[1] exist + inp0 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=0) + inp1 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=1) + # vout[2] does not exist + inp2 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=2) + + # try to spend the sum of existing vouts + out1 = proto.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=220160000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises( + TrezorFailure, match="Not enough outputs in previous transaction." + ): + btc.sign_tx(client, "Bitcoin", [inp0, inp1, inp2], [out1], prev_txes=cache) + + @pytest.mark.parametrize( + "field, value", + (("extra_data", b"hello world"), ("expiry", 9), ("timestamp", 42)), + ) + @pytest.mark.skip_ui + def test_prevtx_forbidden_fields(self, client, field, value): + cache = TxCache("Bitcoin") + inp0 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=0) + out1 = proto.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + prev_tx = cache[TXHASH_157041] + setattr(prev_tx, field, value) + name = field.replace("_", " ") + with pytest.raises( + TrezorFailure, match=r"(?i){} not enabled on this coin".format(name) + ): + btc.sign_tx( + client, "Bitcoin", [inp0], [out1], prev_txes={TXHASH_157041: prev_tx} + ) + + @pytest.mark.parametrize("field, value", (("expiry", 9), ("timestamp", 42))) + @pytest.mark.skip_ui + def test_signtx_forbidden_fields(self, client, field, value): + cache = TxCache("Bitcoin") + inp0 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=0) + out1 = proto.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + details = proto.SignTx() + setattr(details, field, value) + name = field.replace("_", " ") + with pytest.raises( + TrezorFailure, match=r"(?i){} not enabled on this coin".format(name) + ): + btc.sign_tx(client, "Bitcoin", [inp0], [out1], details, prev_txes=cache) + + @pytest.mark.skip_ui + def test_incorrect_script_type(self, client): + address_n = parse_path("44'/1'/0'/0/0") + attacker_multisig_public_key = bytes.fromhex( + "030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + multisig = proto.MultisigRedeemScriptType( + m=1, + nodes=[ + btc.get_public_node(client, address_n).node, + proto.HDNodeType( + depth=0, + fingerprint=0, + child_num=0, + chain_code=bytes(32), + public_key=attacker_multisig_public_key, + ), + ], + address_n=[], + ) + inp1 = proto.TxInputType( + address_n=address_n, + prev_index=1, + sequence=0xFFFFFFFF, + script_type=proto.InputScriptType.SPENDADDRESS, + multisig=multisig, + prev_hash=TXHASH_e5040e, + ) + out1 = proto.TxOutputType( + address_n=address_n, + amount=1000000 - 50000 - 10000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, + multisig=multisig, + ) + out2 = proto.TxOutputType( + address="mtkyndbpgv1G7nwggwKDVagRpxEJrwwyh6", + amount=50000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises( + TrezorFailure, match="Multisig field provided but not expected." + ): + btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TxCache("Testnet") + ) diff --git a/tests/device_tests/test_msg_signtx_bgold.py b/tests/device_tests/test_msg_signtx_bgold.py index 60b26bf80..ce01ee702 100644 --- a/tests/device_tests/test_msg_signtx_bgold.py +++ b/tests/device_tests/test_msg_signtx_bgold.py @@ -577,3 +577,40 @@ class TestMsgSigntxBitcoinGold: serialized_tx.hex() == "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250100000023220020ea9ec48498c451286c2ebaf9e19255e2873b0fb517d67b2f2005298c7e437829ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400473044022077cb8b2a534f79328810ca8c330539ae9ffa086c359ddb7da11026557b04eef202201d95be0dd1da0aa01720953e52d5dabffd19a998d1490c13a21b8e52e4ead2e041483045022100e41cbd6a501ba8fe6f65554420e23e950d35af0da9b052da54a087463b0717ca02206c695c8d1f74f9535b5d89a2fd1f9326a0ef20e5400137f1e1daeee992b62b594169522103279aea0b253b144d1b2bb8532280001a996dcddd04f86e5e13df1355032cbc1321032c6465c956c0879663fa8be974c912d229c179a5cdedeb29611a1bec1f951eb22103494480a4b72101cbd2eadac8e18c7a3a7589a7f576bf46b8971c38c51e5eceeb53ae00000000" ) + + def test_send_mixed_inputs(self, client): + # First is non-segwit, second is segwit. + + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/0'/0/0"), + amount=31000000, + prev_hash=bytes.fromhex( + "e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd" + ), + prev_index=0, + ) + + inp2 = proto.TxInputType( + address_n=parse_path("84'/156'/0'/1/0"), + amount=7289000, + prev_hash=bytes.fromhex( + "65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b" + ), + prev_index=1, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=31000000 + 7289000 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "01000000000102cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a473044022061e94392fa4c0a4bf510bf713c23a37c6c5f6f4dbe5c116e86cff23a93c578e9022026661d2ffb1102d07b7c1631270152441fa171d91108b75a7b9a2cc36ca7db6c4121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff01803a4802000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0002483045022100e39d9bff8350b9ba20cb2ed88e82d7568a83184616acdc16bd1adb4005c5a471022066ff36084e896a69a91a0fad01721f20f2bb42b41e20be35e72fc3729ac7ace74121030b75ccac9add5f82a4c61fe34e791a2f2eda61b544bce4f6fa3d403bb0de748400000000" + ) diff --git a/tests/device_tests/test_msg_signtx_capricoin.py b/tests/device_tests/test_msg_signtx_capricoin.py deleted file mode 100644 index add801102..000000000 --- a/tests/device_tests/test_msg_signtx_capricoin.py +++ /dev/null @@ -1,69 +0,0 @@ -# This file is part of the Trezor project. -# -# Copyright (C) 2012-2019 SatoshiLabs and contributors -# -# This library is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the License along with this library. -# If not, see . - -import pytest - -from trezorlib import btc, messages -from trezorlib.tools import parse_path - -from ..tx_cache import TxCache - -TXHASH_3bf506 = bytes.fromhex( - "3bf506c81ce84eda891679ddc797d162c17c60b15d6c0ac23be5e31369e7235f" -) - -TXHASH_f3a6e6 = bytes.fromhex( - "f3a6e6411f1b2dffd76d2729bae8e056f8f9ecf8996d3f428e75a6f23f2c5e8c" -) - - -@pytest.mark.altcoin -@pytest.mark.capricoin -@pytest.mark.skip_t1 # T1 support is not planned -def test_timestamp_included(client): - # tx: 3bf506c81ce84eda891679ddc797d162c17c60b15d6c0ac23be5e31369e7235f - # input 0: 0.01 CPC - # tx: f3a6e6411f1b2dffd76d2729bae8e056f8f9ecf8996d3f428e75a6f23f2c5e8c - # input 0: 0.02 CPC - - inp1 = messages.TxInputType( - address_n=parse_path("m/44'/289'/0'/0/0"), prev_hash=TXHASH_3bf506, prev_index=0 - ) - - inp2 = messages.TxInputType( - address_n=parse_path("m/44'/289'/0'/0/0"), prev_hash=TXHASH_f3a6e6, prev_index=1 - ) - - out1 = messages.TxOutputType( - address="CUGi8RGPWxbHM6FxF4eMEfqmQ6Bs5VjCdr", - amount=3000000 - 20000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with client: - details = messages.SignTx(version=1, timestamp=0x5BCF5C66) - _, timestamp_tx = btc.sign_tx( - client, - "Capricoin", - [inp1, inp2], - [out1], - details=details, - prev_txes=TxCache("Capricoin"), - ) - - # Accepted by network https://insight.capricoin.org/tx/1bf227e6e24fe1f8ac98849fe06a2c5b77762e906fcf7e82787675f7f3a10bb8 - accepted_txhex = "01000000665ccf5b025f23e76913e3e53bc20a6c5db1607cc162d197c7dd791689da4ee81cc806f53b000000006b483045022100fce7ccbeb9524f36d118ebcfebcb133a05c236c4478e2051cfd5c9632920aee602206921b7be1a81f30cce3d8e7dba4597fc16a2761c42321c49d65eeacdfe3781250121021fcf98aee04939ec7df5762f426dc2d1db8026e3a73c3bbe44749dacfbb61230ffffffff8c5e2c3ff2a6758e423f6d99f8ecf9f856e0e8ba29276dd7ff2d1b1f41e6a6f3010000006a473044022015d967166fe9f89fbed8747328b1c4658aa1d7163e731c5fd5908feafe08e9a6022028af30801098418bd298cc60b143c52c48466f5791256721304b6eba4fdf0b3c0121021fcf98aee04939ec7df5762f426dc2d1db8026e3a73c3bbe44749dacfbb61230ffffffff01a0782d00000000001976a914818437acfd15780debd31f3fd21d4ca678bb36d188ac00000000" - assert timestamp_tx.hex() == accepted_txhex diff --git a/tests/device_tests/test_msg_signtx_komodo.py b/tests/device_tests/test_msg_signtx_komodo.py index 1381ff2a2..a6e5fb0d9 100644 --- a/tests/device_tests/test_msg_signtx_komodo.py +++ b/tests/device_tests/test_msg_signtx_komodo.py @@ -84,7 +84,6 @@ class TestMsgSigntxKomodo: details = proto.SignTx( version=4, - overwintered=True, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2A30B8, @@ -164,7 +163,6 @@ class TestMsgSigntxKomodo: details = proto.SignTx( version=4, - overwintered=True, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2AF1F2, diff --git a/tests/device_tests/test_msg_signtx_peercoin.py b/tests/device_tests/test_msg_signtx_peercoin.py index 16b512b71..edd23e930 100644 --- a/tests/device_tests/test_msg_signtx_peercoin.py +++ b/tests/device_tests/test_msg_signtx_peercoin.py @@ -17,10 +17,13 @@ import pytest from trezorlib import btc, messages +from trezorlib.exceptions import TrezorFailure from trezorlib.tools import parse_path from ..tx_cache import TxCache +TX_CACHE = TxCache("Peercoin") + TXHASH_41b29a = bytes.fromhex( "41b29ad615d8eea40a4654a052d18bb10cd08f203c351f4d241f88b031357d3d" ) @@ -42,17 +45,76 @@ def test_timestamp_included(client): script_type=messages.OutputScriptType.PAYTOADDRESS, ) - with client: - details = messages.SignTx(version=1, timestamp=0x5DC5448A) - _, timestamp_tx = btc.sign_tx( + details = messages.SignTx(version=1, timestamp=0x5DC5448A) + _, timestamp_tx = btc.sign_tx( + client, "Peercoin", [inp1], [out1], details=details, prev_txes=TX_CACHE, + ) + + # Accepted by network https://explorer.peercoin.net/api/getrawtransaction?txid=f7e3624c143b6a170cc44f9337d0fa8ea8564a211de9c077c6889d8c78f80909&decrypt=1 + accepted_txhex = "010000008a44c55d013d7d3531b0881f244d1f353c208fd00cb18bd152a054460aa4eed815d69ab241000000006a473044022025c0ea702390c702c7ae8b5ea469820bea8d942c8c16439f8f0ba2e91e699efc02200db9b0a48fa2861695fa91df4831a4c7306587e5d2dc85419647f462717bc8f001210274cb0ee652d9457fbb0f3872d43155a6bc16f77bd5749d8826b53db443b1b278ffffffff01905f0100000000001976a914ff9a05654150fdc92b1655f49d7f2a8aaf6a3a2a88ac00000000" + assert timestamp_tx.hex() == accepted_txhex + + +@pytest.mark.altcoin +@pytest.mark.peercoin +@pytest.mark.skip_ui +def test_timestamp_missing(client): + inp1 = messages.TxInputType( + address_n=parse_path("m/44'/6'/0'/0/0"), prev_hash=TXHASH_41b29a, prev_index=0 + ) + out1 = messages.TxOutputType( + address="PXtfyTjzgXSgTwK5AbszdHQSSxyQN3BLM5", + amount=100000 - 10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + details = messages.SignTx(version=1, timestamp=None) + with pytest.raises(TrezorFailure, match="Timestamp must be set."): + btc.sign_tx( + client, "Peercoin", [inp1], [out1], details=details, prev_txes=TX_CACHE, + ) + + details = messages.SignTx(version=1, timestamp=0) + with pytest.raises(TrezorFailure, match="Timestamp must be set."): + btc.sign_tx( + client, "Peercoin", [inp1], [out1], details=details, prev_txes=TX_CACHE, + ) + + +@pytest.mark.altcoin +@pytest.mark.peercoin +@pytest.mark.skip_ui +def test_timestamp_missing_prevtx(client): + inp1 = messages.TxInputType( + address_n=parse_path("m/44'/6'/0'/0/0"), prev_hash=TXHASH_41b29a, prev_index=0 + ) + out1 = messages.TxOutputType( + address="PXtfyTjzgXSgTwK5AbszdHQSSxyQN3BLM5", + amount=100000 - 10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + details = messages.SignTx(version=1, timestamp=0x5DC5448A) + + prevtx = TX_CACHE[TXHASH_41b29a] + prevtx.timestamp = 0 + + with pytest.raises(TrezorFailure, match="Timestamp must be set."): + btc.sign_tx( client, "Peercoin", [inp1], [out1], details=details, - prev_txes=TxCache("Peercoin"), + prev_txes={TXHASH_41b29a: prevtx}, ) - # Accepted by network https://explorer.peercoin.net/api/getrawtransaction?txid=f7e3624c143b6a170cc44f9337d0fa8ea8564a211de9c077c6889d8c78f80909&decrypt=1 - accepted_txhex = "010000008a44c55d013d7d3531b0881f244d1f353c208fd00cb18bd152a054460aa4eed815d69ab241000000006a473044022025c0ea702390c702c7ae8b5ea469820bea8d942c8c16439f8f0ba2e91e699efc02200db9b0a48fa2861695fa91df4831a4c7306587e5d2dc85419647f462717bc8f001210274cb0ee652d9457fbb0f3872d43155a6bc16f77bd5749d8826b53db443b1b278ffffffff01905f0100000000001976a914ff9a05654150fdc92b1655f49d7f2a8aaf6a3a2a88ac00000000" - assert timestamp_tx.hex() == accepted_txhex + prevtx.timestamp = None + with pytest.raises(TrezorFailure, match="Timestamp must be set."): + btc.sign_tx( + client, + "Peercoin", + [inp1], + [out1], + details=details, + prev_txes={TXHASH_41b29a: prevtx}, + ) diff --git a/tests/device_tests/test_msg_signtx_prevhash.py b/tests/device_tests/test_msg_signtx_prevhash.py new file mode 100644 index 000000000..17e3c9b6f --- /dev/null +++ b/tests/device_tests/test_msg_signtx_prevhash.py @@ -0,0 +1,165 @@ +from hashlib import sha256 +from io import BytesIO + +import pytest + +from trezorlib import btc, messages +from trezorlib.exceptions import TrezorFailure + +from ..tx_cache import TxCache + +TXHASH_157041 = bytes.fromhex( + "1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6" +) + + +def write_prefixed_bytes(io, data) -> None: + assert len(data) < 253 + io.write(len(data).to_bytes(1, "little")) + io.write(data) + + +def serialize_input(tx_input) -> bytes: + """serialize for Bitcoin tx format""" + b = BytesIO() + if tx_input.prev_hash: + b.write(tx_input.prev_hash[::-1]) + b.write(tx_input.prev_index.to_bytes(4, "little")) + write_prefixed_bytes(b, tx_input.script_sig) + b.write(tx_input.sequence.to_bytes(4, "little")) + return b.getvalue() + + +def serialize_bin_output(tx_output) -> bytes: + b = BytesIO() + b.write(tx_output.amount.to_bytes(8, "little")) + write_prefixed_bytes(b, tx_output.script_pubkey) + return b.getvalue() + + +def serialize_tx(tx) -> bytes: + b = BytesIO() + b.write(tx.version.to_bytes(4, "little")) + assert len(tx.inputs) < 253 + b.write(len(tx.inputs).to_bytes(1, "little")) + for inp in tx.inputs: + b.write(serialize_input(inp)) + assert len(tx.bin_outputs) < 253 + b.write(len(tx.bin_outputs).to_bytes(1, "little")) + for outp in tx.bin_outputs: + b.write(serialize_bin_output(outp)) + lock_time = tx.lock_time or 0 + b.write(lock_time.to_bytes(4, "little")) + if tx.extra_data: + b.write(tx.extra_data) + return b.getvalue() + + +def hash_tx(data: bytes) -> bytes: + return sha256(sha256(data).digest()).digest()[::-1] + + +def _check_error_message(value: bytes, model: str, message: str): + if model != "1": + assert message == "Provided prev_hash is invalid." + return + + # T1 has several possible errors + if value is None: + assert message.endswith("missing required field") + elif len(value) > 32: + assert message.endswith("bytes overflow") + else: + assert message.endswith("Encountered invalid prevhash") + + +@pytest.mark.skip_ui +@pytest.mark.parametrize("prev_hash", (None, b"", b"x", b"hello world", b"x" * 33)) +def test_invalid_prev_hash(client, prev_hash): + inp1 = messages.TxInputType( + address_n=[0], + amount=123456789, + prev_hash=prev_hash, + prev_index=0, + script_type=messages.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = messages.TxOutputType( + address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", + amount=12300000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises(TrezorFailure) as e: + btc.sign_tx(client, "Testnet", [inp1], [out1]) + _check_error_message(prev_hash, client.features.model, e.value.message) + + +@pytest.mark.skip_ui +@pytest.mark.parametrize("prev_hash", (None, b"", b"x", b"hello world", b"x" * 33)) +def test_invalid_prev_hash_attack(client, prev_hash): + # prepare input with a valid prev-hash + inp1 = messages.TxInputType( + address_n=[0], + amount=123456789, + prev_hash=b"\x00" * 32, + prev_index=0, + script_type=messages.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = messages.TxOutputType( + address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", + amount=12300000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + counter = 1 + + def attack_filter(msg): + nonlocal counter + + if not msg.tx.inputs: + return msg + + # on first attempt, send unmodified input + if counter > 0: + counter -= 1 + return msg + + # on second request, send modified input + msg.tx.inputs[0].prev_hash = prev_hash + return msg + + with client, pytest.raises(TrezorFailure) as e: + client.set_filter(messages.TxAck, attack_filter) + btc.sign_tx(client, "Testnet", [inp1], [out1]) + + # check that injection was performed + assert counter == 0 + _check_error_message(prev_hash, client.features.model, e.value.message) + + +@pytest.mark.skip_ui +@pytest.mark.parametrize("prev_hash", (None, b"", b"x", b"hello world", b"x" * 33)) +def test_invalid_prev_hash_in_prevtx(client, prev_hash): + cache = TxCache("Bitcoin") + prev_tx = cache[TXHASH_157041] + + # smoke check: replace prev_hash with all zeros, reserialize and hash, try to sign + prev_tx.inputs[0].prev_hash = b"\x00" * 32 + tx_hash = hash_tx(serialize_tx(prev_tx)) + + inp0 = messages.TxInputType(address_n=[0], prev_hash=tx_hash, prev_index=0) + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=1000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + btc.sign_tx(client, "Bitcoin", [inp0], [out1], prev_txes={tx_hash: prev_tx}) + + # attack: replace prev_hash with an invalid value + prev_tx.inputs[0].prev_hash = prev_hash + tx_hash = hash_tx(serialize_tx(prev_tx)) + inp0.prev_hash = tx_hash + + with pytest.raises(TrezorFailure) as e: + btc.sign_tx(client, "Bitcoin", [inp0], [out1], prev_txes={tx_hash: prev_tx}) + _check_error_message(prev_hash, client.features.model, e.value.message) diff --git a/tests/device_tests/test_msg_signtx_segwit_native.py b/tests/device_tests/test_msg_signtx_segwit_native.py index 1d5332125..1d2e3e4fb 100644 --- a/tests/device_tests/test_msg_signtx_segwit_native.py +++ b/tests/device_tests/test_msg_signtx_segwit_native.py @@ -395,6 +395,43 @@ class TestMsgSigntxSegwitNative: == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac02483045022100ead79ee134f25bb585b48aee6284a4bb14e07f03cc130253e83450d095515e5202201e161e9402c8b26b666f2b67e5b668a404ef7e57858ae9a6a68c3837e65fdc69012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7902463043021f585c54a84dc7326fa60e22729accd41153c7dd4725bd4c8f751aa3a8cd8d6a0220631bfd83fc312cc6d5d129572a25178696d81eaf50c8c3f16c6121be4f4c029d012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" ) + def test_send_mixed_inputs(self, client): + # First is non-segwit, second is segwit. + + inp1 = proto.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + # amount=31000000, + prev_hash=bytes.fromhex( + "e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd" + ), + prev_index=0, + ) + + inp2 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/1/0"), + amount=7289000, + prev_hash=bytes.fromhex( + "65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b" + ), + prev_index=1, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc", + amount=31000000 + 7289000 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1, inp2], [out1], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "01000000000102cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006b483045022100b9b1002dfaa8aa6e658e37726dc526f145bac3715a933d40f8dacadff2cede560220197691c6bfc55ff260f5a48e9e94d9db73aff0400d79600f8ca63b7c0c7b37010121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff01803a480200000000160014a579388225827d9f2fe9014add644487808c695d0002473044022013dd59fb2e22da981a528b155e25e3ce360001c275408ea649b34cd51b509e68022030febb79bbb3e75263cdb68d9b9e08ab0ebe85d1986eb4fa5ce2f668b40a2a2c012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" + ) + @pytest.mark.multisig def test_send_multisig_1(self, client): nodes = [ @@ -810,3 +847,119 @@ class TestMsgSigntxSegwitNative: serialized_tx.hex() == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000" ) + + # Ensure that if there is a non-multisig input, then a multisig output + # will not be identified as a change output. + def test_multisig_mismatch_inputs_single(self, client): + # m/84'/1'/0' for "alcohol woman abuse ..." seed. + node_int = deserialize( + "Vpub5kFDCYhiYuAzjk7TBQPNFffbexHF7iAd8AVVgHQKUany7e6NQvthgk86d7DfH57DY2dwBK4PyVTDDaS1r2gjkdyJyUYGoV9qNujGSrW9Dpe" + ) + + # m/84'/1'/0' for "all all ... all" seed. + node_ext = deserialize( + "Vpub5jR76XyyhBaQXPSRf3PBeY3gF914d9sf7DWFVhMESEQMCdNv35XiVvp8gZsFXAv222VPHLNnAEXxMPG8DPiSuhAXfEydBf55LTLBGHCDzH2" + ) + + # tb1qpzmgzpcumztvmpu3q27wwdggqav26j9dgks92pvnne2lz9ferxgssmhzlq + multisig_in = proto.MultisigRedeemScriptType( + nodes=[node_int, node_ext], address_n=[0, 0], signatures=[b"", b""], m=1 + ) + + multisig_out = proto.MultisigRedeemScriptType( + nodes=[node_int, node_ext], address_n=[1, 0], signatures=[b"", b""], m=1 + ) + + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=bytes.fromhex( + "09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a" + ), + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + + inp2 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + prev_hash=bytes.fromhex( + "a345b85759b385c6446055e4c3baa77e8161a65009dc009489b48aa6587ce348" + ), + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + multisig=multisig_in, + amount=100, + ) + + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + address_n=parse_path("84'/1'/0'/1/0"), + script_type=proto.OutputScriptType.PAYTOWITNESS, + multisig=multisig_out, + amount=12300000 + 100 - 5000000 - 10000, + ) + + with client: + client.set_expected_responses( + [ + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + # Ensure that the multisig output is not identified as a change output. + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.TxRequest(request_type=proto.RequestType.TXFINISHED), + ] + ) + + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff48e37c58a68ab4899400dc0950a661817ea7bac3e4556044c685b35957b845a30000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987f43c6f0000000000220020733ecfbbe7e47a74dde6c7645b60cdf627e90a585cde7733bc7fdaf9fe30b37402473044022037dc98b16be542a6e3e1ab32007a74192c43f2498170cc5e1dffb6847e3663e402206715102d0eb59e6461a97c78eb40a8679a04a8921fdafef25f0d3d16cc65de39012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f8620300473044022070a24bcb00041cbed465f1f546bc59e1e353a6e182393932d5ba96e20bc32ef702202ddc76a97c01465692d5b0a0a61d653f64b9ea833af1810022110fd4d505ff950147512103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d2103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86252ae00000000" + ) diff --git a/tests/device_tests/test_msg_signtx_zcash.py b/tests/device_tests/test_msg_signtx_zcash.py index 216cd4522..ee2cb85bc 100644 --- a/tests/device_tests/test_msg_signtx_zcash.py +++ b/tests/device_tests/test_msg_signtx_zcash.py @@ -78,10 +78,7 @@ class TestMsgSigntxZcash: ) details = proto.SignTx( - version=3, - overwintered=True, - version_group_id=0x03C48270, - branch_id=0x5BA81B19, + version=3, version_group_id=0x03C48270, branch_id=0x5BA81B19, ) _, serialized_tx = btc.sign_tx( client, @@ -142,10 +139,7 @@ class TestMsgSigntxZcash: ) details = proto.SignTx( - version=4, - overwintered=True, - version_group_id=0x892F2085, - branch_id=0x76B809BB, + version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, ) _, serialized_tx = btc.sign_tx( client, diff --git a/tests/device_tests/test_multisig.py b/tests/device_tests/test_multisig.py index d32d344d9..2fbc557d1 100644 --- a/tests/device_tests/test_multisig.py +++ b/tests/device_tests/test_multisig.py @@ -300,3 +300,128 @@ class TestMultisig: with pytest.raises(TrezorFailure, match="Pubkey not found in multisig script"): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) + + def test_attack_change_input(self, client): + """ + In Phases 1 and 2 the attacker replaces a non-multisig input + `input_real` with a multisig input `input_fake`, which allows the + attacker to provide a 1-of-2 multisig change address. When `input_real` + is provided in the signing phase, an error must occur. + """ + address_n = parse_path("48'/1'/0'/0/0") + attacker_multisig_public_key = bytes.fromhex( + "03653a148b68584acb97947344a7d4fd6a6f8b8485cad12987ff8edac874268088" + ) + + input_real = proto.TxInputType( + address_n=address_n, + prev_hash=bytes.fromhex( + "fbbff7f3c85f8067453d7c062bd5efb8ad839953376ae5eceaf92774102c6e39" + ), + prev_index=1, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + amount=1000000, + ) + + multisig_fake = proto.MultisigRedeemScriptType( + m=1, + nodes=[ + btc.get_public_node(client, address_n).node, + proto.HDNodeType( + depth=0, + fingerprint=0, + child_num=0, + chain_code=bytes(32), + public_key=attacker_multisig_public_key, + ), + ], + address_n=[], + ) + + input_fake = proto.TxInputType( + address_n=address_n, + prev_hash=input_real.prev_hash, + prev_index=input_real.prev_index, + script_type=input_real.script_type, + multisig=multisig_fake, + amount=input_real.amount, + ) + + output_payee = proto.TxOutputType( + address="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi", + amount=1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + output_change = proto.TxOutputType( + address_n=address_n, + amount=input_real.amount - output_payee.amount - 1000, + script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, + multisig=multisig_fake, + ) + + attack_count = 2 + + def attack_processor(msg): + nonlocal attack_count + # replace the first input_real with input_fake + if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == input_real: + msg.tx.inputs[0] = input_fake + attack_count -= 1 + return msg + + client.set_filter(proto.TxAck, attack_processor) + with client: + client.set_expected_responses( + [ + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + # serialized_tx: 01000000000101396e2c107427f9eaece56a37539983adb8efd52b067c3d4567805fc8f3f7bffb01000000232200200b5eada0e3bd4e52b831d6a14553e6f73a4387f1d3a19466af2850dedd74374effffffff + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + # serialized_tx: 02e8030000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=1), + ), + proto.TxRequest( + # serialized_tx: 703a0f000000000017a914a1261837f1b40e84346b1504ffe294e402965f2687 + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.Failure(code=proto.FailureType.ProcessError), + ] + ) + + with pytest.raises(TrezorFailure) as exc: + btc.sign_tx( + client, "Testnet", [input_real], [output_payee, output_change] + ) + # must not produce this tx: + # 01000000000101396e2c107427f9eaece56a37539983adb8efd52b067c3d4567805fc8f3f7bffb01000000171600147a876a07b366f79000b441335f2907f777a0280bffffffff02e8030000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac703a0f000000000017a914a1261837f1b40e84346b1504ffe294e402965f2687024830450221009ff835e861be4e36ca1f2b6224aee2f253dfb9f456b13e4b1724bb4aaff4c9c802205e10679c2ead85743119f468cba5661f68b7da84dd2d477a7215fef98516f1f9012102af12ddd0d55e4fa2fcd084148eaf5b0b641320d0431d63d1e9a90f3cbd0d540700000000 + + assert exc.value.code == proto.FailureType.ProcessError + if client.features.model == "1": + assert exc.value.message.endswith("Failed to compile input") + else: + assert exc.value.message.endswith( + "Transaction has changed during signing" + ) diff --git a/tests/device_tests/test_op_return.py b/tests/device_tests/test_op_return.py index 21c288845..2f631b4f6 100644 --- a/tests/device_tests/test_op_return.py +++ b/tests/device_tests/test_op_return.py @@ -119,6 +119,7 @@ class TestOpReturn: == "010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100bc36e1227b334e856c532bbef86d30a96823a5f2461738f4dbf969dfbcf1b40b022078c5353ec9a4bce2bb05bd1ec466f2ab379c1aad926e208738407bba4e09784b012103330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882ffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000" ) + @pytest.mark.skip_ui def test_nonzero_opreturn(self, client): inp1 = proto.TxInputType( address_n=parse_path("44'/0'/10'/0/5"), @@ -169,14 +170,63 @@ class TestOpReturn: ] ) - with pytest.raises(TrezorFailure) as exc: + with pytest.raises( + TrezorFailure, match="OP_RETURN output with non-zero amount" + ): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) - if client.features.model == "1": - assert exc.value.code == proto.FailureType.ProcessError - assert exc.value.message.endswith("Failed to compile output") - else: - assert exc.value.code == proto.FailureType.DataError - assert exc.value.message.endswith( - "OP_RETURN output with non-zero amount" + @pytest.mark.skip_ui + def test_opreturn_address(self, client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/0'/0'/0/2"), prev_hash=TXHASH_d5f65e, prev_index=0 + ) + + out1 = proto.TxOutputType( + address_n=parse_path("44'/0'/0'/1/2"), + amount=0, + op_return_data=b"OMNI TRANSACTION GOES HERE", + script_type=proto.OutputScriptType.PAYTOOPRETURN, + ) + + with client: + client.set_expected_responses( + [ + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.TxRequest( + request_type=proto.RequestType.TXMETA, + details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType( + request_index=0, tx_hash=TXHASH_d5f65e + ), + ), + proto.TxRequest( + request_type=proto.RequestType.TXINPUT, + details=proto.TxRequestDetailsType( + request_index=1, tx_hash=TXHASH_d5f65e + ), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType( + request_index=0, tx_hash=TXHASH_d5f65e + ), + ), + proto.TxRequest( + request_type=proto.RequestType.TXOUTPUT, + details=proto.TxRequestDetailsType(request_index=0), + ), + proto.Failure(), + ] + ) + with pytest.raises( + TrezorFailure, match="Output's address_n provided but not expected." + ): + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1], prev_txes=TX_API ) diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 2f4a0e838..3dd644d95 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -9,9 +9,9 @@ "test_cancel.py::test_cancel_message_via_initialize[message1]": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586", "test_msg_applysettings.py-test_apply_settings": "b698654871541258f97d58ada0f010b2d77b74829791566746cad619d3740a94", "test_msg_applysettings.py-test_apply_settings_passphrase": "fb38537b921f8064f7ea6e1a584e70a8be74968a3be6726b7d36cf57de0d7865", -"test_msg_backup_device.py::test_backup_bip39": "ff34ef60d2bbb92fc4e4ab00a1e4f9c2c7884e3186bb6861398f74dd3e05e3cf", -"test_msg_backup_device.py::test_backup_slip39_advanced": "edfccb742254ab1c5945c27f0c70926c2a4adb6fff4df0ed561bd58b05043034", -"test_msg_backup_device.py::test_backup_slip39_basic": "ca04ca33f05b5b0f3c762f0cad293a376e056e43a28ce94ffb77b36d491cbc1f", +"test_msg_backup_device.py::test_backup_bip39": "749f543f21fe0005ef43b00e23162cf68522d1460cee5cc77d933324e85b5ded", +"test_msg_backup_device.py::test_backup_slip39_advanced": "efb31ae0ed0565d0c044e0aeabe3d32a524e99155d50d6b72100627c68a1d472", +"test_msg_backup_device.py::test_backup_slip39_basic": "ffef65aa4bb5f265644a5df0063542c3f261f815db65914893a690760d0d0b6a", "test_msg_backup_device.py::test_interrupt_backup_fails": "225b3da1acac6e9a65106fcc4a01de8a44de035aedb4dcc21c09f439199fdf40", "test_msg_backup_device.py::test_no_backup_fails": "93039a9472cfc9058563bd56e4a3dbe2e41af64744a61f6ee3255a04bd3a9366", "test_msg_backup_device.py::test_no_backup_show_entropy_fails": "14fcdd2ded299ca099a35966cc9f21204b31de8d6bab9ec91cb64537bd70440c", @@ -219,11 +219,11 @@ "test_msg_recoverydevice_slip39_basic_dryrun.py::test_2of3_invalid_seed_dryrun": "55f2dd6b4958659f071c3f57e06286f872ac38af4828f446a0f4e91c657dfccc", "test_msg_resetdevice_bip39_t2.py-test_already_initialized": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586", "test_msg_resetdevice_bip39_t2.py-test_failed_pin": "f284b630fef6ae437c9726cd0ee0d1728a77f677f37cd5f88aabb21e596f589e", -"test_msg_resetdevice_bip39_t2.py-test_reset_device": "aaa37f33897fbdf33858a9cbb8982be1b1c1d1e2cbff83ebfd4c49fa8fc4b342", +"test_msg_resetdevice_bip39_t2.py-test_reset_device": "c5fc35eab68889c0b3315cad09afd573ce32c1e94c2cb942388638414145f631", "test_msg_resetdevice_bip39_t2.py-test_reset_device_192": "febbacc3370cf9219faa49bbc542a7aa1280d9fc3e6e9776dacbcd2f09231636", -"test_msg_resetdevice_bip39_t2.py-test_reset_device_pin": "dd95b1f1e7b496828314a4baf77f5f9f3aa54fc11754236e35f7519da9fd44c8", -"test_msg_resetdevice_slip39_advanced.py-test_reset_device_slip39_advanced": "b1ca19a20f4d2be96847c8d2373921a68c5c9bd1292790229c64f93a0319cb69", -"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic": "77e9d45a9fb16a8759478ac1d433bb86ce58c01fa135bc4524596955de20552d", +"test_msg_resetdevice_bip39_t2.py-test_reset_device_pin": "e5957c6790bb3319b90da678949d09bfdd2d641d8d315ffa6b98a316cffeef0c", +"test_msg_resetdevice_slip39_advanced.py-test_reset_device_slip39_advanced": "77fae06d2427b6626debb71448e0b79c81afb99da10df9b9e987259eb045edf2", +"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic": "ad0d71e21112456fa99fdbd36563aa1ccbf49343a94ca1ed74068b2ec04ebd61", "test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic_256": "5f21f628ada58d9b519aec96f99a087df1098825de33421ddb36777dc4f578f1", "test_msg_ripple_get_address.py-test_ripple_get_address": "2bb7d7bf48f1218530b4d7045d48480cad6411e110df537551b2f80b342007f2", "test_msg_ripple_get_address.py-test_ripple_get_address_other": "2bb7d7bf48f1218530b4d7045d48480cad6411e110df537551b2f80b342007f2", @@ -280,10 +280,10 @@ "test_msg_signtx_bgold.py-test_send_bitcoin_gold_change": "de2fe54950938864480fd40866db18a73565fdc9de2f7867ab7e0a8ae7f65ce4", "test_msg_signtx_bgold.py-test_send_bitcoin_gold_nochange": "65a3fa31182748333a44e8cedcee653d7532428126d6df1ef3514424adcb10f1", "test_msg_signtx_bgold.py-test_send_btg_multisig_change": "4ed4962fa425498e4d7ae158d1233b01319dfa071edcb2d71f2f4d4e57c4b4fd", +"test_msg_signtx_bgold.py-test_send_mixed_inputs": "ed137c7c45d1bd9f2e73b4ca6ea0eff63b601e8ad73d79a90aefd2046e2d51b2", "test_msg_signtx_bgold.py-test_send_multisig_1": "d049b3b25042c732ce26a253e7de49581adc83003713860924b8d951cb46de0c", "test_msg_signtx_bgold.py-test_send_p2sh": "ddd48151ce1d74ade0b9858cbcdba316581991ec92c2ef54b5893e3aae75f995", "test_msg_signtx_bgold.py-test_send_p2sh_witness_change": "02e44d4c1072eb774486210f885b1bee53acfb3b7fd787207b9f955853fef055", -"test_msg_signtx_capricoin.py::test_timestamp_included": "15052cadcea92d3405ba0f603c1a5c54bc4fe60eb0b89c79b062620023c3444b", "test_msg_signtx_dash.py-test_send_dash": "291f1a3ace22877641494a1a470a1a4a8dab6e363fc4402dadaeb52c1288c72b", "test_msg_signtx_dash.py-test_send_dash_dip2_input": "cf7fc7e6fe3a9e4063e743da6fc44c27dac013917bc00cfc63d13a183c091d91", "test_msg_signtx_decred.py-test_decred_multisig_change": "9a7e9e1adcb0ba6770e3965df8324f2b7bc46d6bcd866db9289e8e1d62ef486e", @@ -303,7 +303,9 @@ "test_msg_signtx_segwit.py-test_send_p2sh": "ca593e31e919b9e920289b13e4c70b9607f34b93d06ace69835e3d08ecf046c8", "test_msg_signtx_segwit.py-test_send_p2sh_change": "562c7ee5a2e264c9f93387dd165403dab32bb305a4c3a6143a902c4a4c9e5950", "test_msg_signtx_segwit.py-test_testnet_segwit_big_amount": "5613c0c8852b3e79db9e90d2185ff5802e88869c51b3134a7f8463df47f17a02", +"test_msg_signtx_segwit_native.py-test_multisig_mismatch_inputs_single": "5094082bedf105f2fb6f116ea0348171ae01a51a63d3771c04cfb6c58d44a230", "test_msg_signtx_segwit_native.py-test_send_both": "0b6e01818e71c22ca40c9401c616582b95c8435ff0cd5b74d083332eeeac0b51", +"test_msg_signtx_segwit_native.py-test_send_mixed_inputs": "d72acb396bbc3109054919bddc823e8900bb30b6c41c553922beb449af9bb51d", "test_msg_signtx_segwit_native.py-test_send_multisig_1": "f728159a10dd938b861e5e766319223b6aa7384c1be7edb5bdef12bd80159b9b", "test_msg_signtx_segwit_native.py-test_send_multisig_2": "30b2c9ef9f520d6098c6649b2a06263011bc8c0c0118bda637abca73f5a599ac", "test_msg_signtx_segwit_native.py-test_send_multisig_3_change": "a8b228c8dec41f1bb1ca7ee45b5a979a8b66fc03648c7324c989255a1d5cc01e", @@ -361,6 +363,7 @@ "test_msg_wipedevice.py-test_wipe_device": "400dde1df31b10a4fcacc95a0f7a27f34c41a5f12ad5b7f253ec7e2ff38f0c41", "test_multisig.py-test_15_of_15": "b606b4e715f736e1e562747289a87624e93782f56ca36e90b4ef9bb4300b8d6d", "test_multisig.py-test_2_of_3": "2be92556edf4ff8eed340d535f379ee6915eae34fef25d669ce865848e7b4705", +"test_multisig.py-test_attack_change_input": "89859fea184df09ce96df5281d405c0e85c87ba7efbafa4b3fdf7d9402c0fc44", "test_multisig.py-test_missing_pubkey": "dfd9bdb063329cbc7fae8984a4ec4e4e1f700732e95429ff6a64ae912bacea8d", "test_multisig_change.py-test_external_external": "0f9bc8153070c4bad85bf7ae9d1d30843752538b4d1f8964bc748015a07f00bc", "test_multisig_change.py-test_external_internal": "f60554e040d8965b8f3efdf9eea1f940b64b5844f12d1ee802abbec8d15ea9bf", @@ -370,18 +373,17 @@ "test_multisig_change.py-test_multisig_external_external": "ddecdadd659b0d1360a6a255c6f9dbf2c5b813039877b76d4062ddab765e1912", "test_multisig_change.py-test_multisig_mismatch_change": "7cb243b20be31a587dced4aaaf782a2d8487595369dde66aacb1b9a76e89c4fe", "test_multisig_change.py-test_multisig_mismatch_inputs": "64741bd84c5394e719125c1fbe8c34ef866ac63ca24ee1299e4268c59a199466", -"test_op_return.py-test_nonzero_opreturn": "826099ec3e22bd113fac1bc6f4b22e362673a730ad6838a8894b52541837141c", "test_op_return.py-test_opreturn": "87907ef9c2f4ce30ac95ad7d0cb3eac66762756e4ace52147bc589d64277f3b1", "test_passphrase_slip39_advanced.py::test_128bit_passphrase": "69b6b8b22c819e1282d7d2c14b31bf8d015c81ac05fe034540dbb11c8a20dbdb", "test_passphrase_slip39_advanced.py::test_256bit_passphrase": "69b6b8b22c819e1282d7d2c14b31bf8d015c81ac05fe034540dbb11c8a20dbdb", "test_passphrase_slip39_basic.py::test_2of5_passphrase": "1e00b1a7840bc144b98b7bce26f74fc913a0abf9d1c500571d7803b6b2e0943c", "test_passphrase_slip39_basic.py::test_3of6_passphrase": "1e00b1a7840bc144b98b7bce26f74fc913a0abf9d1c500571d7803b6b2e0943c", -"test_reset_backup.py::test_skip_backup_manual[0-backup_flow_bip39]": "458d09ef5b84b80093f904e9cdd04172b2781ccc303239a077daba586781f186", -"test_reset_backup.py::test_skip_backup_manual[1-backup_flow_slip39_basic]": "ff23780ce790c0f0c53961a94f9faa00873878130cc4ddd4d0a74bebeb4fdcde", -"test_reset_backup.py::test_skip_backup_manual[2-backup_flow_slip39_advanced]": "d43f68e08d989766fd0b75403fa75aea5bf6f746383198ed0bdc55467c5595bd", -"test_reset_backup.py::test_skip_backup_msg[0-backup_flow_bip39]": "718a277f77290cfd28bf16de1fc46b4da13540015ae3d2566472906389d5a69d", -"test_reset_backup.py::test_skip_backup_msg[1-backup_flow_slip39_basic]": "34a27fe6d204808149b2de3c15c04a52f5d2335ef4a43b2468f218dc0cf20102", -"test_reset_backup.py::test_skip_backup_msg[2-backup_flow_slip39_advanced]": "25a4e8a2ca91518b481538c7c9e70e1769f1aa26c85455bfaadf33c47ae185c2", +"test_reset_backup.py::test_skip_backup_manual[0-backup_flow_bip39]": "1002b2e5c75fcd7dc8d421283e2eccb5b747a4014af274ad335b3cff7d27db9d", +"test_reset_backup.py::test_skip_backup_manual[1-backup_flow_slip39_basic]": "c37acfae2609b03bd84f9eb53b0642c73b16cf78300271fc94a6d9a311b144b9", +"test_reset_backup.py::test_skip_backup_manual[2-backup_flow_slip39_advanced]": "26d8bbbdc25f3105f60fd2367fbb765e41ebd42b8545c42fd9398b62233ec363", +"test_reset_backup.py::test_skip_backup_msg[0-backup_flow_bip39]": "6e26d95a67a27f5bb0fc2bb5eaaca01bce3a30e20391ccb5208179edb768b52e", +"test_reset_backup.py::test_skip_backup_msg[1-backup_flow_slip39_basic]": "bea2ebcb056e300f5b8f731af8ee284bf38d3cc725b79d0772fd85f7b09d32bd", +"test_reset_backup.py::test_skip_backup_msg[2-backup_flow_slip39_advanced]": "fd2001fe6960aa7c527266a4030a93bb189435703033cba7337a77c534b87e89", "test_sdcard.py::test_sd_format": "6bb7486932a5d38cdbb9b1368ee92aca3fad384115c744feadfade80c1605dd8", "test_sdcard.py::test_sd_no_format": "f47e897caee95cf98c1b4506732825f853c4b8afcdc2713e38e3b4055973c9ac", "test_sdcard.py::test_sd_protect_unlock": "621294fce5df0a5f381450647b3a45d71696cca0c46bec368a0fea675709956d",