1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

add Ontology support (#301)

* add Ontology support

Signed-off-by: Matus Zamborsky <zamborsky@gmail.com>
This commit is contained in:
Matus Zamborsky 2018-09-06 15:36:44 +02:00 committed by matejcik
parent 4f572f9e15
commit 21326d3a41
8 changed files with 643 additions and 0 deletions

View File

@ -48,6 +48,12 @@ Use the following command to see all options:
load_device Load custom configuration to the device.
nem_get_address Get NEM address for specified path.
nem_sign_tx Sign (and optionally broadcast) NEM...
ontology_get_address Get Ontology address for specified path.
ontology_get_public_key Get Ontology public key for specified path.
ontology_sign_transfer Sign Ontology Transfer...
ontology_sign_withdraw Sign Ontology Withdraw Ong...
ontology_sign_register Sign Ontology ONT ID Registration...
ontology_sign_add_attr Sign Ontology ONT ID Attributes adding...
ping Send ping message.
recovery_device Start safe recovery workflow.
reset_device Perform device setup and generate new seed.

204
trezorctl
View File

@ -44,6 +44,7 @@ from trezorlib import (
messages as proto,
misc,
nem,
ontology,
protobuf,
ripple,
stellar,
@ -1386,6 +1387,209 @@ def ripple_sign_tx(connect, address, file):
click.echo(binascii.hexlify(result.serialized_tx))
#
# Ontology functions
#
@cli.command(help="Get Ontology address for specified path.")
@click.option(
"-n", "--address", required=True, help="BIP-32 path, e.g. m/44'/888'/0'/0/0"
)
@click.option("-d", "--show-display", is_flag=True)
@click.pass_obj
def ontology_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="BIP-32 path, e.g. m/44'/888'/0'/0/0"
)
@click.option("-d", "--show-display", is_flag=True)
@click.pass_obj
def ontology_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 binascii.hexlify(result.public_key).decode()
@cli.command(help="Sign Ontology transfer.")
@click.option(
"-n",
"--address",
required=True,
help="BIP-32 path to signing key, e.g. m/44'/888'/0'/0/0",
)
@click.option(
"-tx",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-tr",
"--transfer",
type=click.File("r"),
default="-",
help="Transfer in JSON format",
)
@click.pass_obj
def ontology_sign_transfer(connect, address, transaction_f, transfer_f):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
proto.OntologyTransaction, json.load(transaction_f)
)
transfer = protobuf.dict_to_proto(proto.OntologyTransfer, json.load(transfer_f))
result = ontology.sign_transfer(client, address_n, transaction, transfer)
output = {
"payload": binascii.hexlify(result.payload).decode(),
"signature": binascii.hexlify(result.signature).decode(),
}
return output
@cli.command(help="Sign Ontology withdraw Ong.")
@click.option(
"-n",
"--address",
required=True,
help="BIP-32 path to signing key, e.g. m/44'/888'/0'/0/0",
)
@click.option(
"-tx",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-wi",
"--withdraw_ong",
type=click.File("r"),
default="-",
help="Withdrawal in JSON format",
)
@click.pass_obj
def ontology_sign_withdraw_ong(connect, address, transaction_f, withdraw_ong_f):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
proto.OntologyTransaction, json.load(transaction_f)
)
withdraw_ong = protobuf.dict_to_proto(
proto.OntologyWithdrawOng, json.load(withdraw_ong_f)
)
result = ontology.sign_withdrawal(client, address_n, transaction, withdraw_ong)
output = {
"payload": binascii.hexlify(result.payload).decode(),
"signature": binascii.hexlify(result.signature).decode(),
}
return output
@cli.command(help="Sign Ontology ONT ID Registration.")
@click.option(
"-n",
"--address",
required=True,
help="BIP-32 path to signing key, e.g. m/44'/888'/0'/0/0",
)
@click.option(
"-tx",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-re",
"--register",
type=click.File("r"),
default="-",
help="Register in JSON format",
)
@click.argument("transaction")
@click.argument("ont_id_register")
@click.pass_obj
def ontology_sign_ont_id_register(connect, address, transaction_f, ont_id_register_f):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
proto.OntologyTransaction, json.load(transaction_f)
)
ont_id_register = protobuf.dict_to_proto(
proto.OntologyOntIdRegister, json.load(ont_id_register_f)
)
result = ontology.sign_register(client, address_n, transaction, ont_id_register)
output = {
"payload": binascii.hexlify(result.payload).decode(),
"signature": binascii.hexlify(result.signature).decode(),
}
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(
"-tx",
"--transaction",
type=click.File("r"),
default="-",
help="Transaction in JSON format",
)
@click.option(
"-aa",
"--add_attr",
type=click.File("r"),
default="-",
help="Add attributes in JSON format",
)
@click.pass_obj
def ontology_sign_ont_id_add_attributes(
connect, address, transaction_f, ont_id_add_attributes_f
):
client = connect()
address_n = tools.parse_path(address)
transaction = protobuf.dict_to_proto(
proto.OntologyTransaction, json.load(transaction_f)
)
ont_id_add_attributes = protobuf.dict_to_proto(
proto.OntologyOntIdAddAttributes, json.load(ont_id_add_attributes_f)
)
result = ontology.sign_add_attr(
client, address_n, transaction, ont_id_add_attributes
)
output = {
"payload": binascii.hexlify(result.payload).decode(),
"signature": binascii.hexlify(result.signature).decode(),
}
return output
#
# Main
#

