script hash addresses

This commit is contained in:
Lex Berezhny 2020-09-21 21:46:41 -04:00
parent 62a3022a3d
commit d10a88c79b
5 changed files with 50 additions and 17 deletions

View file

@ -45,15 +45,28 @@ class Ledger:
def get_id(cls):
return '{}_{}'.format(cls.symbol.lower(), cls.network_name.lower())
@classmethod
def hash160_to_address(cls, h160):
raw_address = cls.pubkey_address_prefix + h160
return Base58.encode(bytearray(raw_address + double_sha256(raw_address)[0:4]))
@staticmethod
def address_to_hash160(address) -> bytes:
return Base58.decode(address)[1:21]
@classmethod
def pubkey_hash_to_address(cls, h160):
raw_address = cls.pubkey_address_prefix + h160
return Base58.encode(bytearray(raw_address + double_sha256(raw_address)[0:4]))
@classmethod
def public_key_to_address(cls, public_key):
return cls.pubkey_hash_to_address(hash160(public_key))
@classmethod
def script_hash_to_address(cls, h160):
raw_address = cls.script_address_prefix + h160
return Base58.encode(bytearray(raw_address + double_sha256(raw_address)[0:4]))
@staticmethod
def private_key_to_wif(private_key):
return b'\x1c' + private_key + b'\x01'
@classmethod
def is_valid_address(cls, address):
decoded = Base58.decode_check(address)
@ -133,14 +146,6 @@ class Ledger:
if 'fee_currency' in kwargs or 'fee_amount' in kwargs:
return claim_address
@classmethod
def public_key_to_address(cls, public_key):
return cls.hash160_to_address(hash160(public_key))
@staticmethod
def private_key_to_wif(private_key):
return b'\x1c' + private_key + b'\x01'
class TestNetLedger(Ledger):
network_name = 'testnet'

View file

@ -282,11 +282,14 @@ class Output(InputOutput):
def has_address(self):
return (
'pubkey_hash' in self.script.values or
'script_hash' in self.script.values or
'pubkey' in self.script.values
)
def get_address(self, ledger):
return ledger.hash160_to_address(self.pubkey_hash)
if 'script_hash' in self.script.values:
return ledger.script_hash_to_address(self.script.values['script_hash'])
return ledger.pubkey_hash_to_address(self.pubkey_hash)
@classmethod
def pay_pubkey_hash(cls, amount, pubkey_hash):

View file

@ -334,7 +334,7 @@ class Wallet:
assert txi.txo_ref.txo is not None
txo_script = txi.txo_ref.txo.script
if txo_script.is_pay_pubkey_hash:
address = self.ledger.hash160_to_address(txo_script.values['pubkey_hash'])
address = self.ledger.pubkey_hash_to_address(txo_script.values['pubkey_hash'])
private_key = await self.get_private_key_for_address(address)
assert private_key is not None, 'Cannot find private key for signing output.'
serialized = tx._serialize_for_signature(i)

View file

@ -96,6 +96,10 @@ class TestAccountBalanceImpactFromTransaction(TestCase):
class TestTransactionSerialization(TestCase):
def setUp(self):
super().setUp()
self.ledger = Ledger(Config.with_null_dir())
def test_genesis_transaction(self):
raw = unhexlify(
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1f0"
@ -228,3 +232,24 @@ class TestTransactionSerialization(TestCase):
tx._reset()
self.assertEqual(tx.raw, raw)
def test_pubkey_address(self):
t = Transaction(unhexlify(
"010000000100000000000000000000000000000000000000000000000000000000"
"00000000ffffffff03510101ffffffff0100e1f505000000002321024ca653fc09"
"4c95aa409430caf2eee08fa6e5fbbe78431e0ec9e7cd80193d98f9ac00000000"
))
txo = t.outputs[0]
self.assertEqual(txo.script.template.name, 'pay_pubkey_full')
self.assertEqual(txo.get_address(self.ledger), 'bZi1WEjGtsdAwuZTnNNTCAZLxhHkiHec4m')
def test_script_hash_address(self):
t = Transaction(unhexlify(
"020000000100000000000000000000000000000000000000000000000000000000"
"00000000ffffffff2403b5a50b04b9e6ba5e08810007e6675b03002f504c41594d"
"4f4e415f69735f676f6f642f000000000100c37ec60600000017a914fbbf4e9bfe"
"70f27fb8aacd5386acc57f7a5ff7f58700000000"
))
txo = t.outputs[0]
self.assertEqual(txo.script.template.name, 'pay_script_hash')
self.assertEqual(txo.get_address(self.ledger), 'rVBhueRT9E8RPdVcpCdXV5gRiiXVjE6VD9')

View file

@ -237,7 +237,7 @@ class TestQueries(AsyncioTestCase):
async def create_tx_from_txo(self, txo, to_account, height):
from_hash = txo.script.values['pubkey_hash']
from_address = self.ledger.hash160_to_address(from_hash)
from_address = self.ledger.pubkey_hash_to_address(from_hash)
to_address = await to_account.receiving.get_or_create_usable_address()
to_hash = Ledger.address_to_hash160(to_address)
tx = Transaction(height=height, is_verified=True) \
@ -250,7 +250,7 @@ class TestQueries(AsyncioTestCase):
async def create_tx_to_nowhere(self, txo, height):
from_hash = txo.script.values['pubkey_hash']
from_address = self.ledger.hash160_to_address(from_hash)
from_address = self.ledger.pubkey_hash_to_address(from_hash)
to_hash = NULL_HASH
tx = Transaction(height=height, is_verified=True) \
.add_inputs([self.txi(txo)]) \