mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-25 23:01:02 +00:00
ripple: get address
This commit is contained in:
parent
51d810b6da
commit
b5c2ae49dd
@ -32,4 +32,4 @@ known_standard_library = micropython,ubinascii,ustruct,uctypes,utime,utimeq,trez
|
|||||||
[tool:pytest]
|
[tool:pytest]
|
||||||
addopts = --pyargs trezorlib.tests.device_tests
|
addopts = --pyargs trezorlib.tests.device_tests
|
||||||
xfail_strict = true
|
xfail_strict = true
|
||||||
run_xfail =
|
run_xfail = ripple
|
||||||
|
13
src/apps/ripple/__init__.py
Normal file
13
src/apps/ripple/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from trezor.wire import register, protobuf_workflow
|
||||||
|
from trezor.messages.wire_types import RippleGetAddress
|
||||||
|
from .get_address import get_address
|
||||||
|
from .serializer import *
|
||||||
|
|
||||||
|
|
||||||
|
def dispatch_RippleGetAddress(*args, **kwargs):
|
||||||
|
from .get_address import get_address
|
||||||
|
return get_address(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def boot():
|
||||||
|
register(RippleGetAddress, protobuf_workflow, dispatch_RippleGetAddress)
|
33
src/apps/ripple/base58_ripple.py
Normal file
33
src/apps/ripple/base58_ripple.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from trezor.crypto import base58
|
||||||
|
|
||||||
|
# Ripple uses different 58 character alphabet than traditional base58
|
||||||
|
_ripple_alphabet = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
|
||||||
|
|
||||||
|
|
||||||
|
def encode(data: bytes) -> str:
|
||||||
|
"""
|
||||||
|
Convert bytes to base58 encoded string.
|
||||||
|
"""
|
||||||
|
return base58.encode(data, alphabet=_ripple_alphabet)
|
||||||
|
|
||||||
|
|
||||||
|
def decode(string: str) -> bytes:
|
||||||
|
"""
|
||||||
|
Convert base58 encoded string to bytes.
|
||||||
|
"""
|
||||||
|
return base58.decode(string, alphabet=_ripple_alphabet)
|
||||||
|
|
||||||
|
|
||||||
|
def encode_check(data: bytes, digestfunc=base58.sha256d_32) -> str:
|
||||||
|
"""
|
||||||
|
Convert bytes to base58 encoded string, append checksum.
|
||||||
|
"""
|
||||||
|
return encode(data + digestfunc(data))
|
||||||
|
|
||||||
|
|
||||||
|
def decode_check(string: str, digestfunc=base58.sha256d_32) -> bytes:
|
||||||
|
"""
|
||||||
|
Convert base58 encoded string to bytes and verify checksum.
|
||||||
|
"""
|
||||||
|
data = decode(string)
|
||||||
|
return base58.verify_checksum(data, digestfunc)
|
20
src/apps/ripple/get_address.py
Normal file
20
src/apps/ripple/get_address.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from apps.common import seed
|
||||||
|
from apps.common.display_address import show_address, show_qr
|
||||||
|
from trezor.messages.RippleAddress import RippleAddress
|
||||||
|
from trezor.messages.RippleGetAddress import RippleGetAddress
|
||||||
|
from . import helpers
|
||||||
|
|
||||||
|
|
||||||
|
async def get_address(ctx, msg: RippleGetAddress):
|
||||||
|
node = await seed.derive_node(ctx, msg.address_n)
|
||||||
|
pubkey = node.public_key()
|
||||||
|
address = helpers.address_from_public_key(pubkey)
|
||||||
|
|
||||||
|
if msg.show_display:
|
||||||
|
while True:
|
||||||
|
if await show_address(ctx, address):
|
||||||
|
break
|
||||||
|
if await show_qr(ctx, address.upper()):
|
||||||
|
break
|
||||||
|
|
||||||
|
return RippleAddress(address=address)
|
25
src/apps/ripple/helpers.py
Normal file
25
src/apps/ripple/helpers.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from trezor.crypto.hashlib import ripemd160, sha256
|
||||||
|
|
||||||
|
from . import base58_ripple
|
||||||
|
|
||||||
|
|
||||||
|
def address_from_public_key(pubkey: bytes):
|
||||||
|
"""Extracts public key from an address
|
||||||
|
|
||||||
|
Ripple address is in format:
|
||||||
|
<1-byte ripple flag> <20-bytes account id> <4-bytes dSHA-256 checksum>
|
||||||
|
|
||||||
|
- 1-byte flag is 0x00 which is 'r' (Ripple uses its own base58 alphabet)
|
||||||
|
- 20-bytes account id is a ripemd160(sha256(pubkey))
|
||||||
|
- checksum is first 4 bytes of double sha256(data)
|
||||||
|
|
||||||
|
see https://developers.ripple.com/accounts.html#address-encoding
|
||||||
|
"""
|
||||||
|
"""Returns the Ripple address created using base58"""
|
||||||
|
h = sha256(pubkey).digest()
|
||||||
|
h = ripemd160(h).digest()
|
||||||
|
|
||||||
|
address = bytearray()
|
||||||
|
address.append(0x00) # 'r'
|
||||||
|
address.extend(h)
|
||||||
|
return base58_ripple.encode_check(bytes(address))
|
@ -16,9 +16,9 @@ import apps.ethereum
|
|||||||
import apps.lisk
|
import apps.lisk
|
||||||
import apps.nem
|
import apps.nem
|
||||||
import apps.stellar
|
import apps.stellar
|
||||||
|
import apps.ripple
|
||||||
import apps.cardano
|
import apps.cardano
|
||||||
|
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
import apps.debug
|
import apps.debug
|
||||||
else:
|
else:
|
||||||
@ -32,6 +32,7 @@ apps.ethereum.boot()
|
|||||||
apps.lisk.boot()
|
apps.lisk.boot()
|
||||||
apps.nem.boot()
|
apps.nem.boot()
|
||||||
apps.stellar.boot()
|
apps.stellar.boot()
|
||||||
|
apps.ripple.boot()
|
||||||
apps.cardano.boot()
|
apps.cardano.boot()
|
||||||
if __debug__:
|
if __debug__:
|
||||||
apps.debug.boot()
|
apps.debug.boot()
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
_alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
|
||||||
def encode(data: bytes) -> str:
|
def encode(data: bytes, alphabet=_alphabet) -> str:
|
||||||
"""
|
"""
|
||||||
Convert bytes to base58 encoded string.
|
Convert bytes to base58 encoded string.
|
||||||
"""
|
"""
|
||||||
@ -33,22 +33,22 @@ def encode(data: bytes) -> str:
|
|||||||
result = ""
|
result = ""
|
||||||
while acc > 0:
|
while acc > 0:
|
||||||
acc, mod = divmod(acc, 58)
|
acc, mod = divmod(acc, 58)
|
||||||
result += _alphabet[mod]
|
result += alphabet[mod]
|
||||||
|
|
||||||
return "".join((c for c in reversed(result + _alphabet[0] * (origlen - newlen))))
|
return "".join((c for c in reversed(result + alphabet[0] * (origlen - newlen))))
|
||||||
|
|
||||||
|
|
||||||
def decode(string: str) -> bytes:
|
def decode(string: str, alphabet=_alphabet) -> bytes:
|
||||||
"""
|
"""
|
||||||
Convert base58 encoded string to bytes.
|
Convert base58 encoded string to bytes.
|
||||||
"""
|
"""
|
||||||
origlen = len(string)
|
origlen = len(string)
|
||||||
string = string.lstrip(_alphabet[0])
|
string = string.lstrip(alphabet[0])
|
||||||
newlen = len(string)
|
newlen = len(string)
|
||||||
|
|
||||||
p, acc = 1, 0
|
p, acc = 1, 0
|
||||||
for c in reversed(string):
|
for c in reversed(string):
|
||||||
acc += p * _alphabet.index(c)
|
acc += p * alphabet.index(c)
|
||||||
p *= 58
|
p *= 58
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
@ -83,8 +83,12 @@ def decode_check(string: str, digestfunc=sha256d_32) -> bytes:
|
|||||||
Convert base58 encoded string to bytes and verify checksum.
|
Convert base58 encoded string to bytes and verify checksum.
|
||||||
"""
|
"""
|
||||||
result = decode(string)
|
result = decode(string)
|
||||||
|
return verify_checksum(result, digestfunc)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_checksum(data: bytes, digestfunc) -> bytes:
|
||||||
digestlen = len(digestfunc(b""))
|
digestlen = len(digestfunc(b""))
|
||||||
result, check = result[:-digestlen], result[-digestlen:]
|
result, check = data[:-digestlen], data[-digestlen:]
|
||||||
|
|
||||||
if check != digestfunc(result):
|
if check != digestfunc(result):
|
||||||
raise ValueError("Invalid checksum")
|
raise ValueError("Invalid checksum")
|
||||||
|
19
tests/test_apps.ripple.pubkey_to_address.py
Normal file
19
tests/test_apps.ripple.pubkey_to_address.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from common import *
|
||||||
|
from apps.ripple.helpers import address_from_public_key
|
||||||
|
|
||||||
|
|
||||||
|
class TestStellarPubkeyToAddress(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_pubkey_to_address(self):
|
||||||
|
addr = address_from_public_key(unhexlify('ed9434799226374926eda3b54b1b461b4abf7237962eae18528fea67595397fa32'))
|
||||||
|
self.assertEqual(addr, 'rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN')
|
||||||
|
|
||||||
|
addr = address_from_public_key(unhexlify('03e2b079e9b09ae8916da8f5ee40cbda9578dbe7c820553fe4d5f872eec7b1fdd4'))
|
||||||
|
self.assertEqual(addr, 'rhq549rEtUrJowuxQC2WsHNGLjAjBQdAe8')
|
||||||
|
|
||||||
|
addr = address_from_public_key(unhexlify('0282ee731039929e97db6aec242002e9aa62cd62b989136df231f4bb9b8b7c7eb2'))
|
||||||
|
self.assertEqual(addr, 'rKzE5DTyF9G6z7k7j27T2xEas2eMo85kmw')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user