71
trezorlib/ontology.py Normal file
View File

@ -0,0 +1,71 @@
# 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.OntologySignedTransfer)
def sign_transfer(client, address_n, t, tr):
return client.call(
messages.OntologySignTransfer(address_n=address_n, transaction=t, transfer=tr)
)
@expect(messages.OntologySignedWithdrawOng)
def sign_withdrawal(client, address_n, t, w):
return client.call(
messages.OntologySignWithdrawOng(
address_n=address_n, transaction=t, withdraw_ong=w
)
)
@expect(messages.OntologySignedOntIdRegister)
def sign_register(client, address_n, t, r):
return client.call(
messages.OntologySignOntIdRegister(
address_n=address_n, transaction=t, ont_id_register=r
)
)
@expect(messages.OntologySignedOntIdAddAttributes)
def sign_add_attr(client, address_n, t, a):
return client.call(
messages.OntologySignOntIdAddAttributes(
address_n=address_n, transaction=t, ont_id_add_attributes=a
)
)

View File

@ -0,0 +1,43 @@
# 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 TrezorTest
@pytest.mark.xfail
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologyGetaddress(TrezorTest):
def test_ontology_get_ont_address(self):
self.setup_mnemonic_nopin_nopassphrase()
assert (
ontology.get_address(self.client, parse_path("m/44'/1024'/0'/0/0"))
== "ANzeepWmi9hoLBA3UiwVhUm7Eku196VUHk"
)
def test_ontology_get_neo_address(self):
self.setup_mnemonic_nopin_nopassphrase()
assert (
ontology.get_address(self.client, parse_path("m/44'/888'/0'/0/0"))
== "AZEMburLePcdfqBFnVfdbsXKiBSnmtgFZr"
)

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 time
from binascii import unhexlify
import pytest
from trezorlib import messages
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.xfail
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologySignOntIdAddAttributes(TrezorTest):
def test_ontology_sign_ont_id_add_attributes(self):
self.setup_mnemonic_nopin_nopassphrase()
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=unhexlify(
"03a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa33"
),
ont_id_attributes=[
messages.OntologyOntIdAttribute(
key="firstName", type="json", value="John Sheppard"
)
],
)
self.client.debug.swipe_down()
# not using ontology.sign_add_attr() because of swiping
signature = self._ontology_sign(
2, parse_path("m/44'/1024'/0'/0/0"), transaction, ont_id_add_attributes
)
assert signature.payload == unhexlify(
"bd00c66b2a6469643a6f6e743a4147566e344e5a4e455137526177485444786a61546a5a33523868387131617139686a7cc8516a7cc80966697273744e616d656a7cc8046a736f6e6a7cc80d4a6f686e2053686570706172646a7cc82103a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa336a7cc86c0d616464417474726962757465731400000000000000000000000000000000000000030068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert signature.signature == unhexlify(
"01c256dc16d88685fd6652d69b808059f7ed30edadb0ccfe51802702b94b65500922f9ea80e0fd7b77b5c51515e3bc43a495b3e98fb3adb82a0ab5dd47169fcf4e"
)
def _ontology_sign(
self, num_of_swipes, address_n, transaction, ont_id_add_attributes
):
# Sending Ontology message
msg = messages.OntologySignOntIdAddAttributes(
address_n=address_n,
transaction=transaction,
ont_id_add_attributes=ont_id_add_attributes,
)
self.client.transport.write(msg)
ret = self.client.transport.read()
# Confirm action
assert isinstance(ret, messages.ButtonRequest)
self.client.debug.press_yes()
self.client.transport.write(messages.ButtonAck())
time.sleep(1)
for _ in range(num_of_swipes):
self.client.debug.swipe_down()
time.sleep(1)
self.client.debug.press_yes()
return self.client.transport.read()

View File

@ -0,0 +1,83 @@
# 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
from binascii import unhexlify
import pytest
from trezorlib import messages
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.xfail
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologySignOntIdRegister(TrezorTest):
def test_ontology_sign_ont_id_register(self):
self.setup_mnemonic_nopin_nopassphrase()
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=unhexlify(
"03a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa33"
),
)
# not using ontology.sign_register() because of swiping
signature = self._ontology_sign(
1, parse_path("m/44'/1024'/0'/0/0"), transaction, ont_id_register
)
assert signature.payload == unhexlify(
"9800c66b2a6469643a6f6e743a4147566e344e5a4e455137526177485444786a61546a5a33523868387131617139686a7cc82103a8269b0dad311d98195e76729bc57003348a315fd17b6bf4f90ba8b86735fa336a7cc86c127265674944576974685075626c69634b65791400000000000000000000000000000000000000030068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert signature.signature == unhexlify(
"015d6abe231352d1ab32f0b0de0222cfb9a7a13f467a2bf8a369b61aa1f933dc3a6a2ba7831c8a15984fe0958d24cbca05d8e0736510c1734d773145ce3eac9e9b"
)
def _ontology_sign(self, num_of_swipes, address_n, transaction, ont_id_register):
# Sending Ontology message
msg = messages.OntologySignOntIdRegister(
address_n=address_n,
transaction=transaction,
ont_id_register=ont_id_register,
)
self.client.transport.write(msg)
ret = self.client.transport.read()
# Confirm action
assert isinstance(ret, messages.ButtonRequest)
self.client.debug.press_yes()
self.client.transport.write(messages.ButtonAck())
time.sleep(1)
for _ in range(num_of_swipes):
self.client.debug.swipe_down()
time.sleep(1)
self.client.debug.press_yes()
return self.client.transport.read()

View File

@ -0,0 +1,86 @@
# 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 binascii import unhexlify
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.xfail
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologySigntx(TrezorTest):
def test_ontology_sign_transfer_ont(self):
self.setup_mnemonic_nopin_nopassphrase()
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(
self.client, parse_path("m/44'/1024'/0'/0/0"), transaction, transfer
)
assert signature.payload == unhexlify(
"7900c66b140b045b101bc9fabaf181e251a38e76b73962111b6a7cc814e885e849e7f545ea84e8c555b86c70e4f751c4ec6a7cc80864000000000000006a7cc86c51c1087472616e736665721400000000000000000000000000000000000000010068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert signature.signature == unhexlify(
"0102f9b0c43b2ed35aa89b0927a60e692cb8a74280c2da819a909150c8b3fd2b0b401806c97797fcc4b93d34f210ad01740cfd13b720a389a80f384c1f94fb749e"
)
def test_ontology_sign_transfer_ong(self):
self.setup_mnemonic_nopin_nopassphrase()
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(
self.client, parse_path("m/44'/1024'/0'/0/0"), transaction, transfer
)
assert signature.signature == unhexlify(
"01ad88061a6cf5f4960cf9d311adb6dec4925d368b0fa9b7f56269f2a4078bea2367469af50c70260142d2ce3cc2d1e7fd0b2923df659c994412ff18f138438e9d"
)

View File

@ -0,0 +1,58 @@
# 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 binascii import unhexlify
import pytest
from trezorlib import messages, ontology
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.xfail
@pytest.mark.ontology
@pytest.mark.skip_t1
class TestMsgOntologySignWithdraw(TrezorTest):
def test_ontology_sign_withdraw_ong(self):
self.setup_mnemonic_nopin_nopassphrase()
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(
self.client, parse_path("m/44'/1024'/0'/0/0"), transaction, withdraw_ong
)
assert signature.payload == unhexlify(
"9300c66b140b045b101bc9fabaf181e251a38e76b73962111b6a7cc81400000000000000000000000000000000000000016a7cc814e885e849e7f545ea84e8c555b86c70e4f751c4ec6a7cc808001bb700000000006a7cc86c0c7472616e7366657246726f6d1400000000000000000000000000000000000000020068164f6e746f6c6f67792e4e61746976652e496e766f6b65"
)
assert signature.signature == unhexlify(
"01a44355ac4549a021ecc571eb85ffb6ae4ff50cffc416ec55df40cad538fa55c64386167df2fb6b3fa9e698ebe265088839667b88da7e599ce7df679b0d5dfe60"
)