Skip to content

Commit

Permalink
Merge branch 'master' into s/sonic-evm
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan authored Jan 27, 2025
2 parents 6d765b6 + 8b6c042 commit 0e50ff2
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 14 deletions.
36 changes: 24 additions & 12 deletions src/XRP/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace TW::Ripple {

const int NETWORK_PREFIX = 0x53545800;
const size_t CURRENCY_CODE_SIZE = 20;
const size_t CURRENCY_CODE_HEX_SIZE = CURRENCY_CODE_SIZE * 2;

Data Transaction::serialize() const {
// See https://xrpl.org/serialization.html
Expand Down Expand Up @@ -85,7 +87,7 @@ Data Transaction::serialize() const {
(transaction_type == TransactionType::NFTokenCreateOffer)) {
encodeType(FieldType::amount, 1, data);
append(data,
(currency_amount.currency.size() > 0) ?
(!currency_amount.currency.empty()) ?
serializeCurrencyAmount(currency_amount) :
serializeAmount(amount));
} else if (transaction_type == TransactionType::TrustSet) {
Expand Down Expand Up @@ -257,17 +259,7 @@ Data Transaction::serializeCurrencyAmount(const CurrencyAmount& currency_amount)
// https://xrpl.org/serialization.html#amount-fields
auto data = Data();
encode64BE(amount_cast.value, data);

// ISO-4217 currency code
encodeZeros(1, data); // type code (0x00)
encodeZeros(11, data); // reserved
if (currency_amount.currency.size() == 3) {
data.insert(data.end(), currency_amount.currency.begin(), currency_amount.currency.end());
} else {
encodeZeros(3, data); // none
}

encodeZeros(5, data); // reserved
serializeCurrencyCode(data, currency_amount.currency);
data.insert(data.end(), currency_amount.issuer.begin(), currency_amount.issuer.end());
return data;
}
Expand All @@ -278,4 +270,24 @@ Data Transaction::serializeAddress(Address address) {
return data;
}

void Transaction::serializeCurrencyCode(Data& out, const std::string& currency_code) {
if (currency_code.size() == CURRENCY_CODE_HEX_SIZE) {
auto code_bytes = parse_hex(currency_code);
out.insert(out.end(), code_bytes.begin(), code_bytes.end());
return;
}

// Standard ISO-4217 currency code
encodeZeros(1, out); // type code (0x00)
encodeZeros(11, out); // reserved

if (currency_code.size() == 3) {
out.insert(out.end(), currency_code.begin(), currency_code.end());
} else {
encodeZeros(3, out); // none
}

encodeZeros(5, out); // reserved
}

} // namespace TW::Ripple
5 changes: 3 additions & 2 deletions src/XRP/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Transaction {
/// See https://github.com/trezor/trezor-core/tree/master/src/apps/ripple#transactions
public:
struct CurrencyAmount {
Data currency;
std::string currency;
Data value;
Data issuer;
};
Expand Down Expand Up @@ -182,10 +182,11 @@ class Transaction {
static Data serializeAmount(int64_t p_amount);
static Data serializeCurrencyAmount(const CurrencyAmount& currency_amount);
static Data serializeAddress(Address address);
static void serializeCurrencyCode(Data& out, const std::string& currency_code);

private:
void setCurrencyAmount(CurrencyAmount& p_currency_amount, const std::string& p_currency, const std::string& p_value, const std::string& p_issuer) {
p_currency_amount.currency = Data(p_currency.begin(), p_currency.end());
p_currency_amount.currency = p_currency;
p_currency_amount.value = Data(p_value.begin(), p_value.end());
setAccount(p_issuer, p_currency_amount.issuer);
}
Expand Down
41 changes: 41 additions & 0 deletions tests/chains/XRP/TWAnySignerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ TEST(TWAnySignerRipple, SignTrustSetPayment) {
EXPECT_EQ(hex(output.encoded()), "12001422000000002401ec60b9201b01ec60ce63d4c38d7ea4c6800000000000000000000000000055534400000000004b4e9c06f24296074f7bc48f92a97916c6dc5ea968400000000000000a732103dc4a0dae2d550de7cace9c26c1a331a114e3e7efee5577204b476d27e2dc683a7446304402206ebcc7a689845df373dd2566cd3789862d426d9ad4e6a09c2d2772b57e82696a022066b1f217a0f0d834d167613a313f74097423a9ccd11f1ae7f90ffab0d2fc26b58114308ea8e515b64f2e6616a33b42e1bbb9fa00bbd2");
}

TEST(TWAnySignerRipple, SignTrustSetPaymentNonStandardCurrencyCode) {
// https://livenet.xrpl.org/transactions/31ABD41ECAD459BCD008DBA4377047413AEE7A965517DB240016B66A3F4A97E1
auto key = parse_hex("574e99f7946cfa2a6ca9368ca72fd37e42583cddb9ecc746aa4cb194ef4b2480");
Proto::SigningInput input;

input.mutable_op_trust_set()->mutable_limit_amount()->set_currency("524C555344000000000000000000000000000000");
input.mutable_op_trust_set()->mutable_limit_amount()->set_value("1000000000");
input.mutable_op_trust_set()->mutable_limit_amount()->set_issuer("rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De");
input.set_fee(500);
input.set_sequence(93674950);
input.set_last_ledger_sequence(187349950);
input.set_account("rDgEGKXWkHHr1HYq2ETnNAs9MdV4R8Gyt");
input.set_private_key(key.data(), key.size());

Proto::SigningOutput output;
ANY_SIGN(input, TWCoinTypeXRP);

EXPECT_EQ(hex(output.encoded()), "12001422000000002405955dc6201b0b2abbbe63d6c38d7ea4c68000524c555344000000000000000000000000000000e5e961c6a025c9404aa7b662dd1df975be75d13e6840000000000001f47321039c77e9329017ced5f8673ebafcd29687a1fff181140c030062fa77865688fc5d74473045022100aa5f7ffc2e11008a3fe98173c66360937cd3a72cb0951aa1b46ba32675c36b2d02206bc02de3a609e5c4b9e1510a6431a7d7efc0fba4ab9586d6595b86047e46bac281140265c09d122fab2a261a80ee59f1f4cd8fba8cf8");
}

TEST(TWAnySignerRipple, SignTokenPayment0) {
// https://testnet.xrpl.org/transactions/8F7820892294598B58CFA2E1101D15ED98C179B25A2BA6DAEB4F5B727CB00D4E
auto key = parse_hex("4ba5fd2ebf0f5d7e579b3c354c263ebb39cda4093845125786a280301af14e21");
Expand Down Expand Up @@ -119,6 +139,27 @@ TEST(TWAnySignerRipple, SignTokenPayment1) {
EXPECT_EQ(hex(output.encoded()), "12000022000000002401ec61e0201b01ec61f561d48a68d1c931200000000000000000000000000055534400000000004b4e9c06f24296074f7bc48f92a97916c6dc5ea968400000000000000a73210348c331ab218ba964150490c83875b06ccad2100b1f5707f296764712738cf1ca74473045022100a938783258d33e2e3e6099d1ab68fd85c3fd21adfa00e136a67bed8fddec6c9a02206cc6784c1f212f19dc939207643d361ceaa8334eb366722cf33b24dc7669dd7a81143a2f2f189d05abb8519cc9dee0e2dbc6fa53924183148132e4e20aecf29090ac428a9c43f230a829220d");
}

TEST(TWAnySignerRipple, SignTokenPaymentNonStandardCurrencyCode) {
// https://livenet.xrpl.org/transactions/6A1229450BB795E450C4AFAA7B72B58962621C0B8760372634796B3941718BFB
auto key = parse_hex("574e99f7946cfa2a6ca9368ca72fd37e42583cddb9ecc746aa4cb194ef4b2480");
Proto::SigningInput input;

input.mutable_op_payment()->mutable_currency_amount()->set_currency("524C555344000000000000000000000000000000");
input.mutable_op_payment()->mutable_currency_amount()->set_value("1");
input.mutable_op_payment()->mutable_currency_amount()->set_issuer("rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De");
input.mutable_op_payment()->set_destination("r4oPb529jpRA1tVTDARmBuZPYB2CJjKFac");
input.set_fee(12);
input.set_sequence(93674951);
input.set_last_ledger_sequence(187349950);
input.set_account("rDgEGKXWkHHr1HYq2ETnNAs9MdV4R8Gyt");
input.set_private_key(key.data(), key.size());

Proto::SigningOutput output;
ANY_SIGN(input, TWCoinTypeXRP);

EXPECT_EQ(hex(output.encoded()), "12000022000000002405955dc7201b0b2abbbe61d4838d7ea4c68000524c555344000000000000000000000000000000e5e961c6a025c9404aa7b662dd1df975be75d13e68400000000000000c7321039c77e9329017ced5f8673ebafcd29687a1fff181140c030062fa77865688fc5d744630440220552e90f417c2cabe39368bb45cf7495ba6ebe395f259a6509c9f3a7296e76a0d02201b37dae0c4c77fa70a451cd4a61c10575c8b052c282c082a32c229e7624a05e381140265c09d122fab2a261a80ee59f1f4cd8fba8cf88314ef20a3d93b00cc729eec11a3058d3d1feb4465e0");
}

TEST(TWAnySignerRipple, SignEscrowCreateMain) {
// https://xrpscan.com/tx/3576E5D413CBDC228D13F281BB66304C1EE9DDEAA5563F1783EDB1848266D739
auto key = parse_hex("a3cf20a85b25be4c955f0814718cc7a02eae9195159bd72ede5dd5c4e60d22c4");
Expand Down

0 comments on commit 0e50ff2

Please sign in to comment.