1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-14 03:30:02 +00:00

common+python: add Ontology support

python cli: change option short names

core: fix ontology capability generation

core+python: post rebase 'make gen' and fixes

python/ontology - cleanup writer

test/ontology: added proper marks and removed class

test/ontology: added missing mark
This commit is contained in:
Matus Zamborsky 2019-05-25 12:00:43 +02:00 committed by ciny
parent 11d80f0f20
commit 23df799e77
63 changed files with 2258 additions and 6 deletions

View File

@ -1,4 +1,4 @@
check: messages.pb messages-binance.pb messages-bitcoin.pb messages-bootloader.pb messages-cardano.pb messages-common.pb messages-crypto.pb messages-debug.pb messages-ethereum.pb messages-lisk.pb messages-management.pb messages-monero.pb messages-nem.pb messages-ripple.pb messages-stellar.pb messages-tezos.pb messages-eos.pb
check: messages.pb messages-binance.pb messages-bitcoin.pb messages-bootloader.pb messages-cardano.pb messages-common.pb messages-crypto.pb messages-debug.pb messages-ethereum.pb messages-lisk.pb messages-management.pb messages-monero.pb messages-nem.pb messages-ripple.pb messages-stellar.pb messages-tezos.pb messages-ontology.pb messages-eos.pb
%.pb: %.proto
protoc -I/usr/include -I. $< -o $@

View File

@ -83,6 +83,7 @@ message Features {
Capability_U2F = 14;
Capability_Shamir = 15;
Capability_ShamirGroups = 16;
Capability_Ontology = 17;
}
optional BackupType backup_type = 31; // type of device backup (BIP-39 / SLIP-39 basic / SLIP-39 advanced)
optional bool sd_card_present = 32; // is SD card present

View File

@ -0,0 +1,134 @@
syntax = "proto2";
package hw.trezor.messages.ontology;
// Sugar for easier handling in Java
option java_package = "com.satoshilabs.trezor.lib.protobuf";
option java_outer_classname = "TrezorMessageOntology";
/**
* Ontology Transaction
* @embed
*/
message OntologyTransaction {
optional uint32 version = 1;
optional uint32 type = 2;
optional uint32 nonce = 3;
optional uint64 gas_price = 4;
optional uint64 gas_limit = 5;
optional string payer = 6;
repeated OntologyTxAttribute tx_attributes = 7;
/**
* Attribute of Ontology transaction
*/
message OntologyTxAttribute {
optional uint32 usage = 1;
optional bytes data = 2;
}
}
/**
* Request: Ask device for Ontology public key corresponding to address_n path
* @start
* @next OntologyPublicKey
*/
message OntologyGetPublicKey {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
optional bool show_display = 2; // Optionally show on display before sending the result
}
/**
* Response: Contains Ontology public key derived from device private seed
* @end
*/
message OntologyPublicKey {
optional bytes public_key = 1; // Ontology public key
}
/**
* Request: Ask device for Ontology address corresponding to address_n path
* @start
* @next OntologyAddress
*/
message OntologyGetAddress {
repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
optional bool show_display = 2; // Optionally show on display before sending the result
}
/**
* Response: Contains Ontology address derived from device private seed
* @end
*/
message OntologyAddress {
optional string address = 1; // Ontology address
}
/**
* Request: Ask device to sign Ontology transaction
* @start
* @next OntologySignedTx
*/
message OntologySignTx{
repeated uint32 address_n = 1;
optional OntologyTransaction transaction = 2;
optional OntologyTransfer transfer = 3;
optional OntologyWithdrawOng withdraw_ong = 4;
optional OntologyOntIdRegister ont_id_register = 5;
optional OntologyOntIdAddAttributes ont_id_add_attributes = 6;
message OntologyTransfer {
optional OntologyAsset asset = 1;
optional uint64 amount = 2;
optional string from_address = 3;
optional string to_address = 4;
/**
* Ontology Asset
*/
enum OntologyAsset {
ONT = 1;
ONG = 2;
}
}
/**
* Ontology ONG Withdrawal
*/
message OntologyWithdrawOng {
optional uint64 amount = 1;
optional string from_address = 2;
optional string to_address = 3;
}
/**
* Ontology ONT ID registration
*/
message OntologyOntIdRegister {
optional string ont_id = 1;
optional bytes public_key = 2;
}
/**
* Ontology ONT ID attributes adding
*/
message OntologyOntIdAddAttributes {
optional string ont_id = 1;
optional bytes public_key = 2;
repeated OntologyOntIdAttribute ont_id_attributes = 3;
/**
* Attribute of Ontology ONT ID
*/
message OntologyOntIdAttribute {
optional string key = 1;
optional string type = 2;
optional string value = 3;
}
}
}
/**
* Response: Contains Ontology tx signature and payload
* @end
*/
message OntologySignedTx {
optional bytes signature = 1;
optional bytes payload = 2;
}

View File

