|
|
|
@ -1,12 +1,12 @@
|
|
|
|
|
from common import *
|
|
|
|
|
from trezor.crypto import bip32, bip39
|
|
|
|
|
from trezor.messages.GetAddress import GetAddress
|
|
|
|
|
from trezor.utils import HashWriter
|
|
|
|
|
|
|
|
|
|
from apps.bitcoin.addresses import validate_full_path
|
|
|
|
|
from apps.common.paths import HARDENED
|
|
|
|
|
from apps.common import coins
|
|
|
|
|
from apps.bitcoin import scripts
|
|
|
|
|
from apps.bitcoin.addresses import *
|
|
|
|
|
from apps.bitcoin.keychain import validate_path_against_script_type
|
|
|
|
|
from apps.bitcoin.writers import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -32,17 +32,17 @@ class TestAddress(unittest.TestCase):
|
|
|
|
|
seed = bip39.seed(' '.join(['all'] * 12), '')
|
|
|
|
|
root = bip32.from_seed(seed, 'secp256k1')
|
|
|
|
|
|
|
|
|
|
node = node_derive(root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0])
|
|
|
|
|
node = node_derive(root, [H_(49), H_(1), H_(0), 1, 0])
|
|
|
|
|
address = address_p2wpkh_in_p2sh(node.public_key(), coin)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(address, '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX')
|
|
|
|
|
|
|
|
|
|
node = node_derive(root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 1])
|
|
|
|
|
node = node_derive(root, [H_(49), H_(1), H_(0), 1, 1])
|
|
|
|
|
address = address_p2wpkh_in_p2sh(node.public_key(), coin)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(address, '2NFWLCJQBSpz1oUJwwLpX8ECifFWGznBVqs')
|
|
|
|
|
|
|
|
|
|
node = node_derive(root, [49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0])
|
|
|
|
|
node = node_derive(root, [H_(49), H_(1), H_(0), 0, 0])
|
|
|
|
|
address = address_p2wpkh_in_p2sh(node.public_key(), coin)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(address, '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp')
|
|
|
|
@ -129,96 +129,102 @@ class TestAddress(unittest.TestCase):
|
|
|
|
|
# def test_multisig_address_p2wsh(self):
|
|
|
|
|
# todo couldn't find test data
|
|
|
|
|
|
|
|
|
|
def validate(self, address_n, coin, script_type):
|
|
|
|
|
msg = GetAddress(address_n=address_n, script_type=script_type)
|
|
|
|
|
if script_type == InputScriptType.SPENDMULTISIG:
|
|
|
|
|
msg.multisig = True
|
|
|
|
|
return validate_path_against_script_type(coin, msg)
|
|
|
|
|
|
|
|
|
|
def test_paths_btc(self):
|
|
|
|
|
incorrect_derivation_paths = [
|
|
|
|
|
([49 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # too many HARDENED
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([49 | HARDENED, 123 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid slip44
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 1000 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS), # account too high
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 1 | HARDENED, 2, 0], InputScriptType.SPENDP2SHWITNESS), # invalid y
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 10000000], InputScriptType.SPENDP2SHWITNESS), # address index too high
|
|
|
|
|
([84 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 10000000], InputScriptType.SPENDWITNESS), # address index too high
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 0], InputScriptType.SPENDWITNESS), # invalid input type
|
|
|
|
|
([84 | HARDENED, 0 | HARDENED, 1 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid input type
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 10], InputScriptType.SPENDMULTISIG), # invalid input type
|
|
|
|
|
([H_(49)], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([H_(49), H_(0), H_(0), H_(0), H_(0)], InputScriptType.SPENDP2SHWITNESS), # too many HARDENED
|
|
|
|
|
([H_(49), H_(0)], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([H_(49), H_(0), H_(0), 0, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid length
|
|
|
|
|
([H_(49), H_(123), H_(0), 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid slip44
|
|
|
|
|
([H_(49), H_(0), H_(1000), 0, 0], InputScriptType.SPENDP2SHWITNESS), # account too high
|
|
|
|
|
([H_(49), H_(0), H_(1), 2, 0], InputScriptType.SPENDP2SHWITNESS), # invalid y
|
|
|
|
|
([H_(49), H_(0), H_(1), 0, 10000000], InputScriptType.SPENDP2SHWITNESS), # address index too high
|
|
|
|
|
([H_(84), H_(0), H_(1), 0, 10000000], InputScriptType.SPENDWITNESS), # address index too high
|
|
|
|
|
([H_(49), H_(0), H_(1), 0, 0], InputScriptType.SPENDWITNESS), # invalid input type
|
|
|
|
|
([H_(84), H_(0), H_(1), 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid input type
|
|
|
|
|
([H_(49), H_(0), H_(5), 0, 10], InputScriptType.SPENDMULTISIG), # invalid input type
|
|
|
|
|
]
|
|
|
|
|
correct_derivation_paths = [
|
|
|
|
|
([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS), # btc is segwit coin, but non-segwit paths are allowed as well
|
|
|
|
|
([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 1], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 1123], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 1, 44444], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([49 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([84 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([84 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 0], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([84 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 10], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([48 | HARDENED, 0 | HARDENED, 5 | HARDENED, 0, 10], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([H_(44), H_(0), H_(0), 0, 0], InputScriptType.SPENDADDRESS), # btc is segwit coin, but non-segwit paths are allowed as well
|
|
|
|
|
([H_(44), H_(0), H_(0), 0, 1], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(0), H_(0), 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(49), H_(0), H_(0), 0, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([H_(49), H_(0), H_(0), 1, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([H_(49), H_(0), H_(0), 0, 1123], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([H_(49), H_(0), H_(0), 1, 44444], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([H_(49), H_(0), H_(5), 0, 0], InputScriptType.SPENDP2SHWITNESS),
|
|
|
|
|
([H_(84), H_(0), H_(0), 0, 0], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([H_(84), H_(0), H_(5), 0, 0], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([H_(84), H_(0), H_(5), 0, 10], InputScriptType.SPENDWITNESS),
|
|
|
|
|
([H_(48), H_(0), H_(5), H_(0), 0, 10], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
]
|
|
|
|
|
coin = coins.by_name('Bitcoin')
|
|
|
|
|
|
|
|
|
|
for path, input_type in incorrect_derivation_paths:
|
|
|
|
|
self.assertFalse(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertFalse(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
for path, input_type in correct_derivation_paths:
|
|
|
|
|
self.assertTrue(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertTrue(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
self.assertTrue(validate_full_path([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], coin, InputScriptType.SPENDADDRESS))
|
|
|
|
|
self.assertFalse(validate_full_path([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], coin, InputScriptType.SPENDWITNESS))
|
|
|
|
|
self.assertTrue(validate_full_path([44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0], coin, InputScriptType.SPENDWITNESS, validate_script_type=False))
|
|
|
|
|
self.assertTrue(self.validate([H_(44), H_(0), H_(0), 0, 0], coin, InputScriptType.SPENDADDRESS))
|
|
|
|
|
self.assertFalse(self.validate([H_(44), H_(0), H_(0), 0, 0], coin, InputScriptType.SPENDWITNESS))
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
|
|
|
|
def test_paths_bch(self):
|
|
|
|
|
incorrect_derivation_paths = [
|
|
|
|
|
([44 | HARDENED], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED], InputScriptType.SPENDADDRESS), # too many HARDENED
|
|
|
|
|
([49 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS), # bch is not segwit coin so 49' is not allowed
|
|
|
|
|
([84 | HARDENED, 145 | HARDENED, 1 | HARDENED, 0, 1], InputScriptType.SPENDWITNESS), # and neither is 84'
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([44 | HARDENED, 123 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid slip44
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 1000 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS), # account too high
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 1 | HARDENED, 2, 0], InputScriptType.SPENDADDRESS), # invalid y
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 1 | HARDENED, 0, 10000000], InputScriptType.SPENDADDRESS), # address index too high
|
|
|
|
|
([84 | HARDENED, 145 | HARDENED, 1 | HARDENED, 0, 10000000], InputScriptType.SPENDWITNESS), # address index too high
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDWITNESS), # input type mismatch
|
|
|
|
|
([H_(44)], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([H_(44), H_(145), H_(0), H_(0), H_(0)], InputScriptType.SPENDADDRESS), # too many HARDENED
|
|
|
|
|
([H_(49), H_(145), H_(0), 0, 0], InputScriptType.SPENDP2SHWITNESS), # bch is not segwit coin so 49' is not allowed
|
|
|
|
|
([H_(84), H_(145), H_(1), 0, 1], InputScriptType.SPENDWITNESS), # and neither is 84'
|
|
|
|
|
([H_(44), H_(145)], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([H_(44), H_(145), H_(0), 0, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid length
|
|
|
|
|
([H_(44), H_(123), H_(0), 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid slip44
|
|
|
|
|
([H_(44), H_(145), H_(1000), 0, 0], InputScriptType.SPENDADDRESS), # account too high
|
|
|
|
|
([H_(44), H_(145), H_(1), 2, 0], InputScriptType.SPENDADDRESS), # invalid y
|
|
|
|
|
([H_(44), H_(145), H_(1), 0, 10000000], InputScriptType.SPENDADDRESS), # address index too high
|
|
|
|
|
([H_(84), H_(145), H_(1), 0, 10000000], InputScriptType.SPENDWITNESS), # address index too high
|
|
|
|
|
([H_(44), H_(145), H_(0), 0, 0], InputScriptType.SPENDWITNESS), # input type mismatch
|
|
|
|
|
]
|
|
|
|
|
correct_derivation_paths = [
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 1123], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 1, 44444], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 145 | HARDENED, 5 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([48 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([48 | HARDENED, 145 | HARDENED, 5 | HARDENED, 0, 0], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([48 | HARDENED, 145 | HARDENED, 5 | HARDENED, 0, 10], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([H_(44), H_(145), H_(0), 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(145), H_(0), 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(145), H_(0), 0, 1123], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(145), H_(0), 1, 44444], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(145), H_(5), 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(48), H_(145), H_(0), H_(0), 0, 0], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([H_(48), H_(145), H_(5), H_(0), 0, 0], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
([H_(48), H_(145), H_(5), H_(0), 0, 10], InputScriptType.SPENDMULTISIG),
|
|
|
|
|
]
|
|
|
|
|
coin = coins.by_name('Bcash') # segwit is disabled
|
|
|
|
|
for path, input_type in incorrect_derivation_paths:
|
|
|
|
|
self.assertFalse(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertFalse(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
for path, input_type in correct_derivation_paths:
|
|
|
|
|
self.assertTrue(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertTrue(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
|
|
|
|
def test_paths_other(self):
|
|
|
|
|
incorrect_derivation_paths = [
|
|
|
|
|
([44 | HARDENED, 3 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDMULTISIG), # input type mismatch
|
|
|
|
|
([H_(44), H_(3), H_(0), 0, 0], InputScriptType.SPENDMULTISIG), # input type mismatch
|
|
|
|
|
]
|
|
|
|
|
correct_derivation_paths = [
|
|
|
|
|
([44 | HARDENED, 3 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 3 | HARDENED, 0 | HARDENED, 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 3 | HARDENED, 0 | HARDENED, 0, 1123], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([44 | HARDENED, 3 | HARDENED, 0 | HARDENED, 1, 44444], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(3), H_(0), 0, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(3), H_(0), 1, 0], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(3), H_(0), 0, 1123], InputScriptType.SPENDADDRESS),
|
|
|
|
|
([H_(44), H_(3), H_(0), 1, 44444], InputScriptType.SPENDADDRESS),
|
|
|
|
|
]
|
|
|
|
|
coin = coins.by_name('Dogecoin') # segwit is disabled
|
|
|
|
|
for path, input_type in correct_derivation_paths:
|
|
|
|
|
self.assertTrue(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertTrue(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
for path, input_type in incorrect_derivation_paths:
|
|
|
|
|
self.assertFalse(validate_full_path(path, coin, input_type))
|
|
|
|
|
self.assertFalse(self.validate(path, coin, input_type))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|