Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Convert Mnemonic words back to key data entropy
:param words: Mnemonic words as string of list of words
:type words: str
:param includes_checksum: Boolean to specify if checksum is used. Default is True
:type includes_checksum: bool
:return bytes: Entropy seed
"""
words = self.sanitize_mnemonic(words)
if isinstance(words, TYPE_TEXT):
words = words.split(' ')
wi = []
for word in words:
wi.append(self._wordlist.index(word))
ent = change_base(wi, 2048, 256, output_even=False)
if includes_checksum:
binresult = change_base(ent, 256, 2, len(ent) * 4)
ent = change_base(binresult[:-len(binresult) // 33], 2, 256)
# Check checksum
checksum = binresult[-len(binresult) // 33:]
if checksum != self.checksum(ent):
raise ValueError("Invalid checksum %s for entropy %s" % (checksum, ent))
return ent
:type words: str
:param includes_checksum: Boolean to specify if checksum is used. Default is True
:type includes_checksum: bool
:return bytes: Entropy seed
"""
words = self.sanitize_mnemonic(words)
if isinstance(words, TYPE_TEXT):
words = words.split(' ')
wi = []
for word in words:
wi.append(self._wordlist.index(word))
ent = change_base(wi, 2048, 256, output_even=False)
if includes_checksum:
binresult = change_base(ent, 256, 2, len(ent) * 4)
ent = change_base(binresult[:-len(binresult) // 33], 2, 256)
# Check checksum
checksum = binresult[-len(binresult) // 33:]
if checksum != self.checksum(ent):
raise ValueError("Invalid checksum %s for entropy %s" % (checksum, ent))
return ent
t.block_hash = tx['blockhash']
t.fee = tx['fee']
t.rawtx = tx['hex']
t.size = len(tx['hex']) // 2
t.network = self.network
if t.coinbase:
input_values = []
t.input_total = t.output_total
else:
input_values = [(inp['account'], -inp['value']) for inp in tx['entries'] if inp['value'] < 0]
if len(input_values) >= 49:
raise ClientError("More then 49 transaction inputs not supported by bitgo")
t.input_total = sum([x[1] for x in input_values])
for i in t.inputs:
if not i.address:
raise ClientError("Address missing in input. Provider might not support segwit transactions")
if len(t.inputs) != len(input_values):
i.value = None
continue
value = [x[1] for x in input_values if x[0] == i.address]
if len(value) != 1:
_logger.warning("BitGoClient: Address %s input value should be found exactly 1 times in value list" %
i.address)
i.value = None
else:
i.value = value[0]
for o in t.outputs:
o.spent = None
if t.input_total != t.output_total + t.fee:
t.input_total = t.output_total + t.fee
return t
@staticmethod
def checksum(data):
"""
Calculates checksum for given data key
:param data: key string
:type data: bytes, hexstring
:return str: Checksum of key in bits
"""
data = to_bytes(data)
if len(data) % 4 > 0:
raise ValueError('Data length in bits should be divisible by 32, but it is not (%d bytes = %d bits).' %
(len(data), len(data) * 8))
key_hash = hashlib.sha256(data).digest()
return change_base(key_hash, 256, 2, 256)[:len(data) * 8 // 32]
def test_wallet_import_private_for_known_public_p2sh_segwit(self):
pk1 = HDKey('YXscyqNJ5YK411nwB3VjLYgjht3dqfKxyLdGSqNMGKhYdcK4Gh1CRSJyxS2So8KXSQrxtysS1jAmHtLnxRKa47xEiAx6hP'
'vrj8tuEzyeR8TQNu5e')
pk2 = HDKey('YXscyqNJ5YK411nwB4Jo3JCQ1GZNetf4BrLJjZiqdWKVzoXwPtyJ5xyNdZjuEWtqCeSZGtmg7SuQerERwniHLYL3aVcnyS'
'ciEAxk7gLgDkoZC5Lq')
w = HDWallet.create('segwit-p2sh-p2wsh-import',
[pk1, pk2.public_master(witness_type='p2sh-segwit', multisig=True)],
witness_type='p2sh-segwit', network='bitcoinlib_test', db_uri=self.DATABASE_URI)
w.get_key()
w.utxos_update()
t = w.sweep('23CvEnQKsTVGgqCZzW6ewXPSJH9msFPsBt3')
self.assertEqual(len(t.inputs[0].signatures), 1)
self.assertFalse(t.verify())
w.import_key(pk2)
wc0 = w.cosigner[0]
self.assertEqual(len(wc0.keys(is_private=False)), 0)
t2 = w.send_to('23CvEnQKsTVGgqCZzW6ewXPSJH9msFPsBt3', 1000000)
def test_wallet_single_key_main_key(self):
w = HDWallet.create('multisig_with_single_key', [HDKey().public_master_multisig(), HDKey(key_type='single')],
sigs_required=2, db_uri=self.DATABASE_URI)
w.new_key()
self.assertEqual(len(w.keys_addresses()), 1)
def test_wallet_import_master_key(self):
k = HDKey()
w = HDWallet.create('test_wallet_import_master_key', keys=k.public_master(),
db_uri=self.DATABASE_URI)
self.assertFalse(w.main_key.is_private)
self.assertRaisesRegexp(WalletError, "Please supply a valid private BIP32 master key with key depth 0",
w.import_master_key, k.public())
self.assertRaisesRegexp(WalletError, "Network of Wallet class, main account key and the imported private "
"key must use the same network",
w.import_master_key, HDKey(network='litecoin'))
self.assertRaisesRegexp(WalletError, "This key does not correspond to current public master key",
w.import_master_key, HDKey())
w.import_master_key(k.wif_private())
self.assertTrue(w.main_key.is_private)
k2 = HDKey()
w2 = HDWallet.create('test_wallet_import_master_key2', keys=k2.subkey_for_path("m/32'"), scheme='single',
db_uri=self.DATABASE_URI)
self.assertRaisesRegexp(WalletError, "Main key is already a private key, cannot import key",
w2.import_master_key, k2)
w2.main_key = None
self.assertRaisesRegexp(WalletError, "Main wallet key is not an HDWalletKey instance",
w2.import_master_key, k2)
k3 = HDKey()
w3 = HDWallet.create('test_wallet_import_master_key3', keys=k3.subkey_for_path("m/32'").public(),
def test_wallet_key_import_and_sign_multisig(self):
network = 'bitcoinlib_test'
words = 'square innocent drama'
seed = Mnemonic().to_seed(words, 'password')
hdkey = HDKey.from_seed(seed, network=network)
hdkey.key_type = 'single'
key_list = [
HDKey(network=network, multisig=True).public_master(),
HDKey(network=network),
hdkey.public()
]
with HDWallet.create('Multisig-2-of-3-example', key_list, sigs_required=2,
db_uri=self.DATABASE_URI) as wlt:
wlt.new_key()
wlt.utxos_update()
wt = wlt.send_to('21A6yyUPRL9hZZo1Rw4qP5G6h9idVVLUncE', 10000000)
wt.sign(hdkey)
wt.send()
self.assertIsNone(wt.error)
def test_wallet_transaction_sign_with_wif(self):
wif = 'YXscyqNJ5YK411nwB4eU6PmyGTJkBUHjgXEf53z4TTjHCDXPPXKJD2PyfXonwtT7VwSdqcZJS2oeDbvg531tEsx3yq4425Mfrb9aS' \
'PyNQ5bUGFwu'
wif2 = 'YXscyqNJ5YK411nwB4UK8ScMahPWewyKrTBjgM5BZKRkPg8B2HmKT3r8yc2GFg9GqgFXaWmxkTRhNkRGVxbzUREMH8L5HxoKGCY8' \
'WDdf1GcW2k8q'
w = wallet_create_or_open('test_wallet_transaction_sign_with_wif',
keys=[wif, HDKey(wif2).public_master_multisig(witness_type='segwit')],
witness_type='segwit', network='bitcoinlib_test',
db_uri=self.DATABASE_URI)
w.get_key()
w.utxos_update()
t = w.send_to('blt1q285vnphcs4r0t5dw06tmxl7aryj3jnx88duehv4p7eldsshrmygsmlq84z', 2000, fee=1000)
t.sign(wif2)
self.assertIsNone(t.send())
self.assertTrue(t.pushed)
def test_wallet_segwit_multiple_account_paths(self):
pk1 = HDKey(
"ZprvAhadJRUYsNge9JCXTr7xphZaR6sW3HEeSQL7wgtEXceG5hoUViB9KQ4EX6hAdgziW7MorQAjyasWYirrCQrb3ySHaPBa8EiLTx"
"t4LmqTyzp")
pk2 = HDKey(
"ZprvAhadJRUYsNgeBbjftwKvAhDEV1hrYBGY19wATHqnEt5jfWXxXChYP8Qfnw3w2zJZskNercma5S1fWYH7e7XwbTVPgbabvs1CfU"
"zY2KQD2cB")
w = HDWallet.create("account-test", keys=[pk1, pk2.public_master(multisig=True)], witness_type='segwit',
db_uri=self.DATABASE_URI)
w.new_account()
w.new_account()
w.new_account(account_id=100)
self.assertRaisesRegexp(WalletError, "Account with ID 100 already exists for this wallet",
w.new_account, 'test', 100)
paths = ["m/48'/0'/0'/2'", "m/48'/0'/0'/2'/0/0", "m/48'/0'/0'/2'/1/0", "m/48'/0'/1'/2'", "m/48'/0'/1'/2'/0/0",
"m/48'/0'/1'/2'/1/0", "m/48'/0'/100'/2'", "m/48'/0'/100'/2'/0/0", "m/48'/0'/100'/2'/1/0"]
self.assertListEqual(sorted(paths), sorted([k.path for k in w.keys()]))
self.assertListEqual(w.accounts(), [0, 1, 100])