@ -177,6 +177,14 @@ enum MessageType {
MessageType_CardanoTxAck = 309 [(wire_in) = true];
MessageType_CardanoSignedTx = 310 [(wire_out) = true];
// Ontology
MessageType_OntologyGetAddress = 350 [(wire_in) = true];
MessageType_OntologyAddress = 351 [(wire_out) = true];
MessageType_OntologyGetPublicKey = 352 [(wire_in) = true];
MessageType_OntologyPublicKey = 353 [(wire_out) = true];
MessageType_OntologySignTx = 354 [(wire_in) = true];
MessageType_OntologySignedTx = 355 [(wire_out) = true];
// Ripple
MessageType_RippleGetAddress = 400 [(wire_in) = true];
MessageType_RippleAddress = 401 [(wire_out) = true];

View File

@ -61,6 +61,7 @@ def get_features() -> Features:
Capability.Lisk,
Capability.Monero,
Capability.NEM,
Capability.Ontology,
Capability.Ripple,
Capability.Stellar,
Capability.Tezos,

View File

@ -0,0 +1,16 @@
from trezor import wire
from trezor.messages import MessageType
from apps.common import HARDENED
CURVE = "nist256p1"
def boot() -> None:
ns = [
[CURVE, HARDENED | 44, HARDENED | 1024],
[CURVE, HARDENED | 44, HARDENED | 888],
]
wire.add(MessageType.OntologyGetPublicKey, __name__, "get_public_key", ns)
wire.add(MessageType.OntologyGetAddress, __name__, "get_address", ns)
wire.add(MessageType.OntologySignTx, __name__, "sign_tx", ns)

View File

@ -0,0 +1,9 @@
ONT_CONTRACT = (
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
)
ONG_CONTRACT = (
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
)
ONTID_CONTRACT = (
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"
)

View File

@ -0,0 +1,26 @@
from trezor.crypto.curve import nist256p1
from trezor.messages.OntologyAddress import OntologyAddress
from trezor.messages.OntologyGetAddress import OntologyGetAddress
from .helpers import CURVE, get_address_from_public_key, validate_full_path
from apps.common import paths
from apps.common.layout import show_address, show_qr
async def get_address(ctx, msg: OntologyGetAddress, keychain) -> OntologyAddress:
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
node = keychain.derive(msg.address_n, CURVE)
seckey = node.private_key()
public_key = nist256p1.publickey(seckey, True)
address = get_address_from_public_key(public_key)
if msg.show_display:
while True:
if await show_address(ctx, address):
break
if await show_qr(ctx, address):
break
return OntologyAddress(address=address)

View File

@ -0,0 +1,20 @@
from trezor.crypto.curve import nist256p1
from trezor.messages.OntologyGetPublicKey import OntologyGetPublicKey
from trezor.messages.OntologyPublicKey import OntologyPublicKey
from .helpers import CURVE, validate_full_path
from apps.common import layout, paths
async def get_public_key(ctx, msg: OntologyGetPublicKey, keychain) -> OntologyPublicKey:
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
node = keychain.derive(msg.address_n, CURVE)
seckey = node.private_key()
public_key = nist256p1.publickey(seckey, True)
if msg.show_display:
await layout.show_pubkey(ctx, public_key)
return OntologyPublicKey(public_key=public_key)

View File

@ -0,0 +1,44 @@
from trezor.crypto import base58
from trezor.crypto.scripts import sha256_ripemd160_digest
from apps.common import HARDENED
CURVE = "nist256p1"
def get_address_from_public_key(pubkey: bytes) -> str:
"""
Computes address from public key
"""
address_bytes = b"\x17" + sha256_ripemd160_digest(b"\x21" + pubkey + b"\xac")
return base58.encode_check(address_bytes)
def get_bytes_from_address(address: str) -> bytes:
"""
Converts base58check address to hex representation
"""
return base58.decode_check(address)[1:]
def validate_full_path(path: list) -> bool:
"""
Validates derivation path to fit 44'/1024'/a'/{0,1}/i,
where `a` is an account number and i an address index.
The max value for `a` is 20, 1 000 000 for `i`.
The derivation scheme v1 allowed a'/0/i only,
but in v2 it can be a'/1/i as well.
"""
if len(path) != 5:
return False
if path[0] != 44 | HARDENED:
return False
if path[1] != 1024 | HARDENED and path[1] != 888 | HARDENED:
return False
if path[2] < HARDENED or path[2] > 20 | HARDENED:
return False
if path[3] != 0 and path[3] != 1:
return False
if path[4] > 1000000:
return False
return True

View File

@ -0,0 +1,61 @@
from ubinascii import hexlify
from trezor import ui
from trezor.messages import ButtonRequestType
from trezor.ui.scroll import Paginated
from trezor.ui.text import Text
from trezor.utils import chunks, format_amount
from apps.common.confirm import require_confirm
async def require_confirm_transfer_ont(ctx, dest, value):
text = Text("Confirm sending", ui.ICON_SEND, icon_color=ui.GREEN)
text.bold(format_amount(value, 0) + "ONT")
text.mono(*split_address("To: " + dest))
return await require_confirm(ctx, text, ButtonRequestType.SignTx)
async def require_confirm_transfer_ong(ctx, dest, value):
text = Text("Confirm sending", ui.ICON_SEND, icon_color=ui.GREEN)
text.bold(format_amount(value, 9) + "ONG")
text.mono(*split_address("To: " + dest))
return await require_confirm(ctx, text, ButtonRequestType.SignTx)
async def require_confirm_withdraw_ong(ctx, value):
text = Text("Confirm withdraw of ", ui.ICON_SEND, icon_color=ui.GREEN)
text.bold(format_amount(value, 9) + "ONG")
return await require_confirm(ctx, text, ButtonRequestType.SignTx)
async def require_confirm_ont_id_register(ctx, ont_id, public_key):
t = Text("Confirm registering", ui.ICON_SEND, ui.GREEN)
key = hexlify(public_key).decode()
t.normal("for " + ont_id + " with public key " + key)
pages = [t]
return await require_confirm(ctx, Paginated(pages), code=ButtonRequestType.SignTx)
async def require_confirm_ont_id_add_attributes(ctx, ont_id, public_key, attributes):
key = hexlify(public_key).decode()
t = Text("Confirm attributes", ui.ICON_SEND, ui.GREEN)
t.normal("for " + ont_id + " with public key " + key)
pages = [t]
for attribute in attributes:
t1 = Text("Attribute:")
t1.normal("Name " + attribute.key)
t1.normal("Type: " + attribute.type)
t1.normal("Value: " + attribute.value)
pages.append(t1)
return await require_confirm(ctx, Paginated(pages), ButtonRequestType.SignTx)
def split_address(address):
return chunks(address, 16)
def split_str(text: str):
return list(chunks(text, 16))

View File

@ -0,0 +1,51 @@
from .. import writer
from . import opcode
def write_push_bytes(ret: bytearray, param: bytes) -> None:
"""
Writes PUSH BYTES instruction
"""
length = len(param)
if length < opcode.PUSHBYTES75:
writer.write_byte(ret, length)
elif length < 0x100:
writer.write_byte(ret, opcode.PUSHDATA1)
writer.write_byte(ret, length)
elif length < 0x10000:
writer.write_byte(ret, opcode.PUSHDATA2)
writer.write_uint16(ret, length)
else:
writer.write_byte(ret, opcode.PUSHDATA4)
writer.write_uint32(ret, length)
writer.write_bytes(ret, param)
def write_push_int(ret: bytearray, param: int) -> None:
"""
Writes PUSH INT instruction
"""
if param == -1:
writer.write_byte(ret, opcode.PUSHM1)
elif param == 0:
writer.write_byte(ret, opcode.PUSH0)
elif 0 < param < 16:
num = opcode.PUSH1 - 1 + param
writer.write_byte(ret, num)
else:
# number encoded as 8 bytes
num = bytearray()
writer.write_uint64(num, param)
write_push_bytes(ret, bytes(num))
def write_push_bool(ret: bytearray, param: bool) -> None:
"""
Writes PUSH BOOL instruction
"""
if param:
writer.write_byte(ret, opcode.PUSH1)
else:
writer.write_byte(ret, opcode.PUSH0)

View File

@ -0,0 +1,120 @@
from ubinascii import unhexlify
from trezor import wire
from .. import writer
from . import builder, opcode
class ParamStruct:
"""
Special struct for smart contract argument passing
"""
def __init__(self, arr: list):
self.arr = arr
def build_native_call(func_name: str, params: list, contract: bytes) -> bytes:
"""
Builds native contract call
"""
ret = bytearray()
_write_native_code_script(ret, params)
builder.write_push_bytes(ret, func_name.encode())
builder.write_push_bytes(ret, contract)
builder.write_push_int(ret, 0)
writer.write_byte(ret, opcode.SYSCALL)
builder.write_push_bytes(ret, b"Ontology.Native.Invoke")
return ret
def _write_native_code_script(ret: bytearray, arr: list) -> None:
"""
Writes native code script from supplied data
"""
for val in reversed(arr):
if isinstance(val, str):
builder.write_push_bytes(ret, unhexlify(val))
elif isinstance(val, (bytes, bytearray)):
builder.write_push_bytes(ret, val)
elif isinstance(val, bool):
builder.write_push_bool(ret, val)
elif isinstance(val, int):
builder.write_push_int(ret, val)
elif isinstance(val, ParamStruct):
builder.write_push_int(ret, 0)
writer.write_byte(ret, opcode.NEWSTRUCT)
writer.write_byte(ret, opcode.TOALTSTACK)
for v in val.arr:
_write_code_param_script(ret, v)
writer.write_byte(ret, opcode.DUPFROMALTSTACK)
writer.write_byte(ret, opcode.SWAP)
writer.write_byte(ret, opcode.APPEND)
writer.write_byte(ret, opcode.FROMALTSTACK)
elif isinstance(val, list) and is_typed_list(val, ParamStruct):
builder.write_push_int(ret, 0)
writer.write_byte(ret, opcode.NEWSTRUCT)
writer.write_byte(ret, opcode.TOALTSTACK)
for s in val:
_write_code_param_script(ret, s)
writer.write_byte(ret, opcode.FROMALTSTACK)
builder.write_push_int(ret, len(val))
writer.write_byte(ret, opcode.PACK)
elif isinstance(val, list):
print("array")
_write_native_code_script(ret, val)
builder.write_push_int(ret, len(val))
writer.write_byte(ret, opcode.PACK)
else:
raise wire.DataError("Invalid param type")
def _write_code_param_script(ret: bytearray, obj) -> None:
"""
Writes native code param script from supplied data
"""
if isinstance(obj, str):
builder.write_push_bytes(ret, unhexlify(obj))
elif isinstance(obj, (bytes, bytearray)):
builder.write_push_bytes(ret, obj)
elif isinstance(obj, bool):
builder.write_push_bool(ret, obj)
elif isinstance(obj, int):
builder.write_push_int(ret, obj)
elif isinstance(obj, ParamStruct):
for v in obj.arr:
_write_code_param_script(ret, v)
writer.write_byte(ret, opcode.DUPFROMALTSTACK)
writer.write_byte(ret, opcode.SWAP)
writer.write_byte(ret, opcode.APPEND)
else:
raise wire.DataError("Invalid param type")
def is_typed_list(arr: list, t) -> bool:
"""
Tests if list contains only object of specified types
"""
for a in arr:
if not isinstance(a, t):
return False
return True

View File

@ -0,0 +1,31 @@
# OpCode constants
# An empty array of bytes is pushed onto the stack.
PUSH0 = 0x00
PUSHBYTES75 = 0x4B
# The next byte contains the number of bytes to be pushed onto the stack.
PUSHDATA1 = 0x4C
# The next two bytes contain the number of bytes to be pushed onto the stack.
PUSHDATA2 = 0x4D
# The next four bytes contain the number of bytes to be pushed onto the stack.
PUSHDATA4 = 0x4E
# The number -1 is pushed onto the stack.
PUSHM1 = 0x4F
# The number 1 is pushed onto the stack.
PUSH1 = 0x51
# Flow control
SYSCALL = 0x68
DUPFROMALTSTACK = 0x6A
# Stack
# Puts the input onto the top of the alt stack. Removes it from the main stack.
TOALTSTACK = 0x6B
# Puts the input onto the top of the main stack. Removes it from the alt stack.
FROMALTSTACK = 0x6C
# The top two items on the stack are swapped.
SWAP = 0x7C
# Array
PACK = 0xC1
NEWSTRUCT = 0xC6
APPEND = 0xC8

View File

@ -0,0 +1,104 @@
from trezor.messages import OntologyAsset
from trezor.messages.OntologyOntIdAddAttributes import OntologyOntIdAddAttributes
from trezor.messages.OntologyOntIdRegister import OntologyOntIdRegister
from trezor.messages.OntologyTransaction import OntologyTransaction
from trezor.messages.OntologyTransfer import OntologyTransfer
from trezor.messages.OntologyTxAttribute import OntologyTxAttribute
from trezor.messages.OntologyWithdrawOng import OntologyWithdrawOng
from . import const as Const, writer
from .helpers import get_bytes_from_address
from .sc.native_builder import ParamStruct, build_native_call
def serialize_tx(tx: OntologyTransaction, payload: bytes, hw) -> None:
writer.write_byte(hw, tx.version)
writer.write_byte(hw, tx.type)
writer.write_uint32(hw, tx.nonce)
writer.write_uint64(hw, tx.gas_price)
writer.write_uint64(hw, tx.gas_limit)
payer = get_bytes_from_address(tx.payer)
writer.write_bytes(hw, payer)
writer.write_bytes(hw, payload)
attributes = tx.tx_attributes
writer.write_varint(hw, len(attributes))
if attributes is not None:
for attribute in attributes:
_serialize_tx_attribute(hw, attribute)
def serialize_transfer(transfer: OntologyTransfer) -> bytes:
from_address = get_bytes_from_address(transfer.from_address)
to_address = get_bytes_from_address(transfer.to_address)
amount = transfer.amount
contract = ""
if transfer.asset == OntologyAsset.ONT:
contract = Const.ONT_CONTRACT
else:
contract = Const.ONG_CONTRACT
struct = ParamStruct([from_address, to_address, amount])
native_call = build_native_call("transfer", [[struct]], contract)
# 9 is the maximum possible length of the uvarint prefix
ret = bytearray()
writer.write_bytes_with_length(ret, native_call)
return bytes(ret)
def serialize_withdraw_ong(withdraw_ong: OntologyWithdrawOng) -> bytes:
from_address = get_bytes_from_address(withdraw_ong.from_address)
to_address = get_bytes_from_address(withdraw_ong.to_address)
amount = withdraw_ong.amount
struct = ParamStruct([from_address, Const.ONT_CONTRACT, to_address, amount])
native_call = build_native_call("transferFrom", [struct], Const.ONG_CONTRACT)
ret = bytearray()
writer.write_bytes_with_length(ret, native_call)
return bytes(ret)
def serialize_ont_id_register(register: OntologyOntIdRegister) -> bytes:
ont_id = register.ont_id.encode()
struct = ParamStruct([ont_id, register.public_key])
native_call = build_native_call(
"regIDWithPublicKey", [struct], Const.ONTID_CONTRACT
)
ret = bytearray()
writer.write_bytes_with_length(ret, native_call)
return bytes(ret)
def serialize_ont_id_add_attributes(add: OntologyOntIdAddAttributes) -> bytes:
ont_id = add.ont_id.encode()
attributes = add.ont_id_attributes
arguments = [ont_id, len(attributes)]
for attribute in attributes:
arguments.append(attribute.key.encode())
arguments.append(attribute.type.encode())
arguments.append(attribute.value.encode())
arguments.append(add.public_key)
struct = ParamStruct(arguments)
native_call = build_native_call("addAttributes", [struct], Const.ONTID_CONTRACT)
ret = bytearray()
writer.write_bytes_with_length(ret, native_call)
return bytes(ret)
def _serialize_tx_attribute(ret: bytearray, attribute: OntologyTxAttribute) -> None:
writer.write_byte(ret, attribute.usage)
if attribute.data is not None:
writer.write_bytes_with_length(ret, attribute.data)

View File

@ -0,0 +1,125 @@
from trezor import wire
from trezor.crypto.curve import nist256p1
from trezor.crypto.hashlib import sha256
from trezor.messages import OntologyAsset
from trezor.messages.OntologySignedTx import OntologySignedTx
from trezor.messages.OntologySignTx import OntologySignTx
from trezor.utils import HashWriter
from .helpers import CURVE, validate_full_path
from .layout import (
require_confirm_ont_id_add_attributes,
require_confirm_ont_id_register,
require_confirm_transfer_ong,
require_confirm_transfer_ont,
require_confirm_withdraw_ong,
)
from .serialize import (
serialize_ont_id_add_attributes,
serialize_ont_id_register,
serialize_transfer,
serialize_tx,
serialize_withdraw_ong,
)
from apps.common import paths
async def sign_tx(ctx, msg: OntologySignTx, keychain) -> OntologySignedTx:
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
if msg.transfer:
return await sign_transfer(ctx, msg, keychain)
elif msg.withdraw_ong:
return await sign_withdraw_ong(ctx, msg, keychain)
elif msg.ont_id_register:
return await sign_ont_id_register(ctx, msg, keychain)
elif msg.ont_id_add_attributes:
return await sign_ont_id_add_attributes(ctx, msg, keychain)
async def sign(raw_data: bytes, private_key: bytes) -> bytes:
"""
Creates signature for data
"""
data_hash = sha256(sha256(raw_data).digest()).digest()
signature = nist256p1.sign(private_key, data_hash, False)
signature = b"\x01" + signature[1:65] # first byte of transaction is 0x01
return signature
async def sign_transfer(ctx, msg: OntologySignTx, keychain) -> OntologySignedTx:
if msg.transaction.type == 0xD1:
if msg.transfer.asset == OntologyAsset.ONT:
await require_confirm_transfer_ont(
ctx, msg.transfer.to_address, msg.transfer.amount
)
if msg.transfer.asset == OntologyAsset.ONG:
await require_confirm_transfer_ong(
ctx, msg.transfer.to_address, msg.transfer.amount
)
else:
raise wire.DataError("Invalid transaction type")
node = keychain.derive(msg.address_n, CURVE)
hw = HashWriter(sha256())
serialized_payload = serialize_transfer(msg.transfer)
serialize_tx(msg.transaction, serialized_payload, hw)
signature = await sign(hw.get_digest(), node.private_key())
return OntologySignedTx(signature=signature, payload=serialized_payload)
async def sign_withdraw_ong(ctx, msg: OntologySignTx, keychain) -> OntologySignedTx:
if msg.transaction.type == 0xD1:
await require_confirm_withdraw_ong(ctx, msg.withdraw_ong.amount)
else:
raise wire.DataError("Invalid transaction type")
node = keychain.derive(msg.address_n, CURVE)
hw = HashWriter(sha256())
serialized_payload = serialize_withdraw_ong(msg.withdraw_ong)
serialize_tx(msg.transaction, serialized_payload, hw)
signature = await sign(hw.get_digest(), node.private_key())
return OntologySignedTx(signature=signature, payload=serialized_payload)
async def sign_ont_id_register(ctx, msg: OntologySignTx, keychain) -> OntologySignedTx:
if msg.transaction.type == 0xD1:
await require_confirm_ont_id_register(
ctx, msg.ont_id_register.ont_id, msg.ont_id_register.public_key
)
else:
raise wire.DataError("Invalid transaction type")
node = keychain.derive(msg.address_n, CURVE)
hw = HashWriter(sha256())
serialized_payload = serialize_ont_id_register(msg.ont_id_register)
serialize_tx(msg.transaction, serialized_payload, hw)
signature = await sign(hw.get_digest(), node.private_key())
return OntologySignedTx(signature=signature, payload=serialized_payload)
async def sign_ont_id_add_attributes(
ctx, msg: OntologySignTx, keychain
) -> OntologySignedTx:
if msg.transaction.type == 0xD1:
await require_confirm_ont_id_add_attributes(
ctx,
msg.ont_id_add_attributes.ont_id,
msg.ont_id_add_attributes.public_key,
msg.ont_id_add_attributes.ont_id_attributes,
)
else:
raise wire.DataError("Invalid transaction type")
node = keychain.derive(msg.address_n, CURVE)
hw = HashWriter(sha256())
serialized_payload = serialize_ont_id_add_attributes(msg.ont_id_add_attributes)
serialize_tx(msg.transaction, serialized_payload, hw)
signature = await sign(hw.get_digest(), node.private_key())
return OntologySignedTx(signature=signature, payload=serialized_payload)

View File

@ -0,0 +1,22 @@
from apps.common.writers import ( # noqa: F401
write_bytes,
write_uint16_le as write_uint16,
write_uint32_le as write_uint32,
write_uint64_le as write_uint64,
)
from apps.wallet.sign_tx.writers import write_varint
def write_byte(w: bytearray, n: int) -> None:
"""
Writes one byte (8bit)
"""
w.append(n & 0xFF)
def write_bytes_with_length(w: bytearray, buf: bytes) -> None:
"""
Writes arbitrary byte sequence prepended with the length using variable length integer
"""
write_varint(w, len(buf))
write_bytes(w, buf)

View File

@ -34,6 +34,7 @@ def _boot_apps() -> None:
import apps.eos
import apps.binance
import apps.webauthn
import apps.ontology
if __debug__:
import apps.debug
@ -54,6 +55,7 @@ def _boot_apps() -> None:
apps.eos.boot()
apps.binance.boot()
apps.webauthn.boot()
apps.ontology.boot()
if __debug__:
apps.debug.boot()

View File

@ -23,3 +23,5 @@ if not utils.BITCOIN_ONLY:
U2F = 14 # type: Literal[14]
Shamir = 15 # type: Literal[15]
ShamirGroups = 16 # type: Literal[16]
if not utils.BITCOIN_ONLY:
Ontology = 17 # type: Literal[17]

View File

@ -6,7 +6,7 @@ if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeCapability = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
EnumTypeCapability = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
EnumTypeBackupType = Literal[0, 1, 2]
except ImportError:
pass
@ -116,7 +116,7 @@ class Features(p.MessageType):
27: ('unfinished_backup', p.BoolType, 0),
28: ('no_backup', p.BoolType, 0),
29: ('recovery_mode', p.BoolType, 0),
30: ('capabilities', p.EnumType("Capability", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)), p.FLAG_REPEATED),
30: ('capabilities', p.EnumType("Capability", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)), p.FLAG_REPEATED),
31: ('backup_type', p.EnumType("BackupType", (0, 1, 2)), 0),
32: ('sd_card_present', p.BoolType, 0),
33: ('sd_protection', p.BoolType, 0),

