Skip to content
This repository has been archived by the owner on Jun 5, 2019. It is now read-only.

Ripple support #286

Merged
merged 7 commits into from
Jul 12, 2018
Merged

Ripple support #286

merged 7 commits into from
Jul 12, 2018

Conversation

tsusanka
Copy link
Contributor

This introduces support for Ripple, which is coming to trezor-core.

I wasn't sure about the API, so I've done it in the similar way as Stellar's. So the signing command takes a dict as an argument consisting of the fields. I'm not sure it is ideal though, so let me know what you think.

@matejcik
Copy link
Contributor

quick notes:

  • please don't use import messages as proto anymore, i'm getting rid of that weirdness
  • please move ripple methods from client to ripple.py; take a look at preliminary: TrezorClient split #276, that's how it's supposed to look in the future (except you don't need the MoveTo adapters because you're creating new functions)



def validate(transaction):
if False in (k in transaction for k in ("Fee", "Sequence", "TransactionType", "Amount", "Destination")):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not all(k in transaction for k in (...)):

also maybe:

if not all(transaction.get(k) for k in (...)):

to check truthiness of the actual values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, so your second option it is

if "Flags" in transaction:
msg.flags = transaction["Flags"]
if "LastLedgerSequence" in transaction:
msg.last_ledger_sequence = transaction["LastLedgerSequence"]
Copy link
Contributor

@matejcik matejcik Jul 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead:

return messages.RippleSignTx(
	fee=transaction["Fee"],
	sequence=transaction["Sequence"],
	flags=transaction.get("Flags"),
	last_ledger_sequence=transaction.get("LastLedgerSequence"),
	payment=create_payment(transaction),
)

(perhaps use get() for the first two as well, for consistency)

the dict.get method will return None if key is missing, so you don't need the if check.

also maybe validate(transaction) within this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, fixed

msg = proto.RipplePayment()
msg.amount = transaction["Amount"]
msg.destination = transaction["Destination"]
return msg
Copy link
Contributor

@matejcik matejcik Jul 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd also put the properties in constructor (same as above), if they are just items from the dict

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@expect(proto.RippleSignedTx)
def ripple_sign_tx(self, n, transaction):
ripple.validate(transaction)
n = self._convert_prime(n)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no more _convert_prime please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should use tools.parse_path(n) right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but not here. the n should already be the output of parse_path, that part is correct


import base64
import struct
import xdrlib
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't seem to use xdrlib?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@matejcik
Copy link
Contributor

re API: where do you expect to get transaction data?
Stellar parses them out of a XDR blob and passes the protobuf objects directly, iirc. That's a reasonable thing to do IMHO. Here, I'd probably prefer that you called create_sign_tx outside the signing function, i.e., use create_sign_tx to "decode" whatever the actual input data and only then call ripple.sign_tx.

I'm probably going to modify Lisk and NEM (which take dicts) to work similarly.

@tsusanka
Copy link
Contributor Author

tsusanka commented Jul 12, 2018

re API: where do you expect to get transaction data?

Yeah, this is something I've wanted to discuss with you. I guess there are three options how the input data can be provided:

  1. Because we support only a simple payment scenario, I was considering an option where the user provides the actual arguments directly in a similar way it is for Ethereum. So the command line api would look like this:

ripple_sign_transaction(self, address_n, destination, amount, fee, sequence, flags=None, last_sequence=None)

This has one serious disadvantage that when the other transaction types are introduced, we'll have to change this API. So maybe it's not a good idea.

  1. Provide the input data as a serialized unsigned transaction. This makes sense, but we'd have to include yet another serialization format - the Ripple's binary format, because of course they're not using something common.

  2. Provide the input data as a JSON-like dictionary. This will resemble the official Ripple API, see here for an example of a Payment transaction JSON. So my idea is, the user would provide this struct. Because we do not want to parse JSON, it would be a simple dict. That's basically how it is done now. But of course, JSON != python's dict, so I'm not sure if we shouldn't address that somehow as well.

@tsusanka
Copy link
Contributor Author

tsusanka commented Jul 12, 2018

please move ripple methods from client to ripple.py; take a look at #276, that's how it's supposed to look in the future (except you don't need the MoveTo adapters because you're creating new functions)

Ok, I'll move the methods to ripple.py. How do I register it in the client? Should I do in the client.py something like

def ripple_sign_tx(self, n, transaction):
	return ripple.sign_tx(n, transaction)

or ...?

@matejcik
Copy link
Contributor

re "register in client" - don't do that at all .) users are expected to from trezorlib import ripple and then ripple.sign_tx(client, ...)

@matejcik
Copy link
Contributor

re API: why not "provide data as protobuf objects"?
then we can have ripple.binary_to_proto to decode the binary format, and/or riple.dict_to_proto to decode the JSON-like input

@tsusanka
Copy link
Contributor Author

Discussed in person. We'll load the transaction data from a json file and then parse into protobuf. The sign_tx function will accept the protobuf messages

@tsusanka
Copy link
Contributor Author

@matejcik I think this is done from my side. Let me know if I forgot something.


@field('address')
@expect(messages.RippleAddress)
def ripple_get_address(client, address_n, show_display=False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename to get_address



@expect(messages.RippleSignedTx)
def ripple_sign_tx(client, address_n, msg: messages.RippleSignTx):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename to sign_tx

@matejcik
Copy link
Contributor

last thing (function names), otherwise LGTM

@tsusanka
Copy link
Contributor Author

Good idea. Done.

@matejcik matejcik added this to the next milestone Jul 12, 2018
@matejcik matejcik merged commit 61e63c6 into master Jul 12, 2018
@matejcik
Copy link
Contributor

and done.
thank you, please delete the branch when you're done here :)

@tsusanka tsusanka deleted the tsusanka/ripple branch July 12, 2018 14:37
@tsusanka tsusanka mentioned this pull request Aug 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants