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:
parent
11d80f0f20
commit
23df799e77
@ -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 $@
|
||||
|
@ -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
|
||||
|
134
common/protob/messages-ontology.proto
Normal file
134
common/protob/messages-ontology.proto
Normal 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;
|
||||
}
|
@ -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];
|
||||
|
@ -61,6 +61,7 @@ def get_features() -> Features:
|
||||
Capability.Lisk,
|
||||
Capability.Monero,
|
||||
Capability.NEM,
|
||||
Capability.Ontology,
|
||||
Capability.Ripple,
|
||||
Capability.Stellar,
|
||||
Capability.Tezos,
|
||||
|
16
core/src/apps/ontology/__init__.py
Normal file
16
core/src/apps/ontology/__init__.py
Normal 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)
|
9
core/src/apps/ontology/const.py
Normal file
9
core/src/apps/ontology/const.py
Normal 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"
|
||||
)
|
26
core/src/apps/ontology/get_address.py
Normal file
26
core/src/apps/ontology/get_address.py
Normal 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)
|
20
core/src/apps/ontology/get_public_key.py
Normal file
20
core/src/apps/ontology/get_public_key.py
Normal 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)
|
44
core/src/apps/ontology/helpers.py
Normal file
44
core/src/apps/ontology/helpers.py
Normal 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
|
61
core/src/apps/ontology/layout.py
Normal file
61
core/src/apps/ontology/layout.py
Normal 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))
|
51
core/src/apps/ontology/sc/builder.py
Normal file
51
core/src/apps/ontology/sc/builder.py
Normal 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)
|
120
core/src/apps/ontology/sc/native_builder.py
Normal file
120
core/src/apps/ontology/sc/native_builder.py
Normal 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
|
31
core/src/apps/ontology/sc/opcode.py
Normal file
31
core/src/apps/ontology/sc/opcode.py
Normal 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
|
104
core/src/apps/ontology/serialize.py
Normal file
104
core/src/apps/ontology/serialize.py
Normal 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)
|
125
core/src/apps/ontology/sign_tx.py
Normal file
125
core/src/apps/ontology/sign_tx.py
Normal 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)
|
22
core/src/apps/ontology/writer.py
Normal file
22
core/src/apps/ontology/writer.py
Normal 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)
|
@ -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()
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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),
|
||||
|
@ -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]
|
||||
|
26
core/src/trezor/messages/OntologyAddress.py
Normal file
26
core/src/trezor/messages/OntologyAddress.py
Normal 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),
|
||||
}
|
7
core/src/trezor/messages/OntologyAsset.py
Normal file
7
core/src/trezor/messages/OntologyAsset.py
Normal 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]
|
29
core/src/trezor/messages/OntologyGetAddress.py
Normal file
29
core/src/trezor/messages/OntologyGetAddress.py
Normal 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),
|
||||
}
|
29
core/src/trezor/messages/OntologyGetPublicKey.py
Normal file
29
core/src/trezor/messages/OntologyGetPublicKey.py
Normal 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),
|
||||
}
|
33
core/src/trezor/messages/OntologyOntIdAddAttributes.py
Normal file
33
core/src/trezor/messages/OntologyOntIdAddAttributes.py
Normal 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),
|
||||
}
|
31
core/src/trezor/messages/OntologyOntIdAttribute.py
Normal file
31
core/src/trezor/messages/OntologyOntIdAttribute.py
Normal 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),
|
||||
}
|
28
core/src/trezor/messages/OntologyOntIdRegister.py
Normal file
28
core/src/trezor/messages/OntologyOntIdRegister.py
Normal 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),
|
||||
}
|
26
core/src/trezor/messages/OntologyPublicKey.py
Normal file
26
core/src/trezor/messages/OntologyPublicKey.py
Normal 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),
|
||||
}
|
47
core/src/trezor/messages/OntologySignTx.py
Normal file
47
core/src/trezor/messages/OntologySignTx.py
Normal 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),
|
||||
}
|
29
core/src/trezor/messages/OntologySignedTx.py
Normal file
29
core/src/trezor/messages/OntologySignedTx.py
Normal 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),
|
||||
}
|
45
core/src/trezor/messages/OntologyTransaction.py
Normal file
45
core/src/trezor/messages/OntologyTransaction.py
Normal 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),
|
||||
}
|
35
core/src/trezor/messages/OntologyTransfer.py
Normal file
35
core/src/trezor/messages/OntologyTransfer.py
Normal 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),
|
||||
}
|
28
core/src/trezor/messages/OntologyTxAttribute.py
Normal file
28
core/src/trezor/messages/OntologyTxAttribute.py
Normal 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),
|
||||
}
|
31
core/src/trezor/messages/OntologyWithdrawOng.py
Normal file
31
core/src/trezor/messages/OntologyWithdrawOng.py
Normal 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),
|
||||
}
|
193
python/src/trezorlib/cli/ontology.py
Normal file
193
python/src/trezorlib/cli/ontology.py
Normal 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
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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),
|
||||
|
@ -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]
|
||||
|
26
python/src/trezorlib/messages/OntologyAddress.py
Normal file
26
python/src/trezorlib/messages/OntologyAddress.py
Normal 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),
|
||||
}
|
7
python/src/trezorlib/messages/OntologyAsset.py
Normal file
7
python/src/trezorlib/messages/OntologyAsset.py
Normal 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]
|
29
python/src/trezorlib/messages/OntologyGetAddress.py
Normal file
29
python/src/trezorlib/messages/OntologyGetAddress.py
Normal 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),
|
||||
}
|
29
python/src/trezorlib/messages/OntologyGetPublicKey.py
Normal file
29
python/src/trezorlib/messages/OntologyGetPublicKey.py
Normal 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),
|
||||
}
|
33
python/src/trezorlib/messages/OntologyOntIdAddAttributes.py
Normal file
33
python/src/trezorlib/messages/OntologyOntIdAddAttributes.py
Normal 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),
|
||||
}
|
31
python/src/trezorlib/messages/OntologyOntIdAttribute.py
Normal file
31
python/src/trezorlib/messages/OntologyOntIdAttribute.py
Normal 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),
|
||||
}
|
28
python/src/trezorlib/messages/OntologyOntIdRegister.py
Normal file
28
python/src/trezorlib/messages/OntologyOntIdRegister.py
Normal 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),
|
||||
}
|
26
python/src/trezorlib/messages/OntologyPublicKey.py
Normal file
26
python/src/trezorlib/messages/OntologyPublicKey.py
Normal 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),
|
||||
}
|
47
python/src/trezorlib/messages/OntologySignTx.py
Normal file
47
python/src/trezorlib/messages/OntologySignTx.py
Normal 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),
|
||||
}
|
29
python/src/trezorlib/messages/OntologySignedTx.py
Normal file
29
python/src/trezorlib/messages/OntologySignedTx.py
Normal 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),
|
||||
}
|
45
python/src/trezorlib/messages/OntologyTransaction.py
Normal file
45
python/src/trezorlib/messages/OntologyTransaction.py
Normal 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),
|
||||
}
|
35
python/src/trezorlib/messages/OntologyTransfer.py
Normal file
35
python/src/trezorlib/messages/OntologyTransfer.py
Normal 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),
|
||||
}
|
28
python/src/trezorlib/messages/OntologyTxAttribute.py
Normal file
28
python/src/trezorlib/messages/OntologyTxAttribute.py
Normal 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),
|
||||
}
|
31
python/src/trezorlib/messages/OntologyWithdrawOng.py
Normal file
31
python/src/trezorlib/messages/OntologyWithdrawOng.py
Normal 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),
|
||||
}
|
@ -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
|
||||
|
66
python/src/trezorlib/ontology.py
Normal file
66
python/src/trezorlib/ontology.py
Normal 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
|
||||
)
|
||||
)
|
1
python/trezorlib/coins.json
Normal file
1
python/trezorlib/coins.json
Normal file
File diff suppressed because one or more lines are too long
41
tests/device_tests/test_msg_ontology_getaddress.py
Normal file
41
tests/device_tests/test_msg_ontology_getaddress.py
Normal 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"
|
||||
)
|
@ -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()
|
70
tests/device_tests/test_msg_ontology_sign_ont_id_register.py
Normal file
70
tests/device_tests/test_msg_ontology_sign_ont_id_register.py
Normal 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()
|
92
tests/device_tests/test_msg_ontology_sign_tx.py
Normal file
92
tests/device_tests/test_msg_ontology_sign_tx.py
Normal 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"
|
||||
)
|
56
tests/device_tests/test_msg_ontology_sign_withdraw_ong.py
Normal file
56
tests/device_tests/test_msg_ontology_sign_withdraw_ong.py
Normal 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"
|
||||
)
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user