View File

@ -130,6 +130,12 @@ if not utils.BITCOIN_ONLY:
CardanoAddress = 308 # type: Literal[308]
CardanoTxAck = 309 # type: Literal[309]
CardanoSignedTx = 310 # type: Literal[310]
OntologyGetAddress = 350 # type: Literal[350]
OntologyAddress = 351 # type: Literal[351]
OntologyGetPublicKey = 352 # type: Literal[352]
OntologyPublicKey = 353 # type: Literal[353]
OntologySignTx = 354 # type: Literal[354]
OntologySignedTx = 355 # type: Literal[355]
RippleGetAddress = 400 # type: Literal[400]
RippleAddress = 401 # type: Literal[401]
RippleSignTx = 402 # type: Literal[402]

View File

@ -0,0 +1,26 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyAddress(p.MessageType):
MESSAGE_WIRE_TYPE = 351
def __init__(
self,
address: str = None,
) -> None:
self.address = address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address', p.UnicodeType, 0),
}

View File

@ -0,0 +1,7 @@
# Automatically generated by pb2py
# fmt: off
if False:
from typing_extensions import Literal
ONT = 1 # type: Literal[1]
ONG = 2 # type: Literal[2]

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyGetAddress(p.MessageType):
MESSAGE_WIRE_TYPE = 350
def __init__(
self,
address_n: List[int] = None,
show_display: bool = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.show_display = show_display
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('show_display', p.BoolType, 0),
}

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyGetPublicKey(p.MessageType):
MESSAGE_WIRE_TYPE = 352
def __init__(
self,
address_n: List[int] = None,
show_display: bool = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.show_display = show_display
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('show_display', p.BoolType, 0),
}

View File

@ -0,0 +1,33 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
from .OntologyOntIdAttribute import OntologyOntIdAttribute
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdAddAttributes(p.MessageType):
def __init__(
self,
ont_id: str = None,
public_key: bytes = None,
ont_id_attributes: List[OntologyOntIdAttribute] = None,
) -> None:
self.ont_id = ont_id
self.public_key = public_key
self.ont_id_attributes = ont_id_attributes if ont_id_attributes is not None else []
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('ont_id', p.UnicodeType, 0),
2: ('public_key', p.BytesType, 0),
3: ('ont_id_attributes', OntologyOntIdAttribute, p.FLAG_REPEATED),
}

View File

@ -0,0 +1,31 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdAttribute(p.MessageType):
def __init__(
self,
key: str = None,
type: str = None,
value: str = None,
) -> None:
self.key = key
self.type = type
self.value = value
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('key', p.UnicodeType, 0),
2: ('type', p.UnicodeType, 0),
3: ('value', p.UnicodeType, 0),
}

View File

@ -0,0 +1,28 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdRegister(p.MessageType):
def __init__(
self,
ont_id: str = None,
public_key: bytes = None,
) -> None:
self.ont_id = ont_id
self.public_key = public_key
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('ont_id', p.UnicodeType, 0),
2: ('public_key', p.BytesType, 0),
}

View File

@ -0,0 +1,26 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyPublicKey(p.MessageType):
MESSAGE_WIRE_TYPE = 353
def __init__(
self,
public_key: bytes = None,
) -> None:
self.public_key = public_key
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('public_key', p.BytesType, 0),
}

View File

@ -0,0 +1,47 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
from .OntologyOntIdAddAttributes import OntologyOntIdAddAttributes
from .OntologyOntIdRegister import OntologyOntIdRegister
from .OntologyTransaction import OntologyTransaction
from .OntologyTransfer import OntologyTransfer
from .OntologyWithdrawOng import OntologyWithdrawOng
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologySignTx(p.MessageType):
MESSAGE_WIRE_TYPE = 354
def __init__(
self,
address_n: List[int] = None,
transaction: OntologyTransaction = None,
transfer: OntologyTransfer = None,
withdraw_ong: OntologyWithdrawOng = None,
ont_id_register: OntologyOntIdRegister = None,
ont_id_add_attributes: OntologyOntIdAddAttributes = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.transaction = transaction
self.transfer = transfer
self.withdraw_ong = withdraw_ong
self.ont_id_register = ont_id_register
self.ont_id_add_attributes = ont_id_add_attributes
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('transaction', OntologyTransaction, 0),
3: ('transfer', OntologyTransfer, 0),
4: ('withdraw_ong', OntologyWithdrawOng, 0),
5: ('ont_id_register', OntologyOntIdRegister, 0),
6: ('ont_id_add_attributes', OntologyOntIdAddAttributes, 0),
}

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologySignedTx(p.MessageType):
MESSAGE_WIRE_TYPE = 355
def __init__(
self,
signature: bytes = None,
payload: bytes = None,
) -> None:
self.signature = signature
self.payload = payload
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('signature', p.BytesType, 0),
2: ('payload', p.BytesType, 0),
}

View File

@ -0,0 +1,45 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
from .OntologyTxAttribute import OntologyTxAttribute
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyTransaction(p.MessageType):
def __init__(
self,
version: int = None,
type: int = None,
nonce: int = None,
gas_price: int = None,
gas_limit: int = None,
payer: str = None,
tx_attributes: List[OntologyTxAttribute] = None,
) -> None:
self.version = version
self.type = type
self.nonce = nonce
self.gas_price = gas_price
self.gas_limit = gas_limit
self.payer = payer
self.tx_attributes = tx_attributes if tx_attributes is not None else []
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('version', p.UVarintType, 0),
2: ('type', p.UVarintType, 0),
3: ('nonce', p.UVarintType, 0),
4: ('gas_price', p.UVarintType, 0),
5: ('gas_limit', p.UVarintType, 0),
6: ('payer', p.UnicodeType, 0),
7: ('tx_attributes', OntologyTxAttribute, p.FLAG_REPEATED),
}

View File

@ -0,0 +1,35 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeOntologyAsset = Literal[1, 2]
except ImportError:
pass
class OntologyTransfer(p.MessageType):
def __init__(
self,
asset: EnumTypeOntologyAsset = None,
amount: int = None,
from_address: str = None,
to_address: str = None,
) -> None:
self.asset = asset
self.amount = amount
self.from_address = from_address
self.to_address = to_address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('asset', p.EnumType("OntologyAsset", (1, 2)), 0),
2: ('amount', p.UVarintType, 0),
3: ('from_address', p.UnicodeType, 0),
4: ('to_address', p.UnicodeType, 0),
}

View File

@ -0,0 +1,28 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyTxAttribute(p.MessageType):
def __init__(
self,
usage: int = None,
data: bytes = None,
) -> None:
self.usage = usage
self.data = data
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('usage', p.UVarintType, 0),
2: ('data', p.BytesType, 0),
}

View File

@ -0,0 +1,31 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyWithdrawOng(p.MessageType):
def __init__(
self,
amount: int = None,
from_address: str = None,
to_address: str = None,
) -> None:
self.amount = amount
self.from_address = from_address
self.to_address = to_address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('amount', p.UVarintType, 0),
2: ('from_address', p.UnicodeType, 0),
3: ('to_address', p.UnicodeType, 0),
}

View File

@ -0,0 +1,193 @@
# 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import json
import click
from .. import messages, ontology, protobuf, tools
PATH_HELP = "BIP-32 path to key, e.g. m/44'/888'/0'/0/0"
@click.group(name="ontology")
def cli():
"""Ontology commands."""
@cli.command(help="Get Ontology address for specified path.")
@click.option("-n", "--address", required=True, help=PATH_HELP)
@click.option("-d", "--show-display", is_flag=True)
@click.pass_obj
def get_address(connect, address, show_display):
client = connect()
address_n = tools.parse_path(address)
return ontology.get_address(client, address_n, show_display)
@cli.command(help="Get Ontology public key for specified path.")
@click.option("-n", "--address", required=True, help=PATH_HELP)
@click.option("-d", "--show-display", is_flag=True)
@click.pass_obj
def get_public_key(connect, address, show_display):
client = connect()
address_n = tools.parse_path(address)
result = ontology.get_public_key(client, address_n, show_display)
return result.public_key.hex()
@cli.command(help="Sign Ontology transfer.")
@click.option("-n", "--address", required=True, help=PATH_HELP)
@click.option(
"-t",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-r",
"--transfer",
type=click.File("r"),
default="-",
help="Transfer in JSON format",
)
@click.pass_obj
def sign_transfer(connect, address, transaction, transfer):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
messages.OntologyTransaction, json.load(transaction)
)
transfer = protobuf.dict_to_proto(messages.OntologyTransfer, json.load(transfer))
result = ontology.sign_transfer(client, address_n, transaction, transfer)
output = {"payload": result.payload.hex(), "signature": result.signature.hex()}
return output
@cli.command(help="Sign Ontology withdraw Ong.")
@click.option("-n", "--address", required=True, help=PATH_HELP)
@click.option(
"-t",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-w",
"--withdraw_ong",
type=click.File("r"),
default="-",
help="Withdrawal in JSON format",
)
@click.pass_obj
def sign_withdraw_ong(connect, address, transaction, withdraw_ong):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
messages.OntologyTransaction, json.load(transaction)
)
withdraw_ong = protobuf.dict_to_proto(
messages.OntologyWithdrawOng, json.load(withdraw_ong)
)
result = ontology.sign_withdrawal(client, address_n, transaction, withdraw_ong)
output = {"payload": result.payload.hex(), "signature": result.signature.hex()}
return output
@cli.command(help="Sign Ontology ONT ID Registration.")
@click.option("-n", "--address", required=True, help=PATH_HELP)
@click.option(
"-t",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-r",
"--register",
type=click.File("r"),
default="-",
help="Register in JSON format",
)
@click.argument("transaction")
@click.argument("ont_id_register")
@click.pass_obj
def sign_ont_id_register(connect, address, transaction, register):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
messages.OntologyTransaction, json.load(transaction)
)
ont_id_register = protobuf.dict_to_proto(
messages.OntologyOntIdRegister, json.load(register)
)
result = ontology.sign_register(client, address_n, transaction, ont_id_register)
output = {"payload": result.payload.hex(), "signature": result.signature.hex()}
return output
@cli.command(help="Sign Ontology ONT ID Attributes adding.")
@click.option(
"-n",
"--address",
required=True,
help="BIP-32 path to signing key, e.g. m/44'/888'/0'/0/0",
)
@click.option(
"-t",
"--transaction",
type=click.File("r"),
required=True,
default="-",
help="Transaction in JSON format",
)
@click.option(
"-a",
"--add_attribute",
type=click.File("r"),
required=True,
default="-",
help="Add attributes in JSON format",
)
@click.pass_obj
def sign_ont_id_add_attributes(connect, address, transaction, add_attribute):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
messages.OntologyTransaction, json.load(transaction)
)
ont_id_add_attributes = protobuf.dict_to_proto(
messages.OntologyOntIdAddAttributes, json.load(add_attribute)
)
result = ontology.sign_add_attr(
client, address_n, transaction, ont_id_add_attributes
)
output = {"payload": result.payload.hex(), "signature": result.signature.hex()}
return output

View File

@ -39,6 +39,7 @@ from . import (
lisk,
monero,
nem,
ontology,
ripple,
settings,
stellar,
@ -266,6 +267,7 @@ cli.add_command(fido.cli)
cli.add_command(lisk.cli)
cli.add_command(monero.cli)
cli.add_command(nem.cli)
cli.add_command(ontology.cli)
cli.add_command(ripple.cli)
cli.add_command(settings.cli)
cli.add_command(stellar.cli)

View File

@ -19,3 +19,4 @@ Tezos = 13 # type: Literal[13]
U2F = 14 # type: Literal[14]
Shamir = 15 # type: Literal[15]
ShamirGroups = 16 # type: Literal[16]
Ontology = 17 # type: Literal[17]

View File

@ -6,7 +6,7 @@ if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeCapability = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
EnumTypeCapability = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
EnumTypeBackupType = Literal[0, 1, 2]
except ImportError:
pass
@ -116,7 +116,7 @@ class Features(p.MessageType):
27: ('unfinished_backup', p.BoolType, 0),
28: ('no_backup', p.BoolType, 0),
29: ('recovery_mode', p.BoolType, 0),
30: ('capabilities', p.EnumType("Capability", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)), p.FLAG_REPEATED),
30: ('capabilities', p.EnumType("Capability", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)), p.FLAG_REPEATED),
31: ('backup_type', p.EnumType("BackupType", (0, 1, 2)), 0),
32: ('sd_card_present', p.BoolType, 0),
33: ('sd_protection', p.BoolType, 0),

View File

@ -127,6 +127,12 @@ CardanoGetAddress = 307 # type: Literal[307]
CardanoAddress = 308 # type: Literal[308]
CardanoTxAck = 309 # type: Literal[309]
CardanoSignedTx = 310 # type: Literal[310]
OntologyGetAddress = 350 # type: Literal[350]
OntologyAddress = 351 # type: Literal[351]
OntologyGetPublicKey = 352 # type: Literal[352]
OntologyPublicKey = 353 # type: Literal[353]
OntologySignTx = 354 # type: Literal[354]
OntologySignedTx = 355 # type: Literal[355]
RippleGetAddress = 400 # type: Literal[400]
RippleAddress = 401 # type: Literal[401]
RippleSignTx = 402 # type: Literal[402]

View File

@ -0,0 +1,26 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyAddress(p.MessageType):
MESSAGE_WIRE_TYPE = 351
def __init__(
self,
address: str = None,
) -> None:
self.address = address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address', p.UnicodeType, 0),
}

View File

@ -0,0 +1,7 @@
# Automatically generated by pb2py
# fmt: off
if False:
from typing_extensions import Literal
ONT = 1 # type: Literal[1]
ONG = 2 # type: Literal[2]

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyGetAddress(p.MessageType):
MESSAGE_WIRE_TYPE = 350
def __init__(
self,
address_n: List[int] = None,
show_display: bool = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.show_display = show_display
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('show_display', p.BoolType, 0),
}

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyGetPublicKey(p.MessageType):
MESSAGE_WIRE_TYPE = 352
def __init__(
self,
address_n: List[int] = None,
show_display: bool = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.show_display = show_display
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('show_display', p.BoolType, 0),
}

View File

@ -0,0 +1,33 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
from .OntologyOntIdAttribute import OntologyOntIdAttribute
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdAddAttributes(p.MessageType):
def __init__(
self,
ont_id: str = None,
public_key: bytes = None,
ont_id_attributes: List[OntologyOntIdAttribute] = None,
) -> None:
self.ont_id = ont_id
self.public_key = public_key
self.ont_id_attributes = ont_id_attributes if ont_id_attributes is not None else []
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('ont_id', p.UnicodeType, 0),
2: ('public_key', p.BytesType, 0),
3: ('ont_id_attributes', OntologyOntIdAttribute, p.FLAG_REPEATED),
}

View File

@ -0,0 +1,31 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdAttribute(p.MessageType):
def __init__(
self,
key: str = None,
type: str = None,
value: str = None,
) -> None:
self.key = key
self.type = type
self.value = value
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('key', p.UnicodeType, 0),
2: ('type', p.UnicodeType, 0),
3: ('value', p.UnicodeType, 0),
}

View File

@ -0,0 +1,28 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyOntIdRegister(p.MessageType):
def __init__(
self,
ont_id: str = None,
public_key: bytes = None,
) -> None:
self.ont_id = ont_id
self.public_key = public_key
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('ont_id', p.UnicodeType, 0),
2: ('public_key', p.BytesType, 0),
}

View File

@ -0,0 +1,26 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyPublicKey(p.MessageType):
MESSAGE_WIRE_TYPE = 353
def __init__(
self,
public_key: bytes = None,
) -> None:
self.public_key = public_key
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('public_key', p.BytesType, 0),
}

View File

@ -0,0 +1,47 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
from .OntologyOntIdAddAttributes import OntologyOntIdAddAttributes
from .OntologyOntIdRegister import OntologyOntIdRegister
from .OntologyTransaction import OntologyTransaction
from .OntologyTransfer import OntologyTransfer
from .OntologyWithdrawOng import OntologyWithdrawOng
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologySignTx(p.MessageType):
MESSAGE_WIRE_TYPE = 354
def __init__(
self,
address_n: List[int] = None,
transaction: OntologyTransaction = None,
transfer: OntologyTransfer = None,
withdraw_ong: OntologyWithdrawOng = None,
ont_id_register: OntologyOntIdRegister = None,
ont_id_add_attributes: OntologyOntIdAddAttributes = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.transaction = transaction
self.transfer = transfer
self.withdraw_ong = withdraw_ong
self.ont_id_register = ont_id_register
self.ont_id_add_attributes = ont_id_add_attributes
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('transaction', OntologyTransaction, 0),
3: ('transfer', OntologyTransfer, 0),
4: ('withdraw_ong', OntologyWithdrawOng, 0),
5: ('ont_id_register', OntologyOntIdRegister, 0),
6: ('ont_id_add_attributes', OntologyOntIdAddAttributes, 0),
}

View File

@ -0,0 +1,29 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologySignedTx(p.MessageType):
MESSAGE_WIRE_TYPE = 355
def __init__(
self,
signature: bytes = None,
payload: bytes = None,
) -> None:
self.signature = signature
self.payload = payload
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('signature', p.BytesType, 0),
2: ('payload', p.BytesType, 0),
}

View File

@ -0,0 +1,45 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
from .OntologyTxAttribute import OntologyTxAttribute
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyTransaction(p.MessageType):
def __init__(
self,
version: int = None,
type: int = None,
nonce: int = None,
gas_price: int = None,
gas_limit: int = None,
payer: str = None,
tx_attributes: List[OntologyTxAttribute] = None,
) -> None:
self.version = version
self.type = type
self.nonce = nonce
self.gas_price = gas_price
self.gas_limit = gas_limit
self.payer = payer
self.tx_attributes = tx_attributes if tx_attributes is not None else []
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('version', p.UVarintType, 0),
2: ('type', p.UVarintType, 0),
3: ('nonce', p.UVarintType, 0),
4: ('gas_price', p.UVarintType, 0),
5: ('gas_limit', p.UVarintType, 0),
6: ('payer', p.UnicodeType, 0),
7: ('tx_attributes', OntologyTxAttribute, p.FLAG_REPEATED),
}

View File

@ -0,0 +1,35 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeOntologyAsset = Literal[1, 2]
except ImportError:
pass
class OntologyTransfer(p.MessageType):
def __init__(
self,
asset: EnumTypeOntologyAsset = None,
amount: int = None,
from_address: str = None,
to_address: str = None,
) -> None:
self.asset = asset
self.amount = amount
self.from_address = from_address
self.to_address = to_address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('asset', p.EnumType("OntologyAsset", (1, 2)), 0),
2: ('amount', p.UVarintType, 0),
3: ('from_address', p.UnicodeType, 0),
4: ('to_address', p.UnicodeType, 0),
}

View File

@ -0,0 +1,28 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyTxAttribute(p.MessageType):
def __init__(
self,
usage: int = None,
data: bytes = None,
) -> None:
self.usage = usage
self.data = data
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('usage', p.UVarintType, 0),
2: ('data', p.BytesType, 0),
}

View File

@ -0,0 +1,31 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class OntologyWithdrawOng(p.MessageType):
def __init__(
self,
amount: int = None,
from_address: str = None,
to_address: str = None,
) -> None:
self.amount = amount
self.from_address = from_address
self.to_address = to_address
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('amount', p.UVarintType, 0),
2: ('from_address', p.UnicodeType, 0),
3: ('to_address', p.UnicodeType, 0),
}

View File

@ -190,6 +190,19 @@ from .NEMSignedTx import NEMSignedTx
from .NEMTransactionCommon import NEMTransactionCommon
from .NEMTransfer import NEMTransfer
from .NextU2FCounter import NextU2FCounter
from .OntologyAddress import OntologyAddress
from .OntologyGetAddress import OntologyGetAddress
from .OntologyGetPublicKey import OntologyGetPublicKey
from .OntologyOntIdAddAttributes import OntologyOntIdAddAttributes
from .OntologyOntIdAttribute import OntologyOntIdAttribute
from .OntologyOntIdRegister import OntologyOntIdRegister
from .OntologyPublicKey import OntologyPublicKey
from .OntologySignTx import OntologySignTx
from .OntologySignedTx import OntologySignedTx
from .OntologyTransaction import OntologyTransaction
from .OntologyTransfer import OntologyTransfer
from .OntologyTxAttribute import OntologyTxAttribute
from .OntologyWithdrawOng import OntologyWithdrawOng
from .PassphraseAck import PassphraseAck
from .PassphraseRequest import PassphraseRequest
from .PassphraseStateAck import PassphraseStateAck
@ -277,6 +290,7 @@ from . import NEMImportanceTransferMode
from . import NEMModificationType
from . import NEMMosaicLevy
from . import NEMSupplyChangeType
from . import OntologyAsset
from . import OutputScriptType
from . import PassphraseSourceType
from . import PinMatrixRequestType

View File

@ -0,0 +1,66 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
from . import messages
from .tools import expect
#
# Ontology functions
#
@expect(messages.OntologyAddress, field="address")
def get_address(client, address_n, show_display=False):
return client.call(
messages.OntologyGetAddress(address_n=address_n, show_display=show_display)
)
@expect(messages.OntologyPublicKey)
def get_public_key(client, address_n, show_display=False):
return client.call(
messages.OntologyGetPublicKey(address_n=address_n, show_display=show_display)
)
@expect(messages.OntologySignedTx)
def sign_transfer(client, address_n, t, tr):
return client.call(
messages.OntologySignTx(address_n=address_n, transaction=t, transfer=tr)
)
@expect(messages.OntologySignedTx)
def sign_withdrawal(client, address_n, t, w):
return client.call(
messages.OntologySignTx(address_n=address_n, transaction=t, withdraw_ong=w)
)
@expect(messages.OntologySignedTx)
def sign_register(client, address_n, t, r):
return client.call(
messages.OntologySignTx(address_n=address_n, transaction=t, ont_id_register=r)
)
@expect(messages.OntologySignedTx)
def sign_add_attr(client, address_n, t, a):
return client.call(
messages.OntologySignTx(
address_n=address_n, transaction=t, ont_id_add_attributes=a
)
)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,41 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from trezorlib import ontology
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologyGetaddress:
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_get_ont_address(self, client):
assert (
ontology.get_address(client, parse_path("m/44'/1024'/0'/0/0"))
== "ANzeepWmi9hoLBA3UiwVhUm7Eku196VUHk"
)
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_get_neo_address(self, client):
assert (
ontology.get_address(client, parse_path("m/44'/888'/0'/0/0"))
== "AZEMburLePcdfqBFnVfdbsXKiBSnmtgFZr"
)

View File

@ -0,0 +1,77 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_sign_ont_id_add_attributes(client):
with client:
client.set_input_flow(input_flow(client, num_pages=2))
transaction = messages.OntologyTransaction(
version=0x00,
nonce=0x7F7F1CEB,
type=0xD1,
gas_price=500,
gas_limit=30000,
payer="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
tx_attributes=[],
)
ont_id_add_attributes = messages.OntologyOntIdAddAttributes(
ont_id="did:ont:AGVn4NZNEQ7RawHTDxjaTjZ3R8h8q1aq9h",
public_key=bytes.fromhex(
"03a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa33"
),
ont_id_attributes=[
messages.OntologyOntIdAttribute(
key="firstName", type="json", value="John Sheppard"
)
],
)
signature = ontology.sign_add_attr(
client, parse_path("m/44'/1024'/0'/0/0"), transaction, ont_id_add_attributes
)
assert (
signature.payload.hex()
== "bd00c66b2a6469643a6f6e743a4147566e344e5a4e455137526177485444786a61546a5a33523868387131617139686a7cc8516a7cc80966697273744e616d656a7cc8046a736f6e6a7cc80d4a6f686e2053686570706172646a7cc82103a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa336a7cc86c0d616464417474726962757465731400000000000000000000000000000000000000030068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert (
signature.signature.hex()
== "01c256dc16d88685fd6652d69b808059f7ed30edadb0ccfe51802702b94b65500922f9ea80e0fd7b77b5c51515e3bc43a495b3e98fb3adb82a0ab5dd47169fcf4e"
)
def input_flow(client, num_pages):
yield
time.sleep(1)
for _ in range(num_pages - 1):
client.debug.swipe_down()
time.sleep(1)
client.debug.press_yes()

View File

@ -0,0 +1,70 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
@pytest.mark.skip(reason="bad testing data")
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_sign_ont_id_register(client):
client.set_input_flow(input_flow(client, num_pages=2))
transaction = messages.OntologyTransaction(
version=0x00,
nonce=0x7F7F1CEB,
type=0xD1,
gas_price=500,
gas_limit=30000,
payer="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
tx_attributes=[],
)
ont_id_register = messages.OntologyOntIdRegister(
ont_id="did:ont:AGVn4NZNEQ7RawHTDxjaTjZ3R8h8q1aq9h",
public_key=bytes.fromhex(
"03a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa33"
),
)
signature = ontology.sign_add_attr(
client, parse_path("m/44'/1024'/0'/0/0"), transaction, ont_id_register
)
assert (
signature.payload.hex()
== "9800c66b2a6469643a6f6e743a4147566e344e5a4e455137526177485444786a61546a5a33523868387131617139686a7cc82103a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa336a7cc86c127265674944576974685075626c69634b65791400000000000000000000000000000000000000030068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert (
signature.signature.hex()
== "015d6abe231352d1ab32f0b0de0222cfb9a7a13f467a2bf8a369b61aa1f933dc3a6a2ba7831c8a15984fe0958d24cbca05d8e0736510c1734d773145ce3eac9e9b"
)
def input_flow(client, num_pages):
yield
time.sleep(1)
for _ in range(num_pages - 1):
client.debug.swipe_down()
time.sleep(1)
client.debug.press_yes()

View File

@ -0,0 +1,92 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
ONTOLOGY_TEST_MNEMONIC = "immune annual decorate major humble surprise dismiss trend edit suit alert uncover release transfer suit torch small timber lock mind tomorrow north lend diet"
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_sign_transfer_ont(client):
transaction = messages.OntologyTransaction(
version=0x00,
nonce=0x7F7F1CEB,
type=0xD1,
gas_price=500,
gas_limit=30000,
payer="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
tx_attributes=[],
)
transfer = messages.OntologyTransfer(
asset=1,
amount=100,
from_address="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
to_address="AcyLq3tokVpkMBMLALVMWRdVJ83TTgBUwU",
)
signature = ontology.sign_transfer(
client, parse_path("m/44'/1024'/0'/0/0"), transaction, transfer
)
assert (
signature.payload.hex()
== "7900c66b140b045b101bc9fabaf181e251a38e76b73962111b6a7cc814e885e849e7f545ea84e8c555b86c70e4f751c4ec6a7cc80864000000000000006a7cc86c51c1087472616e736665721400000000000000000000000000000000000000010068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert (
signature.signature.hex()
== "0102f9b0c43b2ed35aa89b0927a60e692cb8a74280c2da819a909150c8b3fd2b0b401806c97797fcc4b93d34f210ad01740cfd13b720a389a80f384c1f94fb749e"
)
# original test didn't work, had to replace with data from
# https://github.com/ontio/ontology-ts-sdk/blob/master/test/transfer.sign.test.ts
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
@pytest.mark.setup_client(mnemonic=ONTOLOGY_TEST_MNEMONIC)
def test_ontology_sign_transfer_ong(client):
transaction = messages.OntologyTransaction(
version=0x00,
nonce=0x7F7F1CEB,
type=0xD1,
gas_price=500,
gas_limit=30000,
payer="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
tx_attributes=[],
)
transfer = messages.OntologyTransfer(
asset=2,
amount=12000000,
from_address="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
to_address="AcyLq3tokVpkMBMLALVMWRdVJ83TTgBUwU",
)
signature = ontology.sign_transfer(
client, parse_path("m/44'/888'/0'/0/0"), transaction, transfer
)
assert (
signature.signature.hex()
== "017da1b8268e1272d7471eef58fa0884108073c09d5efdae0143da5d281019682e5a1562f1d76484eb0379e3febe7025a958bb14855107b9ad26daec2fee0119f4"
)

View File

@ -0,0 +1,56 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from ..common import MNEMONIC12
@pytest.mark.altcoin
@pytest.mark.ontology
@pytest.mark.skip_t1
@pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_ontology_sign_withdraw_ong(client):
transaction = messages.OntologyTransaction(
version=0x00,
nonce=0x7F7F1CEB,
type=0xD1,
gas_price=500,
gas_limit=30000,
payer="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
tx_attributes=[],
)
withdraw_ong = messages.OntologyWithdrawOng(
amount=12000000,
from_address="AGn8JFPGM5S4jkWhTC89Xtz1Y76sPz29Rc",
to_address="AcyLq3tokVpkMBMLALVMWRdVJ83TTgBUwU",
)
signature = ontology.sign_withdrawal(
client, parse_path("m/44'/1024'/0'/0/0"), transaction, withdraw_ong
)
assert (
signature.payload.hex()
== "9300c66b140b045b101bc9fabaf181e251a38e76b73962111b6a7cc81400000000000000000000000000000000000000016a7cc814e885e849e7f545ea84e8c555b86c70e4f751c4ec6a7cc808001bb700000000006a7cc86c0c7472616e7366657246726f6d1400000000000000000000000000000000000000020068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert (
signature.signature.hex()
== "01a44355ac4549a021ecc571eb85ffb6ae4ff50cffc416ec55df40cad538fa55c64386167df2fb6b3fa9e698ebe265088839667b88da7e599ce7df679b0d5dfe60"
)

View File

@ -17,6 +17,7 @@ CORE_PROTOBUF_SOURCES="\
$PROTOB/messages-management.proto \
$PROTOB/messages-monero.proto \
$PROTOB/messages-nem.proto \
$PROTOB/messages-ontology.proto \
$PROTOB/messages-ripple.proto \
$PROTOB/messages-stellar.proto \
$PROTOB/messages-tezos.proto \
@ -73,12 +74,13 @@ do_rebuild() {
sed -i "3ifrom trezor import utils\n" "$DESTDIR"/Capability.py
sed -i "3ifrom trezor import utils\n" "$DESTDIR"/MessageType.py
sed -i "/^EthereumGetPublicKey/iif not utils.BITCOIN_ONLY:" "$DESTDIR"/MessageType.py
for altcoin in Ethereum NEM Lisk Tezos Stellar Cardano Ripple Monero DebugMonero Eos Binance WebAuthn; do
for altcoin in Ethereum NEM Lisk Tezos Stellar Cardano Ripple Monero DebugMonero Eos Binance WebAuthn Ontology; do
sed -i "s:^$altcoin: $altcoin:" "$DESTDIR"/Capability.py
sed -i "s:^$altcoin: $altcoin:" "$DESTDIR"/MessageType.py
done
sed -i "/^Bitcoin_like/iif not utils.BITCOIN_ONLY:" "$DESTDIR"/Capability.py
sed -i "/^EOS/iif not utils.BITCOIN_ONLY:" "$DESTDIR"/Capability.py
sed -i "/Ontology/iif not utils.BITCOIN_ONLY:" "$DESTDIR"/Capability.py
for feature in Bitcoin_like EOS U2F; do
sed -i "s:^$feature: $feature:" "$DESTDIR"/Capability.py
done