From 92b4cf033b5e569941acee16458696c4fa5c47b7 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Tue, 21 Apr 2020 13:15:52 +0200 Subject: [PATCH 1/7] Update xdr definitions to protocol 13 --- xdr/Stellar-ledger-entries.x | 10 +- xdr/Stellar-ledger.x | 3 +- xdr/Stellar-overlay.x | 12 +- xdr/Stellar-transaction.x | 288 +++++++++++++++++++++++++++-------- xdr/Stellar-types.x | 14 +- 5 files changed, 244 insertions(+), 83 deletions(-) diff --git a/xdr/Stellar-ledger-entries.x b/xdr/Stellar-ledger-entries.x index b511de272..433d4b656 100644 --- a/xdr/Stellar-ledger-entries.x +++ b/xdr/Stellar-ledger-entries.x @@ -160,11 +160,15 @@ struct AccountEntry enum TrustLineFlags { // issuer has authorized account to perform transactions with its credit - AUTHORIZED_FLAG = 1 + AUTHORIZED_FLAG = 1, + // issuer has authorized account to maintain and reduce liabilities for its + // credit + AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG = 2 }; // mask for all trustline flags const MASK_TRUSTLINE_FLAGS = 1; +const MASK_TRUSTLINE_FLAGS_V13 = 3; struct TrustLineEntry { @@ -287,9 +291,11 @@ struct LedgerEntry // the respective envelopes enum EnvelopeType { + ENVELOPE_TYPE_TX_V0 = 0, ENVELOPE_TYPE_SCP = 1, ENVELOPE_TYPE_TX = 2, ENVELOPE_TYPE_AUTH = 3, - ENVELOPE_TYPE_SCPVALUE = 4 + ENVELOPE_TYPE_SCPVALUE = 4, + ENVELOPE_TYPE_TX_FEE_BUMP = 5 }; } diff --git a/xdr/Stellar-ledger.x b/xdr/Stellar-ledger.x index b8eafa2a8..6c2bb88e4 100644 --- a/xdr/Stellar-ledger.x +++ b/xdr/Stellar-ledger.x @@ -366,7 +366,6 @@ struct LedgerCloseMetaV0 union LedgerCloseMeta switch (int v) { case 0: - LedgerCloseMetaV0 v0; + LedgerCloseMetaV0 v0; }; - } diff --git a/xdr/Stellar-overlay.x b/xdr/Stellar-overlay.x index 5e59acd7d..a4ab6b077 100644 --- a/xdr/Stellar-overlay.x +++ b/xdr/Stellar-overlay.x @@ -172,8 +172,8 @@ struct TopologyResponseBody union SurveyResponseBody switch (SurveyMessageCommandType type) { - case SURVEY_TOPOLOGY: - TopologyResponseBody topologyResponseBody; +case SURVEY_TOPOLOGY: + TopologyResponseBody topologyResponseBody; }; union StellarMessage switch (MessageType type) @@ -220,10 +220,10 @@ union AuthenticatedMessage switch (uint32 v) { case 0: struct -{ - uint64 sequence; - StellarMessage message; - HmacSha256Mac mac; + { + uint64 sequence; + StellarMessage message; + HmacSha256Mac mac; } v0; }; } diff --git a/xdr/Stellar-transaction.x b/xdr/Stellar-transaction.x index 74d7a9baf..bee28cbad 100644 --- a/xdr/Stellar-transaction.x +++ b/xdr/Stellar-transaction.x @@ -7,6 +7,19 @@ namespace stellar { +// Source or destination of a payment operation +union MuxedAccount switch (CryptoKeyType type) +{ +case KEY_TYPE_ED25519: + uint256 ed25519; +case KEY_TYPE_MUXED_ED25519: + struct + { + uint64 id; + uint256 ed25519; + } med25519; +}; + struct DecoratedSignature { SignatureHint hint; // last 4 bytes of the public key, used as a hint @@ -55,9 +68,9 @@ struct CreateAccountOp */ struct PaymentOp { - AccountID destination; // recipient of the payment - Asset asset; // what they end up with - int64 amount; // amount they end up with + MuxedAccount destination; // recipient of the payment + Asset asset; // what they end up with + int64 amount; // amount they end up with }; /* PathPaymentStrictReceive @@ -78,9 +91,9 @@ struct PathPaymentStrictReceiveOp // send (excluding fees). // The operation will fail if can't be met - AccountID destination; // recipient of the payment - Asset destAsset; // what they end up with - int64 destAmount; // amount they end up with + MuxedAccount destination; // recipient of the payment + Asset destAsset; // what they end up with + int64 destAmount; // amount they end up with Asset path<5>; // additional hops it must go through to get there }; @@ -101,16 +114,15 @@ struct PathPaymentStrictSendOp Asset sendAsset; // asset we pay with int64 sendAmount; // amount of sendAsset to send (excluding fees) - AccountID destination; // recipient of the payment - Asset destAsset; // what they end up with - int64 destMin; // the minimum amount of dest asset to - // be received - // The operation will fail if it can't be met + MuxedAccount destination; // recipient of the payment + Asset destAsset; // what they end up with + int64 destMin; // the minimum amount of dest asset to + // be received + // The operation will fail if it can't be met Asset path<5>; // additional hops it must go through to get there }; - /* Creates, updates or deletes an offer Threshold: med @@ -232,7 +244,8 @@ struct AllowTrustOp } asset; - bool authorize; + // 0, or any bitwise combination of TrustLineFlags + uint32 authorize; }; /* Inflation @@ -285,7 +298,7 @@ struct Operation // sourceAccount is the account used to run the operation // if not set, the runtime defaults to "sourceAccount" specified at // the transaction level - AccountID* sourceAccount; + MuxedAccount* sourceAccount; union switch (OperationType type) { @@ -306,7 +319,7 @@ struct Operation case ALLOW_TRUST: AllowTrustOp allowTrustOp; case ACCOUNT_MERGE: - AccountID destination; + MuxedAccount destination; case INFLATION: void; case MANAGE_DATA: @@ -353,6 +366,36 @@ struct TimeBounds // maximum number of operations per transaction const MAX_OPS_PER_TX = 100; +// TransactionV0 is a transaction with the AccountID discriminant stripped off, +// leaving a raw ed25519 public key to identify the source account. This is used +// for backwards compatibility starting from the protocol 12/13 boundary. If an +// "old-style" TransactionEnvelope containing a Transaction is parsed with this +// XDR definition, it will be parsed as a "new-style" TransactionEnvelope +// containing a TransactionV0. +struct TransactionV0 +{ + uint256 sourceAccountEd25519; + uint32 fee; + SequenceNumber seqNum; + TimeBounds* timeBounds; + Memo memo; + Operation operations; + union switch (int v) + { + case 0: + void; + } + ext; +}; + +struct TransactionV0Envelope +{ + TransactionV0 tx; + /* Each decorated signature is a signature over the SHA256 hash of + * a TransactionSignaturePayload */ + DecoratedSignature signatures<20>; +}; + /* a transaction is a container for a set of operations - is executed by an account - fees are collected from the account @@ -363,7 +406,7 @@ const MAX_OPS_PER_TX = 100; struct Transaction { // account used to run the transaction - AccountID sourceAccount; + MuxedAccount sourceAccount; // the fee the sourceAccount will pay uint32 fee; @@ -387,27 +430,65 @@ struct Transaction ext; }; -struct TransactionSignaturePayload +struct TransactionV1Envelope { - Hash networkId; + Transaction tx; + /* Each decorated signature is a signature over the SHA256 hash of + * a TransactionSignaturePayload */ + DecoratedSignature signatures<20>; +}; + +struct FeeBumpTransaction +{ + MuxedAccount feeSource; + int64 fee; union switch (EnvelopeType type) { case ENVELOPE_TYPE_TX: - Transaction tx; - /* All other values of type are invalid */ + TransactionV1Envelope v1; } - taggedTransaction; + innerTx; + union switch (int v) + { + case 0: + void; + } + ext; }; -/* A TransactionEnvelope wraps a transaction with signatures. */ -struct TransactionEnvelope +struct FeeBumpTransactionEnvelope { - Transaction tx; + FeeBumpTransaction tx; /* Each decorated signature is a signature over the SHA256 hash of * a TransactionSignaturePayload */ DecoratedSignature signatures<20>; }; +/* A TransactionEnvelope wraps a transaction with signatures. */ +union TransactionEnvelope switch (EnvelopeType type) +{ +case ENVELOPE_TYPE_TX_V0: + TransactionV0Envelope v0; +case ENVELOPE_TYPE_TX: + TransactionV1Envelope v1; +case ENVELOPE_TYPE_TX_FEE_BUMP: + FeeBumpTransactionEnvelope feeBump; +}; + +struct TransactionSignaturePayload +{ + Hash networkId; + union switch (EnvelopeType type) + { + // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 + case ENVELOPE_TYPE_TX: + Transaction tx; + case ENVELOPE_TYPE_TX_FEE_BUMP: + FeeBumpTransaction feeBump; + } + taggedTransaction; +}; + /* Operation Results section */ /* This result is used when offers are taken during an operation */ @@ -484,18 +565,27 @@ enum PathPaymentStrictReceiveResultCode PATH_PAYMENT_STRICT_RECEIVE_SUCCESS = 0, // success // codes considered as "failure" for the operation - PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input - PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = -2, // not enough funds in source account - PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = -3, // no trust line on source account - PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer - PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = -5, // destination account does not exist - PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = -6, // dest missing a trust line for asset - PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = -7, // dest not authorized to hold asset - PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = -8, // dest would go above their limit - PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset - PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = -10, // not enough offers to satisfy path - PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = -11, // would cross one of its own offers - PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax + PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input + PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = + -2, // not enough funds in source account + PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = + -3, // no trust line on source account + PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = + -4, // source not authorized to transfer + PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = + -5, // destination account does not exist + PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = + -6, // dest missing a trust line for asset + PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = + -7, // dest not authorized to hold asset + PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = + -8, // dest would go above their limit + PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset + PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = + -10, // not enough offers to satisfy path + PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = + -11, // would cross one of its own offers + PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax }; struct SimplePaymentResult @@ -527,18 +617,26 @@ enum PathPaymentStrictSendResultCode PATH_PAYMENT_STRICT_SEND_SUCCESS = 0, // success // codes considered as "failure" for the operation - PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input - PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = -2, // not enough funds in source account - PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = -3, // no trust line on source account - PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer - PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = -5, // destination account does not exist - PATH_PAYMENT_STRICT_SEND_NO_TRUST = -6, // dest missing a trust line for asset - PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = -7, // dest not authorized to hold asset - PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit - PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset - PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = -10, // not enough offers to satisfy path - PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = -11, // would cross one of its own offers - PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin + PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input + PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = + -2, // not enough funds in source account + PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = + -3, // no trust line on source account + PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = + -4, // source not authorized to transfer + PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = + -5, // destination account does not exist + PATH_PAYMENT_STRICT_SEND_NO_TRUST = + -6, // dest missing a trust line for asset + PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = + -7, // dest not authorized to hold asset + PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit + PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset + PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = + -10, // not enough offers to satisfy path + PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = + -11, // would cross one of its own offers + PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin }; union PathPaymentStrictSendResult switch (PathPaymentStrictSendResultCode code) @@ -563,21 +661,25 @@ enum ManageSellOfferResultCode MANAGE_SELL_OFFER_SUCCESS = 0, // codes considered as "failure" for the operation - MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid - MANAGE_SELL_OFFER_SELL_NO_TRUST = -2, // no trust line for what we're selling - MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying + MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid + MANAGE_SELL_OFFER_SELL_NO_TRUST = + -2, // no trust line for what we're selling + MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy - MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying - MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell - MANAGE_SELL_OFFER_CROSS_SELF = -8, // would cross an offer from the same user + MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying + MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell + MANAGE_SELL_OFFER_CROSS_SELF = + -8, // would cross an offer from the same user MANAGE_SELL_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling MANAGE_SELL_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying // update errors - MANAGE_SELL_OFFER_NOT_FOUND = -11, // offerID does not match an existing offer + MANAGE_SELL_OFFER_NOT_FOUND = + -11, // offerID does not match an existing offer - MANAGE_SELL_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer + MANAGE_SELL_OFFER_LOW_RESERVE = + -12 // not enough funds to create a new Offer }; enum ManageOfferEffect @@ -624,14 +726,15 @@ enum ManageBuyOfferResultCode MANAGE_BUY_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy - MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying - MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell - MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user + MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying + MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell + MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user MANAGE_BUY_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling MANAGE_BUY_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying // update errors - MANAGE_BUY_OFFER_NOT_FOUND = -11, // offerID does not match an existing offer + MANAGE_BUY_OFFER_NOT_FOUND = + -11, // offerID does not match an existing offer MANAGE_BUY_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer }; @@ -683,7 +786,7 @@ enum ChangeTrustResultCode // cannot create with a limit of 0 CHANGE_TRUST_LOW_RESERVE = -4, // not enough funds to create a new trust line, - CHANGE_TRUST_SELF_NOT_ALLOWED = -5 // trusting self is not allowed + CHANGE_TRUST_SELF_NOT_ALLOWED = -5 // trusting self is not allowed }; union ChangeTrustResult switch (ChangeTrustResultCode code) @@ -811,9 +914,9 @@ enum OperationResultCode { opINNER = 0, // inner object result is valid - opBAD_AUTH = -1, // too few valid signatures / wrong network - opNO_ACCOUNT = -2, // source account was not found - opNOT_SUPPORTED = -3, // operation not supported at this time + opBAD_AUTH = -1, // too few valid signatures / wrong network + opNO_ACCOUNT = -2, // source account was not found + opNOT_SUPPORTED = -3, // operation not supported at this time opTOO_MANY_SUBENTRIES = -4, // max number of subentries already reached opEXCEEDED_WORK_LIMIT = -5 // operation did too much work }; @@ -848,7 +951,7 @@ case opINNER: case BUMP_SEQUENCE: BumpSequenceResult bumpSeqResult; case MANAGE_BUY_OFFER: - ManageBuyOfferResult manageBuyOfferResult; + ManageBuyOfferResult manageBuyOfferResult; case PATH_PAYMENT_STRICT_SEND: PathPaymentStrictSendResult pathPaymentStrictSendResult; } @@ -859,7 +962,8 @@ default: enum TransactionResultCode { - txSUCCESS = 0, // all operations succeeded + txFEE_BUMP_INNER_SUCCESS = 1, // fee bump inner transaction succeeded + txSUCCESS = 0, // all operations succeeded txFAILED = -1, // one of the operations failed (none were applied) @@ -873,7 +977,54 @@ enum TransactionResultCode txNO_ACCOUNT = -8, // source account not found txINSUFFICIENT_FEE = -9, // fee is too small txBAD_AUTH_EXTRA = -10, // unused signatures attached to transaction - txINTERNAL_ERROR = -11 // an unknown error occured + txINTERNAL_ERROR = -11, // an unknown error occured + + txNOT_SUPPORTED = -12, // transaction type not supported + txFEE_BUMP_INNER_FAILED = -13 // fee bump inner transaction failed +}; + +// InnerTransactionResult must be binary compatible with TransactionResult +// because it is be used to represent the result of a Transaction. +struct InnerTransactionResult +{ + // Always 0. Here for binary compatibility. + int64 feeCharged; + + union switch (TransactionResultCode code) + { + // txFEE_BUMP_INNER_SUCCESS is not included + case txSUCCESS: + case txFAILED: + OperationResult results<>; + case txTOO_EARLY: + case txTOO_LATE: + case txMISSING_OPERATION: + case txBAD_SEQ: + case txBAD_AUTH: + case txINSUFFICIENT_BALANCE: + case txNO_ACCOUNT: + case txINSUFFICIENT_FEE: + case txBAD_AUTH_EXTRA: + case txINTERNAL_ERROR: + case txNOT_SUPPORTED: + // txFEE_BUMP_INNER_FAILED is not included + void; + } + result; + + // reserved for future use + union switch (int v) + { + case 0: + void; + } + ext; +}; + +struct InnerTransactionResultPair +{ + Hash transactionHash; // hash of the inner transaction + InnerTransactionResult result; // result for the inner transaction }; struct TransactionResult @@ -882,6 +1033,9 @@ struct TransactionResult union switch (TransactionResultCode code) { + case txFEE_BUMP_INNER_SUCCESS: + case txFEE_BUMP_INNER_FAILED: + InnerTransactionResultPair innerResultPair; case txSUCCESS: case txFAILED: OperationResult results<>; diff --git a/xdr/Stellar-types.x b/xdr/Stellar-types.x index b7a616aef..8f7d5c206 100644 --- a/xdr/Stellar-types.x +++ b/xdr/Stellar-types.x @@ -18,7 +18,10 @@ enum CryptoKeyType { KEY_TYPE_ED25519 = 0, KEY_TYPE_PRE_AUTH_TX = 1, - KEY_TYPE_HASH_X = 2 + KEY_TYPE_HASH_X = 2, + // MUXED enum values for supported type are derived from the enum values + // above by ORing them with 0x100 + KEY_TYPE_MUXED_ED25519 = 0x100 }; enum PublicKeyType @@ -60,22 +63,21 @@ typedef PublicKey NodeID; struct Curve25519Secret { - opaque key[32]; + opaque key[32]; }; struct Curve25519Public { - opaque key[32]; + opaque key[32]; }; struct HmacSha256Key { - opaque key[32]; + opaque key[32]; }; struct HmacSha256Mac { - opaque mac[32]; + opaque mac[32]; }; - } From 126465b83329ff96f45f4f5bceeb6743d0882dc5 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Tue, 21 Apr 2020 13:17:12 +0200 Subject: [PATCH 2/7] Run xdrgen on protocol 13 xdr definitions --- .../org/stellar/sdk/xdr/AllowTrustOp.java | 13 +- .../stellar/sdk/xdr/AuthenticatedMessage.java | 8 +- .../sdk/xdr/ChangeTrustResultCode.java | 2 +- .../org/stellar/sdk/xdr/CryptoKeyType.java | 7 +- .../org/stellar/sdk/xdr/Curve25519Public.java | 2 +- .../org/stellar/sdk/xdr/Curve25519Secret.java | 2 +- .../org/stellar/sdk/xdr/EnvelopeType.java | 8 +- .../stellar/sdk/xdr/FeeBumpTransaction.java | 194 ++++++++++++++ .../sdk/xdr/FeeBumpTransactionEnvelope.java | 73 ++++++ .../org/stellar/sdk/xdr/HmacSha256Key.java | 2 +- .../org/stellar/sdk/xdr/HmacSha256Mac.java | 2 +- .../sdk/xdr/InnerTransactionResult.java | 238 ++++++++++++++++++ .../sdk/xdr/InnerTransactionResultPair.java | 62 +++++ .../org/stellar/sdk/xdr/LedgerCloseMeta.java | 2 +- .../sdk/xdr/ManageBuyOfferResultCode.java | 9 +- .../sdk/xdr/ManageSellOfferResultCode.java | 20 +- .../org/stellar/sdk/xdr/MuxedAccount.java | 137 ++++++++++ .../java/org/stellar/sdk/xdr/Operation.java | 24 +- .../org/stellar/sdk/xdr/OperationResult.java | 2 +- .../stellar/sdk/xdr/OperationResultCode.java | 6 +- .../sdk/xdr/PathPaymentStrictReceiveOp.java | 16 +- .../PathPaymentStrictReceiveResultCode.java | 33 ++- .../sdk/xdr/PathPaymentStrictSendOp.java | 20 +- .../xdr/PathPaymentStrictSendResultCode.java | 32 ++- .../java/org/stellar/sdk/xdr/PaymentOp.java | 16 +- .../stellar/sdk/xdr/SurveyResponseBody.java | 4 +- .../java/org/stellar/sdk/xdr/Transaction.java | 12 +- .../stellar/sdk/xdr/TransactionEnvelope.java | 94 ++++--- .../stellar/sdk/xdr/TransactionResult.java | 22 +- .../sdk/xdr/TransactionResultCode.java | 14 +- .../sdk/xdr/TransactionSignaturePayload.java | 21 +- .../org/stellar/sdk/xdr/TransactionV0.java | 181 +++++++++++++ .../sdk/xdr/TransactionV0Envelope.java | 73 ++++++ .../sdk/xdr/TransactionV1Envelope.java | 73 ++++++ .../org/stellar/sdk/xdr/TrustLineFlags.java | 7 +- 35 files changed, 1287 insertions(+), 144 deletions(-) create mode 100644 src/main/java/org/stellar/sdk/xdr/FeeBumpTransaction.java create mode 100644 src/main/java/org/stellar/sdk/xdr/FeeBumpTransactionEnvelope.java create mode 100644 src/main/java/org/stellar/sdk/xdr/InnerTransactionResult.java create mode 100644 src/main/java/org/stellar/sdk/xdr/InnerTransactionResultPair.java create mode 100644 src/main/java/org/stellar/sdk/xdr/MuxedAccount.java create mode 100644 src/main/java/org/stellar/sdk/xdr/TransactionV0.java create mode 100644 src/main/java/org/stellar/sdk/xdr/TransactionV0Envelope.java create mode 100644 src/main/java/org/stellar/sdk/xdr/TransactionV1Envelope.java diff --git a/src/main/java/org/stellar/sdk/xdr/AllowTrustOp.java b/src/main/java/org/stellar/sdk/xdr/AllowTrustOp.java index 6cd680e19..e836b2fae 100644 --- a/src/main/java/org/stellar/sdk/xdr/AllowTrustOp.java +++ b/src/main/java/org/stellar/sdk/xdr/AllowTrustOp.java @@ -26,7 +26,8 @@ // } // asset; // -// bool authorize; +// // 0, or any bitwise combination of TrustLineFlags +// uint32 authorize; // }; // =========================================================================== @@ -46,17 +47,17 @@ public AllowTrustOpAsset getAsset() { public void setAsset(AllowTrustOpAsset value) { this.asset = value; } - private Boolean authorize; - public Boolean getAuthorize() { + private Uint32 authorize; + public Uint32 getAuthorize() { return this.authorize; } - public void setAuthorize(Boolean value) { + public void setAuthorize(Uint32 value) { this.authorize = value; } public static void encode(XdrDataOutputStream stream, AllowTrustOp encodedAllowTrustOp) throws IOException{ AccountID.encode(stream, encodedAllowTrustOp.trustor); AllowTrustOpAsset.encode(stream, encodedAllowTrustOp.asset); - stream.writeInt(encodedAllowTrustOp.authorize ? 1 : 0); + Uint32.encode(stream, encodedAllowTrustOp.authorize); } public void encode(XdrDataOutputStream stream) throws IOException { encode(stream, this); @@ -65,7 +66,7 @@ public static AllowTrustOp decode(XdrDataInputStream stream) throws IOException AllowTrustOp decodedAllowTrustOp = new AllowTrustOp(); decodedAllowTrustOp.trustor = AccountID.decode(stream); decodedAllowTrustOp.asset = AllowTrustOpAsset.decode(stream); - decodedAllowTrustOp.authorize = stream.readInt() == 1 ? true : false; + decodedAllowTrustOp.authorize = Uint32.decode(stream); return decodedAllowTrustOp; } @Override diff --git a/src/main/java/org/stellar/sdk/xdr/AuthenticatedMessage.java b/src/main/java/org/stellar/sdk/xdr/AuthenticatedMessage.java index 73d1c7855..559567c30 100644 --- a/src/main/java/org/stellar/sdk/xdr/AuthenticatedMessage.java +++ b/src/main/java/org/stellar/sdk/xdr/AuthenticatedMessage.java @@ -14,10 +14,10 @@ // { // case 0: // struct -// { -// uint64 sequence; -// StellarMessage message; -// HmacSha256Mac mac; +// { +// uint64 sequence; +// StellarMessage message; +// HmacSha256Mac mac; // } v0; // }; diff --git a/src/main/java/org/stellar/sdk/xdr/ChangeTrustResultCode.java b/src/main/java/org/stellar/sdk/xdr/ChangeTrustResultCode.java index 52f3523ab..e351dae2e 100644 --- a/src/main/java/org/stellar/sdk/xdr/ChangeTrustResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/ChangeTrustResultCode.java @@ -20,7 +20,7 @@ // // cannot create with a limit of 0 // CHANGE_TRUST_LOW_RESERVE = // -4, // not enough funds to create a new trust line, -// CHANGE_TRUST_SELF_NOT_ALLOWED = -5 // trusting self is not allowed +// CHANGE_TRUST_SELF_NOT_ALLOWED = -5 // trusting self is not allowed // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/CryptoKeyType.java b/src/main/java/org/stellar/sdk/xdr/CryptoKeyType.java index bdbfab00d..bfaf14e5c 100644 --- a/src/main/java/org/stellar/sdk/xdr/CryptoKeyType.java +++ b/src/main/java/org/stellar/sdk/xdr/CryptoKeyType.java @@ -13,7 +13,10 @@ // { // KEY_TYPE_ED25519 = 0, // KEY_TYPE_PRE_AUTH_TX = 1, -// KEY_TYPE_HASH_X = 2 +// KEY_TYPE_HASH_X = 2, +// // MUXED enum values for supported type are derived from the enum values +// // above by ORing them with 0x100 +// KEY_TYPE_MUXED_ED25519 = 0x100 // }; // =========================================================================== @@ -21,6 +24,7 @@ public enum CryptoKeyType implements XdrElement { KEY_TYPE_ED25519(0), KEY_TYPE_PRE_AUTH_TX(1), KEY_TYPE_HASH_X(2), + KEY_TYPE_MUXED_ED25519(256), ; private int mValue; @@ -38,6 +42,7 @@ public static CryptoKeyType decode(XdrDataInputStream stream) throws IOException case 0: return KEY_TYPE_ED25519; case 1: return KEY_TYPE_PRE_AUTH_TX; case 2: return KEY_TYPE_HASH_X; + case 256: return KEY_TYPE_MUXED_ED25519; default: throw new RuntimeException("Unknown enum value: " + value); } diff --git a/src/main/java/org/stellar/sdk/xdr/Curve25519Public.java b/src/main/java/org/stellar/sdk/xdr/Curve25519Public.java index e3c00fccd..5d70e454d 100644 --- a/src/main/java/org/stellar/sdk/xdr/Curve25519Public.java +++ b/src/main/java/org/stellar/sdk/xdr/Curve25519Public.java @@ -12,7 +12,7 @@ // struct Curve25519Public // { -// opaque key[32]; +// opaque key[32]; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/Curve25519Secret.java b/src/main/java/org/stellar/sdk/xdr/Curve25519Secret.java index 68677bc24..491c1b404 100644 --- a/src/main/java/org/stellar/sdk/xdr/Curve25519Secret.java +++ b/src/main/java/org/stellar/sdk/xdr/Curve25519Secret.java @@ -12,7 +12,7 @@ // struct Curve25519Secret // { -// opaque key[32]; +// opaque key[32]; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/EnvelopeType.java b/src/main/java/org/stellar/sdk/xdr/EnvelopeType.java index 3ff079281..90bfba5e6 100644 --- a/src/main/java/org/stellar/sdk/xdr/EnvelopeType.java +++ b/src/main/java/org/stellar/sdk/xdr/EnvelopeType.java @@ -11,18 +11,22 @@ // enum EnvelopeType // { +// ENVELOPE_TYPE_TX_V0 = 0, // ENVELOPE_TYPE_SCP = 1, // ENVELOPE_TYPE_TX = 2, // ENVELOPE_TYPE_AUTH = 3, -// ENVELOPE_TYPE_SCPVALUE = 4 +// ENVELOPE_TYPE_SCPVALUE = 4, +// ENVELOPE_TYPE_TX_FEE_BUMP = 5 // }; // =========================================================================== public enum EnvelopeType implements XdrElement { + ENVELOPE_TYPE_TX_V0(0), ENVELOPE_TYPE_SCP(1), ENVELOPE_TYPE_TX(2), ENVELOPE_TYPE_AUTH(3), ENVELOPE_TYPE_SCPVALUE(4), + ENVELOPE_TYPE_TX_FEE_BUMP(5), ; private int mValue; @@ -37,10 +41,12 @@ public int getValue() { public static EnvelopeType decode(XdrDataInputStream stream) throws IOException { int value = stream.readInt(); switch (value) { + case 0: return ENVELOPE_TYPE_TX_V0; case 1: return ENVELOPE_TYPE_SCP; case 2: return ENVELOPE_TYPE_TX; case 3: return ENVELOPE_TYPE_AUTH; case 4: return ENVELOPE_TYPE_SCPVALUE; + case 5: return ENVELOPE_TYPE_TX_FEE_BUMP; default: throw new RuntimeException("Unknown enum value: " + value); } diff --git a/src/main/java/org/stellar/sdk/xdr/FeeBumpTransaction.java b/src/main/java/org/stellar/sdk/xdr/FeeBumpTransaction.java new file mode 100644 index 000000000..69c65bd4a --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/FeeBumpTransaction.java @@ -0,0 +1,194 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; + +// === xdr source ============================================================ + +// struct FeeBumpTransaction +// { +// MuxedAccount feeSource; +// int64 fee; +// union switch (EnvelopeType type) +// { +// case ENVELOPE_TYPE_TX: +// TransactionV1Envelope v1; +// } +// innerTx; +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; + +// =========================================================================== +public class FeeBumpTransaction implements XdrElement { + public FeeBumpTransaction () {} + private MuxedAccount feeSource; + public MuxedAccount getFeeSource() { + return this.feeSource; + } + public void setFeeSource(MuxedAccount value) { + this.feeSource = value; + } + private Int64 fee; + public Int64 getFee() { + return this.fee; + } + public void setFee(Int64 value) { + this.fee = value; + } + private FeeBumpTransactionInnerTx innerTx; + public FeeBumpTransactionInnerTx getInnerTx() { + return this.innerTx; + } + public void setInnerTx(FeeBumpTransactionInnerTx value) { + this.innerTx = value; + } + private FeeBumpTransactionExt ext; + public FeeBumpTransactionExt getExt() { + return this.ext; + } + public void setExt(FeeBumpTransactionExt value) { + this.ext = value; + } + public static void encode(XdrDataOutputStream stream, FeeBumpTransaction encodedFeeBumpTransaction) throws IOException{ + MuxedAccount.encode(stream, encodedFeeBumpTransaction.feeSource); + Int64.encode(stream, encodedFeeBumpTransaction.fee); + FeeBumpTransactionInnerTx.encode(stream, encodedFeeBumpTransaction.innerTx); + FeeBumpTransactionExt.encode(stream, encodedFeeBumpTransaction.ext); + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static FeeBumpTransaction decode(XdrDataInputStream stream) throws IOException { + FeeBumpTransaction decodedFeeBumpTransaction = new FeeBumpTransaction(); + decodedFeeBumpTransaction.feeSource = MuxedAccount.decode(stream); + decodedFeeBumpTransaction.fee = Int64.decode(stream); + decodedFeeBumpTransaction.innerTx = FeeBumpTransactionInnerTx.decode(stream); + decodedFeeBumpTransaction.ext = FeeBumpTransactionExt.decode(stream); + return decodedFeeBumpTransaction; + } + @Override + public int hashCode() { + return Objects.hashCode(this.feeSource, this.fee, this.innerTx, this.ext); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof FeeBumpTransaction)) { + return false; + } + + FeeBumpTransaction other = (FeeBumpTransaction) object; + return Objects.equal(this.feeSource, other.feeSource) && Objects.equal(this.fee, other.fee) && Objects.equal(this.innerTx, other.innerTx) && Objects.equal(this.ext, other.ext); + } + + public static class FeeBumpTransactionInnerTx { + public FeeBumpTransactionInnerTx () {} + EnvelopeType type; + public EnvelopeType getDiscriminant() { + return this.type; + } + public void setDiscriminant(EnvelopeType value) { + this.type = value; + } + private TransactionV1Envelope v1; + public TransactionV1Envelope getV1() { + return this.v1; + } + public void setV1(TransactionV1Envelope value) { + this.v1 = value; + } + public static void encode(XdrDataOutputStream stream, FeeBumpTransactionInnerTx encodedFeeBumpTransactionInnerTx) throws IOException { + //Xdrgen::AST::Identifier + //EnvelopeType + stream.writeInt(encodedFeeBumpTransactionInnerTx.getDiscriminant().getValue()); + switch (encodedFeeBumpTransactionInnerTx.getDiscriminant()) { + case ENVELOPE_TYPE_TX: + TransactionV1Envelope.encode(stream, encodedFeeBumpTransactionInnerTx.v1); + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static FeeBumpTransactionInnerTx decode(XdrDataInputStream stream) throws IOException { + FeeBumpTransactionInnerTx decodedFeeBumpTransactionInnerTx = new FeeBumpTransactionInnerTx(); + EnvelopeType discriminant = EnvelopeType.decode(stream); + decodedFeeBumpTransactionInnerTx.setDiscriminant(discriminant); + switch (decodedFeeBumpTransactionInnerTx.getDiscriminant()) { + case ENVELOPE_TYPE_TX: + decodedFeeBumpTransactionInnerTx.v1 = TransactionV1Envelope.decode(stream); + break; + } + return decodedFeeBumpTransactionInnerTx; + } + @Override + public int hashCode() { + return Objects.hashCode(this.v1, this.type); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof FeeBumpTransactionInnerTx)) { + return false; + } + + FeeBumpTransactionInnerTx other = (FeeBumpTransactionInnerTx) object; + return Objects.equal(this.v1, other.v1) && Objects.equal(this.type, other.type); + } + + } + public static class FeeBumpTransactionExt { + public FeeBumpTransactionExt () {} + Integer v; + public Integer getDiscriminant() { + return this.v; + } + public void setDiscriminant(Integer value) { + this.v = value; + } + public static void encode(XdrDataOutputStream stream, FeeBumpTransactionExt encodedFeeBumpTransactionExt) throws IOException { + //Xdrgen::AST::Typespecs::Int + //Integer + stream.writeInt(encodedFeeBumpTransactionExt.getDiscriminant().intValue()); + switch (encodedFeeBumpTransactionExt.getDiscriminant()) { + case 0: + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static FeeBumpTransactionExt decode(XdrDataInputStream stream) throws IOException { + FeeBumpTransactionExt decodedFeeBumpTransactionExt = new FeeBumpTransactionExt(); + Integer discriminant = stream.readInt(); + decodedFeeBumpTransactionExt.setDiscriminant(discriminant); + switch (decodedFeeBumpTransactionExt.getDiscriminant()) { + case 0: + break; + } + return decodedFeeBumpTransactionExt; + } + @Override + public int hashCode() { + return Objects.hashCode(this.v); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof FeeBumpTransactionExt)) { + return false; + } + + FeeBumpTransactionExt other = (FeeBumpTransactionExt) object; + return Objects.equal(this.v, other.v); + } + + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/FeeBumpTransactionEnvelope.java b/src/main/java/org/stellar/sdk/xdr/FeeBumpTransactionEnvelope.java new file mode 100644 index 000000000..d19e67cc6 --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/FeeBumpTransactionEnvelope.java @@ -0,0 +1,73 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; +import java.util.Arrays; + +// === xdr source ============================================================ + +// struct FeeBumpTransactionEnvelope +// { +// FeeBumpTransaction tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; + +// =========================================================================== +public class FeeBumpTransactionEnvelope implements XdrElement { + public FeeBumpTransactionEnvelope () {} + private FeeBumpTransaction tx; + public FeeBumpTransaction getTx() { + return this.tx; + } + public void setTx(FeeBumpTransaction value) { + this.tx = value; + } + private DecoratedSignature[] signatures; + public DecoratedSignature[] getSignatures() { + return this.signatures; + } + public void setSignatures(DecoratedSignature[] value) { + this.signatures = value; + } + public static void encode(XdrDataOutputStream stream, FeeBumpTransactionEnvelope encodedFeeBumpTransactionEnvelope) throws IOException{ + FeeBumpTransaction.encode(stream, encodedFeeBumpTransactionEnvelope.tx); + int signaturessize = encodedFeeBumpTransactionEnvelope.getSignatures().length; + stream.writeInt(signaturessize); + for (int i = 0; i < signaturessize; i++) { + DecoratedSignature.encode(stream, encodedFeeBumpTransactionEnvelope.signatures[i]); + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static FeeBumpTransactionEnvelope decode(XdrDataInputStream stream) throws IOException { + FeeBumpTransactionEnvelope decodedFeeBumpTransactionEnvelope = new FeeBumpTransactionEnvelope(); + decodedFeeBumpTransactionEnvelope.tx = FeeBumpTransaction.decode(stream); + int signaturessize = stream.readInt(); + decodedFeeBumpTransactionEnvelope.signatures = new DecoratedSignature[signaturessize]; + for (int i = 0; i < signaturessize; i++) { + decodedFeeBumpTransactionEnvelope.signatures[i] = DecoratedSignature.decode(stream); + } + return decodedFeeBumpTransactionEnvelope; + } + @Override + public int hashCode() { + return Objects.hashCode(this.tx, Arrays.hashCode(this.signatures)); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof FeeBumpTransactionEnvelope)) { + return false; + } + + FeeBumpTransactionEnvelope other = (FeeBumpTransactionEnvelope) object; + return Objects.equal(this.tx, other.tx) && Arrays.equals(this.signatures, other.signatures); + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/HmacSha256Key.java b/src/main/java/org/stellar/sdk/xdr/HmacSha256Key.java index fc2b0e716..248437704 100644 --- a/src/main/java/org/stellar/sdk/xdr/HmacSha256Key.java +++ b/src/main/java/org/stellar/sdk/xdr/HmacSha256Key.java @@ -12,7 +12,7 @@ // struct HmacSha256Key // { -// opaque key[32]; +// opaque key[32]; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/HmacSha256Mac.java b/src/main/java/org/stellar/sdk/xdr/HmacSha256Mac.java index 1bfbcfd8f..f20647c21 100644 --- a/src/main/java/org/stellar/sdk/xdr/HmacSha256Mac.java +++ b/src/main/java/org/stellar/sdk/xdr/HmacSha256Mac.java @@ -12,7 +12,7 @@ // struct HmacSha256Mac // { -// opaque mac[32]; +// opaque mac[32]; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/InnerTransactionResult.java b/src/main/java/org/stellar/sdk/xdr/InnerTransactionResult.java new file mode 100644 index 000000000..6da5783c3 --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/InnerTransactionResult.java @@ -0,0 +1,238 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; +import java.util.Arrays; + +// === xdr source ============================================================ + +// struct InnerTransactionResult +// { +// // Always 0. Here for binary compatibility. +// int64 feeCharged; +// +// union switch (TransactionResultCode code) +// { +// // txFEE_BUMP_INNER_SUCCESS is not included +// case txSUCCESS: +// case txFAILED: +// OperationResult results<>; +// case txTOO_EARLY: +// case txTOO_LATE: +// case txMISSING_OPERATION: +// case txBAD_SEQ: +// case txBAD_AUTH: +// case txINSUFFICIENT_BALANCE: +// case txNO_ACCOUNT: +// case txINSUFFICIENT_FEE: +// case txBAD_AUTH_EXTRA: +// case txINTERNAL_ERROR: +// case txNOT_SUPPORTED: +// // txFEE_BUMP_INNER_FAILED is not included +// void; +// } +// result; +// +// // reserved for future use +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; + +// =========================================================================== +public class InnerTransactionResult implements XdrElement { + public InnerTransactionResult () {} + private Int64 feeCharged; + public Int64 getFeeCharged() { + return this.feeCharged; + } + public void setFeeCharged(Int64 value) { + this.feeCharged = value; + } + private InnerTransactionResultResult result; + public InnerTransactionResultResult getResult() { + return this.result; + } + public void setResult(InnerTransactionResultResult value) { + this.result = value; + } + private InnerTransactionResultExt ext; + public InnerTransactionResultExt getExt() { + return this.ext; + } + public void setExt(InnerTransactionResultExt value) { + this.ext = value; + } + public static void encode(XdrDataOutputStream stream, InnerTransactionResult encodedInnerTransactionResult) throws IOException{ + Int64.encode(stream, encodedInnerTransactionResult.feeCharged); + InnerTransactionResultResult.encode(stream, encodedInnerTransactionResult.result); + InnerTransactionResultExt.encode(stream, encodedInnerTransactionResult.ext); + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static InnerTransactionResult decode(XdrDataInputStream stream) throws IOException { + InnerTransactionResult decodedInnerTransactionResult = new InnerTransactionResult(); + decodedInnerTransactionResult.feeCharged = Int64.decode(stream); + decodedInnerTransactionResult.result = InnerTransactionResultResult.decode(stream); + decodedInnerTransactionResult.ext = InnerTransactionResultExt.decode(stream); + return decodedInnerTransactionResult; + } + @Override + public int hashCode() { + return Objects.hashCode(this.feeCharged, this.result, this.ext); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof InnerTransactionResult)) { + return false; + } + + InnerTransactionResult other = (InnerTransactionResult) object; + return Objects.equal(this.feeCharged, other.feeCharged) && Objects.equal(this.result, other.result) && Objects.equal(this.ext, other.ext); + } + + public static class InnerTransactionResultResult { + public InnerTransactionResultResult () {} + TransactionResultCode code; + public TransactionResultCode getDiscriminant() { + return this.code; + } + public void setDiscriminant(TransactionResultCode value) { + this.code = value; + } + private OperationResult[] results; + public OperationResult[] getResults() { + return this.results; + } + public void setResults(OperationResult[] value) { + this.results = value; + } + public static void encode(XdrDataOutputStream stream, InnerTransactionResultResult encodedInnerTransactionResultResult) throws IOException { + //Xdrgen::AST::Identifier + //TransactionResultCode + stream.writeInt(encodedInnerTransactionResultResult.getDiscriminant().getValue()); + switch (encodedInnerTransactionResultResult.getDiscriminant()) { + case txSUCCESS: + case txFAILED: + int resultssize = encodedInnerTransactionResultResult.getResults().length; + stream.writeInt(resultssize); + for (int i = 0; i < resultssize; i++) { + OperationResult.encode(stream, encodedInnerTransactionResultResult.results[i]); + } + break; + case txTOO_EARLY: + case txTOO_LATE: + case txMISSING_OPERATION: + case txBAD_SEQ: + case txBAD_AUTH: + case txINSUFFICIENT_BALANCE: + case txNO_ACCOUNT: + case txINSUFFICIENT_FEE: + case txBAD_AUTH_EXTRA: + case txINTERNAL_ERROR: + case txNOT_SUPPORTED: + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static InnerTransactionResultResult decode(XdrDataInputStream stream) throws IOException { + InnerTransactionResultResult decodedInnerTransactionResultResult = new InnerTransactionResultResult(); + TransactionResultCode discriminant = TransactionResultCode.decode(stream); + decodedInnerTransactionResultResult.setDiscriminant(discriminant); + switch (decodedInnerTransactionResultResult.getDiscriminant()) { + case txSUCCESS: + case txFAILED: + int resultssize = stream.readInt(); + decodedInnerTransactionResultResult.results = new OperationResult[resultssize]; + for (int i = 0; i < resultssize; i++) { + decodedInnerTransactionResultResult.results[i] = OperationResult.decode(stream); + } + break; + case txTOO_EARLY: + case txTOO_LATE: + case txMISSING_OPERATION: + case txBAD_SEQ: + case txBAD_AUTH: + case txINSUFFICIENT_BALANCE: + case txNO_ACCOUNT: + case txINSUFFICIENT_FEE: + case txBAD_AUTH_EXTRA: + case txINTERNAL_ERROR: + case txNOT_SUPPORTED: + break; + } + return decodedInnerTransactionResultResult; + } + @Override + public int hashCode() { + return Objects.hashCode(Arrays.hashCode(this.results), this.code); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof InnerTransactionResultResult)) { + return false; + } + + InnerTransactionResultResult other = (InnerTransactionResultResult) object; + return Arrays.equals(this.results, other.results) && Objects.equal(this.code, other.code); + } + + } + public static class InnerTransactionResultExt { + public InnerTransactionResultExt () {} + Integer v; + public Integer getDiscriminant() { + return this.v; + } + public void setDiscriminant(Integer value) { + this.v = value; + } + public static void encode(XdrDataOutputStream stream, InnerTransactionResultExt encodedInnerTransactionResultExt) throws IOException { + //Xdrgen::AST::Typespecs::Int + //Integer + stream.writeInt(encodedInnerTransactionResultExt.getDiscriminant().intValue()); + switch (encodedInnerTransactionResultExt.getDiscriminant()) { + case 0: + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static InnerTransactionResultExt decode(XdrDataInputStream stream) throws IOException { + InnerTransactionResultExt decodedInnerTransactionResultExt = new InnerTransactionResultExt(); + Integer discriminant = stream.readInt(); + decodedInnerTransactionResultExt.setDiscriminant(discriminant); + switch (decodedInnerTransactionResultExt.getDiscriminant()) { + case 0: + break; + } + return decodedInnerTransactionResultExt; + } + @Override + public int hashCode() { + return Objects.hashCode(this.v); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof InnerTransactionResultExt)) { + return false; + } + + InnerTransactionResultExt other = (InnerTransactionResultExt) object; + return Objects.equal(this.v, other.v); + } + + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/InnerTransactionResultPair.java b/src/main/java/org/stellar/sdk/xdr/InnerTransactionResultPair.java new file mode 100644 index 000000000..d8edc64ef --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/InnerTransactionResultPair.java @@ -0,0 +1,62 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; + +// === xdr source ============================================================ + +// struct InnerTransactionResultPair +// { +// Hash transactionHash; // hash of the inner transaction +// InnerTransactionResult result; // result for the inner transaction +// }; + +// =========================================================================== +public class InnerTransactionResultPair implements XdrElement { + public InnerTransactionResultPair () {} + private Hash transactionHash; + public Hash getTransactionHash() { + return this.transactionHash; + } + public void setTransactionHash(Hash value) { + this.transactionHash = value; + } + private InnerTransactionResult result; + public InnerTransactionResult getResult() { + return this.result; + } + public void setResult(InnerTransactionResult value) { + this.result = value; + } + public static void encode(XdrDataOutputStream stream, InnerTransactionResultPair encodedInnerTransactionResultPair) throws IOException{ + Hash.encode(stream, encodedInnerTransactionResultPair.transactionHash); + InnerTransactionResult.encode(stream, encodedInnerTransactionResultPair.result); + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static InnerTransactionResultPair decode(XdrDataInputStream stream) throws IOException { + InnerTransactionResultPair decodedInnerTransactionResultPair = new InnerTransactionResultPair(); + decodedInnerTransactionResultPair.transactionHash = Hash.decode(stream); + decodedInnerTransactionResultPair.result = InnerTransactionResult.decode(stream); + return decodedInnerTransactionResultPair; + } + @Override + public int hashCode() { + return Objects.hashCode(this.transactionHash, this.result); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof InnerTransactionResultPair)) { + return false; + } + + InnerTransactionResultPair other = (InnerTransactionResultPair) object; + return Objects.equal(this.transactionHash, other.transactionHash) && Objects.equal(this.result, other.result); + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/LedgerCloseMeta.java b/src/main/java/org/stellar/sdk/xdr/LedgerCloseMeta.java index 9aac2d562..991db5d71 100644 --- a/src/main/java/org/stellar/sdk/xdr/LedgerCloseMeta.java +++ b/src/main/java/org/stellar/sdk/xdr/LedgerCloseMeta.java @@ -13,7 +13,7 @@ // union LedgerCloseMeta switch (int v) // { // case 0: -// LedgerCloseMetaV0 v0; +// LedgerCloseMetaV0 v0; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/ManageBuyOfferResultCode.java b/src/main/java/org/stellar/sdk/xdr/ManageBuyOfferResultCode.java index 1e8c7a882..d96b0a4ee 100644 --- a/src/main/java/org/stellar/sdk/xdr/ManageBuyOfferResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/ManageBuyOfferResultCode.java @@ -20,14 +20,15 @@ // MANAGE_BUY_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying // MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell // MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy -// MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying -// MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell -// MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user +// MANAGE_BUY_OFFER_LINE_FULL = -6, // can't receive more of what it's buying +// MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell +// MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user // MANAGE_BUY_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling // MANAGE_BUY_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying // // // update errors -// MANAGE_BUY_OFFER_NOT_FOUND = -11, // offerID does not match an existing offer +// MANAGE_BUY_OFFER_NOT_FOUND = +// -11, // offerID does not match an existing offer // // MANAGE_BUY_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer // }; diff --git a/src/main/java/org/stellar/sdk/xdr/ManageSellOfferResultCode.java b/src/main/java/org/stellar/sdk/xdr/ManageSellOfferResultCode.java index c5d501b53..c7e990600 100644 --- a/src/main/java/org/stellar/sdk/xdr/ManageSellOfferResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/ManageSellOfferResultCode.java @@ -15,21 +15,25 @@ // MANAGE_SELL_OFFER_SUCCESS = 0, // // // codes considered as "failure" for the operation -// MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid -// MANAGE_SELL_OFFER_SELL_NO_TRUST = -2, // no trust line for what we're selling -// MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying +// MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid +// MANAGE_SELL_OFFER_SELL_NO_TRUST = +// -2, // no trust line for what we're selling +// MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying // MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell // MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED = -5, // not authorized to buy -// MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying -// MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell -// MANAGE_SELL_OFFER_CROSS_SELF = -8, // would cross an offer from the same user +// MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying +// MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell +// MANAGE_SELL_OFFER_CROSS_SELF = +// -8, // would cross an offer from the same user // MANAGE_SELL_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling // MANAGE_SELL_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying // // // update errors -// MANAGE_SELL_OFFER_NOT_FOUND = -11, // offerID does not match an existing offer +// MANAGE_SELL_OFFER_NOT_FOUND = +// -11, // offerID does not match an existing offer // -// MANAGE_SELL_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer +// MANAGE_SELL_OFFER_LOW_RESERVE = +// -12 // not enough funds to create a new Offer // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/MuxedAccount.java b/src/main/java/org/stellar/sdk/xdr/MuxedAccount.java new file mode 100644 index 000000000..b44095e34 --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/MuxedAccount.java @@ -0,0 +1,137 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; + +// === xdr source ============================================================ + +// union MuxedAccount switch (CryptoKeyType type) +// { +// case KEY_TYPE_ED25519: +// uint256 ed25519; +// case KEY_TYPE_MUXED_ED25519: +// struct +// { +// uint64 id; +// uint256 ed25519; +// } med25519; +// }; + +// =========================================================================== +public class MuxedAccount implements XdrElement { + public MuxedAccount () {} + CryptoKeyType type; + public CryptoKeyType getDiscriminant() { + return this.type; + } + public void setDiscriminant(CryptoKeyType value) { + this.type = value; + } + private Uint256 ed25519; + public Uint256 getEd25519() { + return this.ed25519; + } + public void setEd25519(Uint256 value) { + this.ed25519 = value; + } + private MuxedAccountMed25519 med25519; + public MuxedAccountMed25519 getMed25519() { + return this.med25519; + } + public void setMed25519(MuxedAccountMed25519 value) { + this.med25519 = value; + } + public static void encode(XdrDataOutputStream stream, MuxedAccount encodedMuxedAccount) throws IOException { + //Xdrgen::AST::Identifier + //CryptoKeyType + stream.writeInt(encodedMuxedAccount.getDiscriminant().getValue()); + switch (encodedMuxedAccount.getDiscriminant()) { + case KEY_TYPE_ED25519: + Uint256.encode(stream, encodedMuxedAccount.ed25519); + break; + case KEY_TYPE_MUXED_ED25519: + MuxedAccountMed25519.encode(stream, encodedMuxedAccount.med25519); + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static MuxedAccount decode(XdrDataInputStream stream) throws IOException { + MuxedAccount decodedMuxedAccount = new MuxedAccount(); + CryptoKeyType discriminant = CryptoKeyType.decode(stream); + decodedMuxedAccount.setDiscriminant(discriminant); + switch (decodedMuxedAccount.getDiscriminant()) { + case KEY_TYPE_ED25519: + decodedMuxedAccount.ed25519 = Uint256.decode(stream); + break; + case KEY_TYPE_MUXED_ED25519: + decodedMuxedAccount.med25519 = MuxedAccountMed25519.decode(stream); + break; + } + return decodedMuxedAccount; + } + @Override + public int hashCode() { + return Objects.hashCode(this.ed25519, this.med25519, this.type); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof MuxedAccount)) { + return false; + } + + MuxedAccount other = (MuxedAccount) object; + return Objects.equal(this.ed25519, other.ed25519) && Objects.equal(this.med25519, other.med25519) && Objects.equal(this.type, other.type); + } + + public static class MuxedAccountMed25519 { + public MuxedAccountMed25519 () {} + private Uint64 id; + public Uint64 getId() { + return this.id; + } + public void setId(Uint64 value) { + this.id = value; + } + private Uint256 ed25519; + public Uint256 getEd25519() { + return this.ed25519; + } + public void setEd25519(Uint256 value) { + this.ed25519 = value; + } + public static void encode(XdrDataOutputStream stream, MuxedAccountMed25519 encodedMuxedAccountMed25519) throws IOException{ + Uint64.encode(stream, encodedMuxedAccountMed25519.id); + Uint256.encode(stream, encodedMuxedAccountMed25519.ed25519); + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static MuxedAccountMed25519 decode(XdrDataInputStream stream) throws IOException { + MuxedAccountMed25519 decodedMuxedAccountMed25519 = new MuxedAccountMed25519(); + decodedMuxedAccountMed25519.id = Uint64.decode(stream); + decodedMuxedAccountMed25519.ed25519 = Uint256.decode(stream); + return decodedMuxedAccountMed25519; + } + @Override + public int hashCode() { + return Objects.hashCode(this.id, this.ed25519); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof MuxedAccountMed25519)) { + return false; + } + + MuxedAccountMed25519 other = (MuxedAccountMed25519) object; + return Objects.equal(this.id, other.id) && Objects.equal(this.ed25519, other.ed25519); + } + + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/Operation.java b/src/main/java/org/stellar/sdk/xdr/Operation.java index 7dd4f5681..016280f5b 100644 --- a/src/main/java/org/stellar/sdk/xdr/Operation.java +++ b/src/main/java/org/stellar/sdk/xdr/Operation.java @@ -15,7 +15,7 @@ // // sourceAccount is the account used to run the operation // // if not set, the runtime defaults to "sourceAccount" specified at // // the transaction level -// AccountID* sourceAccount; +// MuxedAccount* sourceAccount; // // union switch (OperationType type) // { @@ -36,7 +36,7 @@ // case ALLOW_TRUST: // AllowTrustOp allowTrustOp; // case ACCOUNT_MERGE: -// AccountID destination; +// MuxedAccount destination; // case INFLATION: // void; // case MANAGE_DATA: @@ -54,11 +54,11 @@ // =========================================================================== public class Operation implements XdrElement { public Operation () {} - private AccountID sourceAccount; - public AccountID getSourceAccount() { + private MuxedAccount sourceAccount; + public MuxedAccount getSourceAccount() { return this.sourceAccount; } - public void setSourceAccount(AccountID value) { + public void setSourceAccount(MuxedAccount value) { this.sourceAccount = value; } private OperationBody body; @@ -71,7 +71,7 @@ public void setBody(OperationBody value) { public static void encode(XdrDataOutputStream stream, Operation encodedOperation) throws IOException{ if (encodedOperation.sourceAccount != null) { stream.writeInt(1); - AccountID.encode(stream, encodedOperation.sourceAccount); + MuxedAccount.encode(stream, encodedOperation.sourceAccount); } else { stream.writeInt(0); } @@ -84,7 +84,7 @@ public static Operation decode(XdrDataInputStream stream) throws IOException { Operation decodedOperation = new Operation(); int sourceAccountPresent = stream.readInt(); if (sourceAccountPresent != 0) { - decodedOperation.sourceAccount = AccountID.decode(stream); + decodedOperation.sourceAccount = MuxedAccount.decode(stream); } decodedOperation.body = OperationBody.decode(stream); return decodedOperation; @@ -168,11 +168,11 @@ public AllowTrustOp getAllowTrustOp() { public void setAllowTrustOp(AllowTrustOp value) { this.allowTrustOp = value; } - private AccountID destination; - public AccountID getDestination() { + private MuxedAccount destination; + public MuxedAccount getDestination() { return this.destination; } - public void setDestination(AccountID value) { + public void setDestination(MuxedAccount value) { this.destination = value; } private ManageDataOp manageDataOp; @@ -233,7 +233,7 @@ public static void encode(XdrDataOutputStream stream, OperationBody encodedOpera AllowTrustOp.encode(stream, encodedOperationBody.allowTrustOp); break; case ACCOUNT_MERGE: - AccountID.encode(stream, encodedOperationBody.destination); + MuxedAccount.encode(stream, encodedOperationBody.destination); break; case INFLATION: break; @@ -284,7 +284,7 @@ public static OperationBody decode(XdrDataInputStream stream) throws IOException decodedOperationBody.allowTrustOp = AllowTrustOp.decode(stream); break; case ACCOUNT_MERGE: - decodedOperationBody.destination = AccountID.decode(stream); + decodedOperationBody.destination = MuxedAccount.decode(stream); break; case INFLATION: break; diff --git a/src/main/java/org/stellar/sdk/xdr/OperationResult.java b/src/main/java/org/stellar/sdk/xdr/OperationResult.java index b7c5e6133..392aefdcf 100644 --- a/src/main/java/org/stellar/sdk/xdr/OperationResult.java +++ b/src/main/java/org/stellar/sdk/xdr/OperationResult.java @@ -40,7 +40,7 @@ // case BUMP_SEQUENCE: // BumpSequenceResult bumpSeqResult; // case MANAGE_BUY_OFFER: -// ManageBuyOfferResult manageBuyOfferResult; +// ManageBuyOfferResult manageBuyOfferResult; // case PATH_PAYMENT_STRICT_SEND: // PathPaymentStrictSendResult pathPaymentStrictSendResult; // } diff --git a/src/main/java/org/stellar/sdk/xdr/OperationResultCode.java b/src/main/java/org/stellar/sdk/xdr/OperationResultCode.java index f432d7fcd..91185fe7a 100644 --- a/src/main/java/org/stellar/sdk/xdr/OperationResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/OperationResultCode.java @@ -13,9 +13,9 @@ // { // opINNER = 0, // inner object result is valid // -// opBAD_AUTH = -1, // too few valid signatures / wrong network -// opNO_ACCOUNT = -2, // source account was not found -// opNOT_SUPPORTED = -3, // operation not supported at this time +// opBAD_AUTH = -1, // too few valid signatures / wrong network +// opNO_ACCOUNT = -2, // source account was not found +// opNOT_SUPPORTED = -3, // operation not supported at this time // opTOO_MANY_SUBENTRIES = -4, // max number of subentries already reached // opEXCEEDED_WORK_LIMIT = -5 // operation did too much work // }; diff --git a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveOp.java b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveOp.java index 07cae0689..14e543105 100644 --- a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveOp.java +++ b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveOp.java @@ -18,9 +18,9 @@ // // send (excluding fees). // // The operation will fail if can't be met // -// AccountID destination; // recipient of the payment -// Asset destAsset; // what they end up with -// int64 destAmount; // amount they end up with +// MuxedAccount destination; // recipient of the payment +// Asset destAsset; // what they end up with +// int64 destAmount; // amount they end up with // // Asset path<5>; // additional hops it must go through to get there // }; @@ -42,11 +42,11 @@ public Int64 getSendMax() { public void setSendMax(Int64 value) { this.sendMax = value; } - private AccountID destination; - public AccountID getDestination() { + private MuxedAccount destination; + public MuxedAccount getDestination() { return this.destination; } - public void setDestination(AccountID value) { + public void setDestination(MuxedAccount value) { this.destination = value; } private Asset destAsset; @@ -73,7 +73,7 @@ public void setPath(Asset[] value) { public static void encode(XdrDataOutputStream stream, PathPaymentStrictReceiveOp encodedPathPaymentStrictReceiveOp) throws IOException{ Asset.encode(stream, encodedPathPaymentStrictReceiveOp.sendAsset); Int64.encode(stream, encodedPathPaymentStrictReceiveOp.sendMax); - AccountID.encode(stream, encodedPathPaymentStrictReceiveOp.destination); + MuxedAccount.encode(stream, encodedPathPaymentStrictReceiveOp.destination); Asset.encode(stream, encodedPathPaymentStrictReceiveOp.destAsset); Int64.encode(stream, encodedPathPaymentStrictReceiveOp.destAmount); int pathsize = encodedPathPaymentStrictReceiveOp.getPath().length; @@ -89,7 +89,7 @@ public static PathPaymentStrictReceiveOp decode(XdrDataInputStream stream) throw PathPaymentStrictReceiveOp decodedPathPaymentStrictReceiveOp = new PathPaymentStrictReceiveOp(); decodedPathPaymentStrictReceiveOp.sendAsset = Asset.decode(stream); decodedPathPaymentStrictReceiveOp.sendMax = Int64.decode(stream); - decodedPathPaymentStrictReceiveOp.destination = AccountID.decode(stream); + decodedPathPaymentStrictReceiveOp.destination = MuxedAccount.decode(stream); decodedPathPaymentStrictReceiveOp.destAsset = Asset.decode(stream); decodedPathPaymentStrictReceiveOp.destAmount = Int64.decode(stream); int pathsize = stream.readInt(); diff --git a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveResultCode.java b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveResultCode.java index 6053e2f88..d05eb229d 100644 --- a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictReceiveResultCode.java @@ -15,18 +15,27 @@ // PATH_PAYMENT_STRICT_RECEIVE_SUCCESS = 0, // success // // // codes considered as "failure" for the operation -// PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input -// PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = -2, // not enough funds in source account -// PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = -3, // no trust line on source account -// PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer -// PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = -5, // destination account does not exist -// PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = -6, // dest missing a trust line for asset -// PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = -7, // dest not authorized to hold asset -// PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = -8, // dest would go above their limit -// PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset -// PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = -10, // not enough offers to satisfy path -// PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = -11, // would cross one of its own offers -// PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax +// PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input +// PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED = +// -2, // not enough funds in source account +// PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST = +// -3, // no trust line on source account +// PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED = +// -4, // source not authorized to transfer +// PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION = +// -5, // destination account does not exist +// PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST = +// -6, // dest missing a trust line for asset +// PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED = +// -7, // dest not authorized to hold asset +// PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL = +// -8, // dest would go above their limit +// PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset +// PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS = +// -10, // not enough offers to satisfy path +// PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF = +// -11, // would cross one of its own offers +// PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendOp.java b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendOp.java index 8380c756c..242f0cec2 100644 --- a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendOp.java +++ b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendOp.java @@ -16,11 +16,11 @@ // Asset sendAsset; // asset we pay with // int64 sendAmount; // amount of sendAsset to send (excluding fees) // -// AccountID destination; // recipient of the payment -// Asset destAsset; // what they end up with -// int64 destMin; // the minimum amount of dest asset to -// // be received -// // The operation will fail if it can't be met +// MuxedAccount destination; // recipient of the payment +// Asset destAsset; // what they end up with +// int64 destMin; // the minimum amount of dest asset to +// // be received +// // The operation will fail if it can't be met // // Asset path<5>; // additional hops it must go through to get there // }; @@ -42,11 +42,11 @@ public Int64 getSendAmount() { public void setSendAmount(Int64 value) { this.sendAmount = value; } - private AccountID destination; - public AccountID getDestination() { + private MuxedAccount destination; + public MuxedAccount getDestination() { return this.destination; } - public void setDestination(AccountID value) { + public void setDestination(MuxedAccount value) { this.destination = value; } private Asset destAsset; @@ -73,7 +73,7 @@ public void setPath(Asset[] value) { public static void encode(XdrDataOutputStream stream, PathPaymentStrictSendOp encodedPathPaymentStrictSendOp) throws IOException{ Asset.encode(stream, encodedPathPaymentStrictSendOp.sendAsset); Int64.encode(stream, encodedPathPaymentStrictSendOp.sendAmount); - AccountID.encode(stream, encodedPathPaymentStrictSendOp.destination); + MuxedAccount.encode(stream, encodedPathPaymentStrictSendOp.destination); Asset.encode(stream, encodedPathPaymentStrictSendOp.destAsset); Int64.encode(stream, encodedPathPaymentStrictSendOp.destMin); int pathsize = encodedPathPaymentStrictSendOp.getPath().length; @@ -89,7 +89,7 @@ public static PathPaymentStrictSendOp decode(XdrDataInputStream stream) throws I PathPaymentStrictSendOp decodedPathPaymentStrictSendOp = new PathPaymentStrictSendOp(); decodedPathPaymentStrictSendOp.sendAsset = Asset.decode(stream); decodedPathPaymentStrictSendOp.sendAmount = Int64.decode(stream); - decodedPathPaymentStrictSendOp.destination = AccountID.decode(stream); + decodedPathPaymentStrictSendOp.destination = MuxedAccount.decode(stream); decodedPathPaymentStrictSendOp.destAsset = Asset.decode(stream); decodedPathPaymentStrictSendOp.destMin = Int64.decode(stream); int pathsize = stream.readInt(); diff --git a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendResultCode.java b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendResultCode.java index e95ca29f2..375941336 100644 --- a/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/PathPaymentStrictSendResultCode.java @@ -15,18 +15,26 @@ // PATH_PAYMENT_STRICT_SEND_SUCCESS = 0, // success // // // codes considered as "failure" for the operation -// PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input -// PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = -2, // not enough funds in source account -// PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = -3, // no trust line on source account -// PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer -// PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = -5, // destination account does not exist -// PATH_PAYMENT_STRICT_SEND_NO_TRUST = -6, // dest missing a trust line for asset -// PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = -7, // dest not authorized to hold asset -// PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit -// PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset -// PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = -10, // not enough offers to satisfy path -// PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = -11, // would cross one of its own offers -// PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin +// PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input +// PATH_PAYMENT_STRICT_SEND_UNDERFUNDED = +// -2, // not enough funds in source account +// PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST = +// -3, // no trust line on source account +// PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED = +// -4, // source not authorized to transfer +// PATH_PAYMENT_STRICT_SEND_NO_DESTINATION = +// -5, // destination account does not exist +// PATH_PAYMENT_STRICT_SEND_NO_TRUST = +// -6, // dest missing a trust line for asset +// PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED = +// -7, // dest not authorized to hold asset +// PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit +// PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset +// PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS = +// -10, // not enough offers to satisfy path +// PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF = +// -11, // would cross one of its own offers +// PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/PaymentOp.java b/src/main/java/org/stellar/sdk/xdr/PaymentOp.java index 101058a50..940b8adb2 100644 --- a/src/main/java/org/stellar/sdk/xdr/PaymentOp.java +++ b/src/main/java/org/stellar/sdk/xdr/PaymentOp.java @@ -12,19 +12,19 @@ // struct PaymentOp // { -// AccountID destination; // recipient of the payment -// Asset asset; // what they end up with -// int64 amount; // amount they end up with +// MuxedAccount destination; // recipient of the payment +// Asset asset; // what they end up with +// int64 amount; // amount they end up with // }; // =========================================================================== public class PaymentOp implements XdrElement { public PaymentOp () {} - private AccountID destination; - public AccountID getDestination() { + private MuxedAccount destination; + public MuxedAccount getDestination() { return this.destination; } - public void setDestination(AccountID value) { + public void setDestination(MuxedAccount value) { this.destination = value; } private Asset asset; @@ -42,7 +42,7 @@ public void setAmount(Int64 value) { this.amount = value; } public static void encode(XdrDataOutputStream stream, PaymentOp encodedPaymentOp) throws IOException{ - AccountID.encode(stream, encodedPaymentOp.destination); + MuxedAccount.encode(stream, encodedPaymentOp.destination); Asset.encode(stream, encodedPaymentOp.asset); Int64.encode(stream, encodedPaymentOp.amount); } @@ -51,7 +51,7 @@ public void encode(XdrDataOutputStream stream) throws IOException { } public static PaymentOp decode(XdrDataInputStream stream) throws IOException { PaymentOp decodedPaymentOp = new PaymentOp(); - decodedPaymentOp.destination = AccountID.decode(stream); + decodedPaymentOp.destination = MuxedAccount.decode(stream); decodedPaymentOp.asset = Asset.decode(stream); decodedPaymentOp.amount = Int64.decode(stream); return decodedPaymentOp; diff --git a/src/main/java/org/stellar/sdk/xdr/SurveyResponseBody.java b/src/main/java/org/stellar/sdk/xdr/SurveyResponseBody.java index 25e5556b2..852308b82 100644 --- a/src/main/java/org/stellar/sdk/xdr/SurveyResponseBody.java +++ b/src/main/java/org/stellar/sdk/xdr/SurveyResponseBody.java @@ -12,8 +12,8 @@ // union SurveyResponseBody switch (SurveyMessageCommandType type) // { -// case SURVEY_TOPOLOGY: -// TopologyResponseBody topologyResponseBody; +// case SURVEY_TOPOLOGY: +// TopologyResponseBody topologyResponseBody; // }; // =========================================================================== diff --git a/src/main/java/org/stellar/sdk/xdr/Transaction.java b/src/main/java/org/stellar/sdk/xdr/Transaction.java index cc72a3392..f9f9c435a 100644 --- a/src/main/java/org/stellar/sdk/xdr/Transaction.java +++ b/src/main/java/org/stellar/sdk/xdr/Transaction.java @@ -14,7 +14,7 @@ // struct Transaction // { // // account used to run the transaction -// AccountID sourceAccount; +// MuxedAccount sourceAccount; // // // the fee the sourceAccount will pay // uint32 fee; @@ -41,11 +41,11 @@ // =========================================================================== public class Transaction implements XdrElement { public Transaction () {} - private AccountID sourceAccount; - public AccountID getSourceAccount() { + private MuxedAccount sourceAccount; + public MuxedAccount getSourceAccount() { return this.sourceAccount; } - public void setSourceAccount(AccountID value) { + public void setSourceAccount(MuxedAccount value) { this.sourceAccount = value; } private Uint32 fee; @@ -91,7 +91,7 @@ public void setExt(TransactionExt value) { this.ext = value; } public static void encode(XdrDataOutputStream stream, Transaction encodedTransaction) throws IOException{ - AccountID.encode(stream, encodedTransaction.sourceAccount); + MuxedAccount.encode(stream, encodedTransaction.sourceAccount); Uint32.encode(stream, encodedTransaction.fee); SequenceNumber.encode(stream, encodedTransaction.seqNum); if (encodedTransaction.timeBounds != null) { @@ -113,7 +113,7 @@ public void encode(XdrDataOutputStream stream) throws IOException { } public static Transaction decode(XdrDataInputStream stream) throws IOException { Transaction decodedTransaction = new Transaction(); - decodedTransaction.sourceAccount = AccountID.decode(stream); + decodedTransaction.sourceAccount = MuxedAccount.decode(stream); decodedTransaction.fee = Uint32.decode(stream); decodedTransaction.seqNum = SequenceNumber.decode(stream); int timeBoundsPresent = stream.readInt(); diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionEnvelope.java b/src/main/java/org/stellar/sdk/xdr/TransactionEnvelope.java index ff55d0a09..4d966c830 100644 --- a/src/main/java/org/stellar/sdk/xdr/TransactionEnvelope.java +++ b/src/main/java/org/stellar/sdk/xdr/TransactionEnvelope.java @@ -7,59 +7,89 @@ import java.io.IOException; import com.google.common.base.Objects; -import java.util.Arrays; // === xdr source ============================================================ -// struct TransactionEnvelope +// union TransactionEnvelope switch (EnvelopeType type) // { -// Transaction tx; -// /* Each decorated signature is a signature over the SHA256 hash of -// * a TransactionSignaturePayload */ -// DecoratedSignature signatures<20>; +// case ENVELOPE_TYPE_TX_V0: +// TransactionV0Envelope v0; +// case ENVELOPE_TYPE_TX: +// TransactionV1Envelope v1; +// case ENVELOPE_TYPE_TX_FEE_BUMP: +// FeeBumpTransactionEnvelope feeBump; // }; // =========================================================================== public class TransactionEnvelope implements XdrElement { public TransactionEnvelope () {} - private Transaction tx; - public Transaction getTx() { - return this.tx; + EnvelopeType type; + public EnvelopeType getDiscriminant() { + return this.type; } - public void setTx(Transaction value) { - this.tx = value; + public void setDiscriminant(EnvelopeType value) { + this.type = value; } - private DecoratedSignature[] signatures; - public DecoratedSignature[] getSignatures() { - return this.signatures; + private TransactionV0Envelope v0; + public TransactionV0Envelope getV0() { + return this.v0; } - public void setSignatures(DecoratedSignature[] value) { - this.signatures = value; + public void setV0(TransactionV0Envelope value) { + this.v0 = value; + } + private TransactionV1Envelope v1; + public TransactionV1Envelope getV1() { + return this.v1; + } + public void setV1(TransactionV1Envelope value) { + this.v1 = value; + } + private FeeBumpTransactionEnvelope feeBump; + public FeeBumpTransactionEnvelope getFeeBump() { + return this.feeBump; + } + public void setFeeBump(FeeBumpTransactionEnvelope value) { + this.feeBump = value; + } + public static void encode(XdrDataOutputStream stream, TransactionEnvelope encodedTransactionEnvelope) throws IOException { + //Xdrgen::AST::Identifier + //EnvelopeType + stream.writeInt(encodedTransactionEnvelope.getDiscriminant().getValue()); + switch (encodedTransactionEnvelope.getDiscriminant()) { + case ENVELOPE_TYPE_TX_V0: + TransactionV0Envelope.encode(stream, encodedTransactionEnvelope.v0); + break; + case ENVELOPE_TYPE_TX: + TransactionV1Envelope.encode(stream, encodedTransactionEnvelope.v1); + break; + case ENVELOPE_TYPE_TX_FEE_BUMP: + FeeBumpTransactionEnvelope.encode(stream, encodedTransactionEnvelope.feeBump); + break; } - public static void encode(XdrDataOutputStream stream, TransactionEnvelope encodedTransactionEnvelope) throws IOException{ - Transaction.encode(stream, encodedTransactionEnvelope.tx); - int signaturessize = encodedTransactionEnvelope.getSignatures().length; - stream.writeInt(signaturessize); - for (int i = 0; i < signaturessize; i++) { - DecoratedSignature.encode(stream, encodedTransactionEnvelope.signatures[i]); - } } public void encode(XdrDataOutputStream stream) throws IOException { encode(stream, this); } public static TransactionEnvelope decode(XdrDataInputStream stream) throws IOException { - TransactionEnvelope decodedTransactionEnvelope = new TransactionEnvelope(); - decodedTransactionEnvelope.tx = Transaction.decode(stream); - int signaturessize = stream.readInt(); - decodedTransactionEnvelope.signatures = new DecoratedSignature[signaturessize]; - for (int i = 0; i < signaturessize; i++) { - decodedTransactionEnvelope.signatures[i] = DecoratedSignature.decode(stream); - } + TransactionEnvelope decodedTransactionEnvelope = new TransactionEnvelope(); + EnvelopeType discriminant = EnvelopeType.decode(stream); + decodedTransactionEnvelope.setDiscriminant(discriminant); + switch (decodedTransactionEnvelope.getDiscriminant()) { + case ENVELOPE_TYPE_TX_V0: + decodedTransactionEnvelope.v0 = TransactionV0Envelope.decode(stream); + break; + case ENVELOPE_TYPE_TX: + decodedTransactionEnvelope.v1 = TransactionV1Envelope.decode(stream); + break; + case ENVELOPE_TYPE_TX_FEE_BUMP: + decodedTransactionEnvelope.feeBump = FeeBumpTransactionEnvelope.decode(stream); + break; + } return decodedTransactionEnvelope; } @Override public int hashCode() { - return Objects.hashCode(this.tx, Arrays.hashCode(this.signatures)); + return Objects.hashCode(this.v0, this.v1, this.feeBump, this.type); } @Override public boolean equals(Object object) { @@ -68,6 +98,6 @@ public boolean equals(Object object) { } TransactionEnvelope other = (TransactionEnvelope) object; - return Objects.equal(this.tx, other.tx) && Arrays.equals(this.signatures, other.signatures); + return Objects.equal(this.v0, other.v0) && Objects.equal(this.v1, other.v1) && Objects.equal(this.feeBump, other.feeBump) && Objects.equal(this.type, other.type); } } diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionResult.java b/src/main/java/org/stellar/sdk/xdr/TransactionResult.java index 7ce372e11..f0c210268 100644 --- a/src/main/java/org/stellar/sdk/xdr/TransactionResult.java +++ b/src/main/java/org/stellar/sdk/xdr/TransactionResult.java @@ -17,6 +17,9 @@ // // union switch (TransactionResultCode code) // { +// case txFEE_BUMP_INNER_SUCCESS: +// case txFEE_BUMP_INNER_FAILED: +// InnerTransactionResultPair innerResultPair; // case txSUCCESS: // case txFAILED: // OperationResult results<>; @@ -96,6 +99,13 @@ public TransactionResultCode getDiscriminant() { public void setDiscriminant(TransactionResultCode value) { this.code = value; } + private InnerTransactionResultPair innerResultPair; + public InnerTransactionResultPair getInnerResultPair() { + return this.innerResultPair; + } + public void setInnerResultPair(InnerTransactionResultPair value) { + this.innerResultPair = value; + } private OperationResult[] results; public OperationResult[] getResults() { return this.results; @@ -108,6 +118,10 @@ public static void encode(XdrDataOutputStream stream, TransactionResultResult en //TransactionResultCode stream.writeInt(encodedTransactionResultResult.getDiscriminant().getValue()); switch (encodedTransactionResultResult.getDiscriminant()) { + case txFEE_BUMP_INNER_SUCCESS: + case txFEE_BUMP_INNER_FAILED: + InnerTransactionResultPair.encode(stream, encodedTransactionResultResult.innerResultPair); + break; case txSUCCESS: case txFAILED: int resultssize = encodedTransactionResultResult.getResults().length; @@ -128,6 +142,10 @@ public static TransactionResultResult decode(XdrDataInputStream stream) throws I TransactionResultCode discriminant = TransactionResultCode.decode(stream); decodedTransactionResultResult.setDiscriminant(discriminant); switch (decodedTransactionResultResult.getDiscriminant()) { + case txFEE_BUMP_INNER_SUCCESS: + case txFEE_BUMP_INNER_FAILED: + decodedTransactionResultResult.innerResultPair = InnerTransactionResultPair.decode(stream); + break; case txSUCCESS: case txFAILED: int resultssize = stream.readInt(); @@ -143,7 +161,7 @@ public static TransactionResultResult decode(XdrDataInputStream stream) throws I } @Override public int hashCode() { - return Objects.hashCode(Arrays.hashCode(this.results), this.code); + return Objects.hashCode(this.innerResultPair, Arrays.hashCode(this.results), this.code); } @Override public boolean equals(Object object) { @@ -152,7 +170,7 @@ public boolean equals(Object object) { } TransactionResultResult other = (TransactionResultResult) object; - return Arrays.equals(this.results, other.results) && Objects.equal(this.code, other.code); + return Objects.equal(this.innerResultPair, other.innerResultPair) && Arrays.equals(this.results, other.results) && Objects.equal(this.code, other.code); } } diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionResultCode.java b/src/main/java/org/stellar/sdk/xdr/TransactionResultCode.java index 914ca9ff9..ab6763de8 100644 --- a/src/main/java/org/stellar/sdk/xdr/TransactionResultCode.java +++ b/src/main/java/org/stellar/sdk/xdr/TransactionResultCode.java @@ -11,7 +11,8 @@ // enum TransactionResultCode // { -// txSUCCESS = 0, // all operations succeeded +// txFEE_BUMP_INNER_SUCCESS = 1, // fee bump inner transaction succeeded +// txSUCCESS = 0, // all operations succeeded // // txFAILED = -1, // one of the operations failed (none were applied) // @@ -25,11 +26,15 @@ // txNO_ACCOUNT = -8, // source account not found // txINSUFFICIENT_FEE = -9, // fee is too small // txBAD_AUTH_EXTRA = -10, // unused signatures attached to transaction -// txINTERNAL_ERROR = -11 // an unknown error occured +// txINTERNAL_ERROR = -11, // an unknown error occured +// +// txNOT_SUPPORTED = -12, // transaction type not supported +// txFEE_BUMP_INNER_FAILED = -13 // fee bump inner transaction failed // }; // =========================================================================== public enum TransactionResultCode implements XdrElement { + txFEE_BUMP_INNER_SUCCESS(1), txSUCCESS(0), txFAILED(-1), txTOO_EARLY(-2), @@ -42,6 +47,8 @@ public enum TransactionResultCode implements XdrElement { txINSUFFICIENT_FEE(-9), txBAD_AUTH_EXTRA(-10), txINTERNAL_ERROR(-11), + txNOT_SUPPORTED(-12), + txFEE_BUMP_INNER_FAILED(-13), ; private int mValue; @@ -56,6 +63,7 @@ public int getValue() { public static TransactionResultCode decode(XdrDataInputStream stream) throws IOException { int value = stream.readInt(); switch (value) { + case 1: return txFEE_BUMP_INNER_SUCCESS; case 0: return txSUCCESS; case -1: return txFAILED; case -2: return txTOO_EARLY; @@ -68,6 +76,8 @@ public static TransactionResultCode decode(XdrDataInputStream stream) throws IOE case -9: return txINSUFFICIENT_FEE; case -10: return txBAD_AUTH_EXTRA; case -11: return txINTERNAL_ERROR; + case -12: return txNOT_SUPPORTED; + case -13: return txFEE_BUMP_INNER_FAILED; default: throw new RuntimeException("Unknown enum value: " + value); } diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionSignaturePayload.java b/src/main/java/org/stellar/sdk/xdr/TransactionSignaturePayload.java index d549cca34..916faee0c 100644 --- a/src/main/java/org/stellar/sdk/xdr/TransactionSignaturePayload.java +++ b/src/main/java/org/stellar/sdk/xdr/TransactionSignaturePayload.java @@ -15,9 +15,11 @@ // Hash networkId; // union switch (EnvelopeType type) // { +// // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0 // case ENVELOPE_TYPE_TX: // Transaction tx; -// /* All other values of type are invalid */ +// case ENVELOPE_TYPE_TX_FEE_BUMP: +// FeeBumpTransaction feeBump; // } // taggedTransaction; // }; @@ -82,6 +84,13 @@ public Transaction getTx() { public void setTx(Transaction value) { this.tx = value; } + private FeeBumpTransaction feeBump; + public FeeBumpTransaction getFeeBump() { + return this.feeBump; + } + public void setFeeBump(FeeBumpTransaction value) { + this.feeBump = value; + } public static void encode(XdrDataOutputStream stream, TransactionSignaturePayloadTaggedTransaction encodedTransactionSignaturePayloadTaggedTransaction) throws IOException { //Xdrgen::AST::Identifier //EnvelopeType @@ -90,6 +99,9 @@ public static void encode(XdrDataOutputStream stream, TransactionSignaturePayloa case ENVELOPE_TYPE_TX: Transaction.encode(stream, encodedTransactionSignaturePayloadTaggedTransaction.tx); break; + case ENVELOPE_TYPE_TX_FEE_BUMP: + FeeBumpTransaction.encode(stream, encodedTransactionSignaturePayloadTaggedTransaction.feeBump); + break; } } public void encode(XdrDataOutputStream stream) throws IOException { @@ -103,12 +115,15 @@ public static TransactionSignaturePayloadTaggedTransaction decode(XdrDataInputSt case ENVELOPE_TYPE_TX: decodedTransactionSignaturePayloadTaggedTransaction.tx = Transaction.decode(stream); break; + case ENVELOPE_TYPE_TX_FEE_BUMP: + decodedTransactionSignaturePayloadTaggedTransaction.feeBump = FeeBumpTransaction.decode(stream); + break; } return decodedTransactionSignaturePayloadTaggedTransaction; } @Override public int hashCode() { - return Objects.hashCode(this.tx, this.type); + return Objects.hashCode(this.tx, this.feeBump, this.type); } @Override public boolean equals(Object object) { @@ -117,7 +132,7 @@ public boolean equals(Object object) { } TransactionSignaturePayloadTaggedTransaction other = (TransactionSignaturePayloadTaggedTransaction) object; - return Objects.equal(this.tx, other.tx) && Objects.equal(this.type, other.type); + return Objects.equal(this.tx, other.tx) && Objects.equal(this.feeBump, other.feeBump) && Objects.equal(this.type, other.type); } } diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionV0.java b/src/main/java/org/stellar/sdk/xdr/TransactionV0.java new file mode 100644 index 000000000..265650718 --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/TransactionV0.java @@ -0,0 +1,181 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; +import java.util.Arrays; + +// === xdr source ============================================================ + +// struct TransactionV0 +// { +// uint256 sourceAccountEd25519; +// uint32 fee; +// SequenceNumber seqNum; +// TimeBounds* timeBounds; +// Memo memo; +// Operation operations; +// union switch (int v) +// { +// case 0: +// void; +// } +// ext; +// }; + +// =========================================================================== +public class TransactionV0 implements XdrElement { + public TransactionV0 () {} + private Uint256 sourceAccountEd25519; + public Uint256 getSourceAccountEd25519() { + return this.sourceAccountEd25519; + } + public void setSourceAccountEd25519(Uint256 value) { + this.sourceAccountEd25519 = value; + } + private Uint32 fee; + public Uint32 getFee() { + return this.fee; + } + public void setFee(Uint32 value) { + this.fee = value; + } + private SequenceNumber seqNum; + public SequenceNumber getSeqNum() { + return this.seqNum; + } + public void setSeqNum(SequenceNumber value) { + this.seqNum = value; + } + private TimeBounds timeBounds; + public TimeBounds getTimeBounds() { + return this.timeBounds; + } + public void setTimeBounds(TimeBounds value) { + this.timeBounds = value; + } + private Memo memo; + public Memo getMemo() { + return this.memo; + } + public void setMemo(Memo value) { + this.memo = value; + } + private Operation[] operations; + public Operation[] getOperations() { + return this.operations; + } + public void setOperations(Operation[] value) { + this.operations = value; + } + private TransactionV0Ext ext; + public TransactionV0Ext getExt() { + return this.ext; + } + public void setExt(TransactionV0Ext value) { + this.ext = value; + } + public static void encode(XdrDataOutputStream stream, TransactionV0 encodedTransactionV0) throws IOException{ + Uint256.encode(stream, encodedTransactionV0.sourceAccountEd25519); + Uint32.encode(stream, encodedTransactionV0.fee); + SequenceNumber.encode(stream, encodedTransactionV0.seqNum); + if (encodedTransactionV0.timeBounds != null) { + stream.writeInt(1); + TimeBounds.encode(stream, encodedTransactionV0.timeBounds); + } else { + stream.writeInt(0); + } + Memo.encode(stream, encodedTransactionV0.memo); + int operationssize = encodedTransactionV0.getOperations().length; + stream.writeInt(operationssize); + for (int i = 0; i < operationssize; i++) { + Operation.encode(stream, encodedTransactionV0.operations[i]); + } + TransactionV0Ext.encode(stream, encodedTransactionV0.ext); + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static TransactionV0 decode(XdrDataInputStream stream) throws IOException { + TransactionV0 decodedTransactionV0 = new TransactionV0(); + decodedTransactionV0.sourceAccountEd25519 = Uint256.decode(stream); + decodedTransactionV0.fee = Uint32.decode(stream); + decodedTransactionV0.seqNum = SequenceNumber.decode(stream); + int timeBoundsPresent = stream.readInt(); + if (timeBoundsPresent != 0) { + decodedTransactionV0.timeBounds = TimeBounds.decode(stream); + } + decodedTransactionV0.memo = Memo.decode(stream); + int operationssize = stream.readInt(); + decodedTransactionV0.operations = new Operation[operationssize]; + for (int i = 0; i < operationssize; i++) { + decodedTransactionV0.operations[i] = Operation.decode(stream); + } + decodedTransactionV0.ext = TransactionV0Ext.decode(stream); + return decodedTransactionV0; + } + @Override + public int hashCode() { + return Objects.hashCode(this.sourceAccountEd25519, this.fee, this.seqNum, this.timeBounds, this.memo, Arrays.hashCode(this.operations), this.ext); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof TransactionV0)) { + return false; + } + + TransactionV0 other = (TransactionV0) object; + return Objects.equal(this.sourceAccountEd25519, other.sourceAccountEd25519) && Objects.equal(this.fee, other.fee) && Objects.equal(this.seqNum, other.seqNum) && Objects.equal(this.timeBounds, other.timeBounds) && Objects.equal(this.memo, other.memo) && Arrays.equals(this.operations, other.operations) && Objects.equal(this.ext, other.ext); + } + + public static class TransactionV0Ext { + public TransactionV0Ext () {} + Integer v; + public Integer getDiscriminant() { + return this.v; + } + public void setDiscriminant(Integer value) { + this.v = value; + } + public static void encode(XdrDataOutputStream stream, TransactionV0Ext encodedTransactionV0Ext) throws IOException { + //Xdrgen::AST::Typespecs::Int + //Integer + stream.writeInt(encodedTransactionV0Ext.getDiscriminant().intValue()); + switch (encodedTransactionV0Ext.getDiscriminant()) { + case 0: + break; + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static TransactionV0Ext decode(XdrDataInputStream stream) throws IOException { + TransactionV0Ext decodedTransactionV0Ext = new TransactionV0Ext(); + Integer discriminant = stream.readInt(); + decodedTransactionV0Ext.setDiscriminant(discriminant); + switch (decodedTransactionV0Ext.getDiscriminant()) { + case 0: + break; + } + return decodedTransactionV0Ext; + } + @Override + public int hashCode() { + return Objects.hashCode(this.v); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof TransactionV0Ext)) { + return false; + } + + TransactionV0Ext other = (TransactionV0Ext) object; + return Objects.equal(this.v, other.v); + } + + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionV0Envelope.java b/src/main/java/org/stellar/sdk/xdr/TransactionV0Envelope.java new file mode 100644 index 000000000..90577e8e9 --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/TransactionV0Envelope.java @@ -0,0 +1,73 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; +import java.util.Arrays; + +// === xdr source ============================================================ + +// struct TransactionV0Envelope +// { +// TransactionV0 tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; + +// =========================================================================== +public class TransactionV0Envelope implements XdrElement { + public TransactionV0Envelope () {} + private TransactionV0 tx; + public TransactionV0 getTx() { + return this.tx; + } + public void setTx(TransactionV0 value) { + this.tx = value; + } + private DecoratedSignature[] signatures; + public DecoratedSignature[] getSignatures() { + return this.signatures; + } + public void setSignatures(DecoratedSignature[] value) { + this.signatures = value; + } + public static void encode(XdrDataOutputStream stream, TransactionV0Envelope encodedTransactionV0Envelope) throws IOException{ + TransactionV0.encode(stream, encodedTransactionV0Envelope.tx); + int signaturessize = encodedTransactionV0Envelope.getSignatures().length; + stream.writeInt(signaturessize); + for (int i = 0; i < signaturessize; i++) { + DecoratedSignature.encode(stream, encodedTransactionV0Envelope.signatures[i]); + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static TransactionV0Envelope decode(XdrDataInputStream stream) throws IOException { + TransactionV0Envelope decodedTransactionV0Envelope = new TransactionV0Envelope(); + decodedTransactionV0Envelope.tx = TransactionV0.decode(stream); + int signaturessize = stream.readInt(); + decodedTransactionV0Envelope.signatures = new DecoratedSignature[signaturessize]; + for (int i = 0; i < signaturessize; i++) { + decodedTransactionV0Envelope.signatures[i] = DecoratedSignature.decode(stream); + } + return decodedTransactionV0Envelope; + } + @Override + public int hashCode() { + return Objects.hashCode(this.tx, Arrays.hashCode(this.signatures)); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof TransactionV0Envelope)) { + return false; + } + + TransactionV0Envelope other = (TransactionV0Envelope) object; + return Objects.equal(this.tx, other.tx) && Arrays.equals(this.signatures, other.signatures); + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/TransactionV1Envelope.java b/src/main/java/org/stellar/sdk/xdr/TransactionV1Envelope.java new file mode 100644 index 000000000..f11777a5b --- /dev/null +++ b/src/main/java/org/stellar/sdk/xdr/TransactionV1Envelope.java @@ -0,0 +1,73 @@ +// Automatically generated by xdrgen +// DO NOT EDIT or your changes may be overwritten + +package org.stellar.sdk.xdr; + + +import java.io.IOException; + +import com.google.common.base.Objects; +import java.util.Arrays; + +// === xdr source ============================================================ + +// struct TransactionV1Envelope +// { +// Transaction tx; +// /* Each decorated signature is a signature over the SHA256 hash of +// * a TransactionSignaturePayload */ +// DecoratedSignature signatures<20>; +// }; + +// =========================================================================== +public class TransactionV1Envelope implements XdrElement { + public TransactionV1Envelope () {} + private Transaction tx; + public Transaction getTx() { + return this.tx; + } + public void setTx(Transaction value) { + this.tx = value; + } + private DecoratedSignature[] signatures; + public DecoratedSignature[] getSignatures() { + return this.signatures; + } + public void setSignatures(DecoratedSignature[] value) { + this.signatures = value; + } + public static void encode(XdrDataOutputStream stream, TransactionV1Envelope encodedTransactionV1Envelope) throws IOException{ + Transaction.encode(stream, encodedTransactionV1Envelope.tx); + int signaturessize = encodedTransactionV1Envelope.getSignatures().length; + stream.writeInt(signaturessize); + for (int i = 0; i < signaturessize; i++) { + DecoratedSignature.encode(stream, encodedTransactionV1Envelope.signatures[i]); + } + } + public void encode(XdrDataOutputStream stream) throws IOException { + encode(stream, this); + } + public static TransactionV1Envelope decode(XdrDataInputStream stream) throws IOException { + TransactionV1Envelope decodedTransactionV1Envelope = new TransactionV1Envelope(); + decodedTransactionV1Envelope.tx = Transaction.decode(stream); + int signaturessize = stream.readInt(); + decodedTransactionV1Envelope.signatures = new DecoratedSignature[signaturessize]; + for (int i = 0; i < signaturessize; i++) { + decodedTransactionV1Envelope.signatures[i] = DecoratedSignature.decode(stream); + } + return decodedTransactionV1Envelope; + } + @Override + public int hashCode() { + return Objects.hashCode(this.tx, Arrays.hashCode(this.signatures)); + } + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof TransactionV1Envelope)) { + return false; + } + + TransactionV1Envelope other = (TransactionV1Envelope) object; + return Objects.equal(this.tx, other.tx) && Arrays.equals(this.signatures, other.signatures); + } +} diff --git a/src/main/java/org/stellar/sdk/xdr/TrustLineFlags.java b/src/main/java/org/stellar/sdk/xdr/TrustLineFlags.java index ccc1a962d..5148ea545 100644 --- a/src/main/java/org/stellar/sdk/xdr/TrustLineFlags.java +++ b/src/main/java/org/stellar/sdk/xdr/TrustLineFlags.java @@ -12,12 +12,16 @@ // enum TrustLineFlags // { // // issuer has authorized account to perform transactions with its credit -// AUTHORIZED_FLAG = 1 +// AUTHORIZED_FLAG = 1, +// // issuer has authorized account to maintain and reduce liabilities for its +// // credit +// AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG = 2 // }; // =========================================================================== public enum TrustLineFlags implements XdrElement { AUTHORIZED_FLAG(1), + AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG(2), ; private int mValue; @@ -33,6 +37,7 @@ public static TrustLineFlags decode(XdrDataInputStream stream) throws IOExceptio int value = stream.readInt(); switch (value) { case 1: return AUTHORIZED_FLAG; + case 2: return AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG; default: throw new RuntimeException("Unknown enum value: " + value); } From 3e9e4a6b61545055be6da6385955ec23f98b86ca Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Tue, 21 Apr 2020 17:11:18 +0200 Subject: [PATCH 3/7] Update Transaction to use new xdr definitions --- .../stellar/sdk/AccountMergeOperation.java | 6 +- .../org/stellar/sdk/AllowTrustOperation.java | 43 +++++- src/main/java/org/stellar/sdk/Asset.java | 8 +- .../stellar/sdk/CreateAccountOperation.java | 2 +- src/main/java/org/stellar/sdk/Operation.java | 4 +- .../PathPaymentStrictReceiveOperation.java | 4 +- .../sdk/PathPaymentStrictSendOperation.java | 4 +- .../org/stellar/sdk/PaymentOperation.java | 4 +- .../org/stellar/sdk/SetOptionsOperation.java | 2 +- src/main/java/org/stellar/sdk/StrKey.java | 73 +++++++++- .../java/org/stellar/sdk/Transaction.java | 135 +++++++++++++----- .../responses/TransactionDeserializer.java | 19 ++- .../java/org/stellar/sdk/OperationTest.java | 8 +- .../sdk/xdr/TransactionDecodeTest.java | 6 +- 14 files changed, 244 insertions(+), 74 deletions(-) diff --git a/src/main/java/org/stellar/sdk/AccountMergeOperation.java b/src/main/java/org/stellar/sdk/AccountMergeOperation.java index 4c0a0baa5..3be2246d4 100644 --- a/src/main/java/org/stellar/sdk/AccountMergeOperation.java +++ b/src/main/java/org/stellar/sdk/AccountMergeOperation.java @@ -28,7 +28,7 @@ public String getDestination() { @Override OperationBody toOperationBody() { OperationBody body = new org.stellar.sdk.xdr.Operation.OperationBody(); - body.setDestination(StrKey.encodeToXDRAccountId(this.destination)); + body.setDestination(StrKey.encodeToXDRMuxedAccount(this.destination)); body.setDiscriminant(OperationType.ACCOUNT_MERGE); return body; } @@ -43,8 +43,8 @@ public static class Builder { private String mSourceAccount; Builder(OperationBody op) { - destination = StrKey.encodeStellarAccountId( - op.getDestination().getAccountID().getEd25519().getUint256() + destination = StrKey.encodeStellarMuxedAccount( + op.getDestination() ); } diff --git a/src/main/java/org/stellar/sdk/AllowTrustOperation.java b/src/main/java/org/stellar/sdk/AllowTrustOperation.java index 21ec896a2..2ffab62b3 100644 --- a/src/main/java/org/stellar/sdk/AllowTrustOperation.java +++ b/src/main/java/org/stellar/sdk/AllowTrustOperation.java @@ -14,11 +14,13 @@ public class AllowTrustOperation extends Operation { private final String trustor; private final String assetCode; private final boolean authorize; + private final boolean authorizeToMaintainLiabilities; - private AllowTrustOperation(String trustor, String assetCode, boolean authorize) { + private AllowTrustOperation(String trustor, String assetCode, boolean authorize, boolean authorizeToMaintainLiabilities) { this.trustor = checkNotNull(trustor, "trustor cannot be null"); this.assetCode = checkNotNull(assetCode, "assetCode cannot be null"); this.authorize = authorize; + this.authorizeToMaintainLiabilities = authorizeToMaintainLiabilities; } /** @@ -62,8 +64,16 @@ org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { asset.setAssetCode12(assetCode12); } op.setAsset(asset); + Uint32 flag = new Uint32(); // authorize - op.setAuthorize(authorize); + if (authorize) { + flag.setUint32(TrustLineFlags.AUTHORIZED_FLAG.getValue()); + } else if (authorizeToMaintainLiabilities) { + flag.setUint32(TrustLineFlags.AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG.getValue()); + } else { + flag.setUint32(0); + } + op.setAuthorize(flag); org.stellar.sdk.xdr.Operation.OperationBody body = new org.stellar.sdk.xdr.Operation.OperationBody(); body.setDiscriminant(OperationType.ALLOW_TRUST); @@ -79,11 +89,12 @@ public static class Builder { private final String trustor; private final String assetCode; private final boolean authorize; + private boolean authorizeToMaintainLiabilities; private String mSourceAccount; Builder(AllowTrustOp op) { - trustor = StrKey.encodeStellarAccountId(op.getTrustor().getAccountID().getEd25519().getUint256()); + trustor = StrKey.encodeStellarAccountId(op.getTrustor()); switch (op.getAsset().getDiscriminant()) { case ASSET_TYPE_CREDIT_ALPHANUM4: assetCode = new String(op.getAsset().getAssetCode4().getAssetCode4()).trim(); @@ -94,7 +105,18 @@ public static class Builder { default: throw new RuntimeException("Unknown asset code"); } - authorize = op.getAuthorize(); + + int flag = op.getAuthorize().getUint32().intValue(); + if (flag == TrustLineFlags.AUTHORIZED_FLAG.getValue()) { + authorize = true; + authorizeToMaintainLiabilities = false; + } else if (flag == TrustLineFlags.AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG.getValue()) { + authorize = false; + authorizeToMaintainLiabilities = true; + } else { + authorize = false; + authorizeToMaintainLiabilities = false; + } } /** @@ -123,7 +145,9 @@ public Builder setSourceAccount(String sourceAccount) { * Builds an operation */ public AllowTrustOperation build() { - AllowTrustOperation operation = new AllowTrustOperation(trustor, assetCode, authorize); + AllowTrustOperation operation = new AllowTrustOperation( + trustor, assetCode, authorize, authorizeToMaintainLiabilities + ); if (mSourceAccount != null) { operation.setSourceAccount(mSourceAccount); } @@ -133,7 +157,13 @@ public AllowTrustOperation build() { @Override public int hashCode() { - return Objects.hashCode(this.getSourceAccount(), this.assetCode, this.authorize, this.trustor); + return Objects.hashCode( + this.getSourceAccount(), + this.assetCode, + this.authorize, + this.authorizeToMaintainLiabilities, + this.trustor + ); } @Override @@ -145,6 +175,7 @@ public boolean equals(Object object) { AllowTrustOperation other = (AllowTrustOperation) object; return Objects.equal(this.assetCode, other.assetCode) && Objects.equal(this.authorize, other.authorize) && + Objects.equal(this.authorizeToMaintainLiabilities, other.authorizeToMaintainLiabilities) && Objects.equal(this.trustor, other.trustor) && Objects.equal(this.getSourceAccount(), other.getSourceAccount()); } diff --git a/src/main/java/org/stellar/sdk/Asset.java b/src/main/java/org/stellar/sdk/Asset.java index 24629645d..1fe37a741 100644 --- a/src/main/java/org/stellar/sdk/Asset.java +++ b/src/main/java/org/stellar/sdk/Asset.java @@ -41,15 +41,11 @@ public static Asset fromXdr(org.stellar.sdk.xdr.Asset xdr) { return new AssetTypeNative(); case ASSET_TYPE_CREDIT_ALPHANUM4: String assetCode4 = Util.paddedByteArrayToString(xdr.getAlphaNum4().getAssetCode().getAssetCode4()); - accountId = StrKey.encodeStellarAccountId( - xdr.getAlphaNum4().getIssuer().getAccountID().getEd25519().getUint256() - ); + accountId = StrKey.encodeStellarAccountId(xdr.getAlphaNum4().getIssuer()); return new AssetTypeCreditAlphaNum4(assetCode4, accountId); case ASSET_TYPE_CREDIT_ALPHANUM12: String assetCode12 = Util.paddedByteArrayToString(xdr.getAlphaNum12().getAssetCode().getAssetCode12()); - accountId = StrKey.encodeStellarAccountId( - xdr.getAlphaNum12().getIssuer().getAccountID().getEd25519().getUint256() - ); + accountId = StrKey.encodeStellarAccountId(xdr.getAlphaNum12().getIssuer()); return new AssetTypeCreditAlphaNum12(assetCode12, accountId); default: throw new IllegalArgumentException("Unknown asset type " + xdr.getDiscriminant()); diff --git a/src/main/java/org/stellar/sdk/CreateAccountOperation.java b/src/main/java/org/stellar/sdk/CreateAccountOperation.java index 938ed2e04..40726c209 100644 --- a/src/main/java/org/stellar/sdk/CreateAccountOperation.java +++ b/src/main/java/org/stellar/sdk/CreateAccountOperation.java @@ -64,7 +64,7 @@ public static class Builder { * @param op {@link CreateAccountOp} */ Builder(CreateAccountOp op) { - destination = StrKey.encodeStellarAccountId(op.getDestination().getAccountID().getEd25519().getUint256()); + destination = StrKey.encodeStellarAccountId(op.getDestination()); startingBalance = Operation.fromXdrAmount(op.getStartingBalance().getInt64().longValue()); } diff --git a/src/main/java/org/stellar/sdk/Operation.java b/src/main/java/org/stellar/sdk/Operation.java index 55cbc3c0b..25261dc0e 100644 --- a/src/main/java/org/stellar/sdk/Operation.java +++ b/src/main/java/org/stellar/sdk/Operation.java @@ -37,7 +37,7 @@ protected static String fromXdrAmount(long value) { public org.stellar.sdk.xdr.Operation toXdr() { org.stellar.sdk.xdr.Operation xdr = new org.stellar.sdk.xdr.Operation(); if (getSourceAccount() != null) { - xdr.setSourceAccount(StrKey.encodeToXDRAccountId(mSourceAccount)); + xdr.setSourceAccount(StrKey.encodeToXDRMuxedAccount(mSourceAccount)); } xdr.setBody(toOperationBody()); return xdr; @@ -115,7 +115,7 @@ public static Operation fromXdr(org.stellar.sdk.xdr.Operation xdr) { } if (xdr.getSourceAccount() != null) { operation.setSourceAccount( - StrKey.encodeStellarAccountId(xdr.getSourceAccount().getAccountID().getEd25519().getUint256()) + StrKey.encodeStellarMuxedAccount(xdr.getSourceAccount()) ); } return operation; diff --git a/src/main/java/org/stellar/sdk/PathPaymentStrictReceiveOperation.java b/src/main/java/org/stellar/sdk/PathPaymentStrictReceiveOperation.java index cf678e63a..13d2fca89 100644 --- a/src/main/java/org/stellar/sdk/PathPaymentStrictReceiveOperation.java +++ b/src/main/java/org/stellar/sdk/PathPaymentStrictReceiveOperation.java @@ -92,7 +92,7 @@ org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { sendMax.setInt64(Operation.toXdrAmount(this.sendMax)); op.setSendMax(sendMax); // destination - op.setDestination(StrKey.encodeToXDRAccountId(this.destination)); + op.setDestination(StrKey.encodeToXDRMuxedAccount(this.destination)); // destAsset op.setDestAsset(destAsset.toXdr()); // destAmount @@ -130,7 +130,7 @@ public static class Builder { Builder(PathPaymentStrictReceiveOp op) { sendAsset = Asset.fromXdr(op.getSendAsset()); sendMax = Operation.fromXdrAmount(op.getSendMax().getInt64().longValue()); - destination = StrKey.encodeStellarAccountId(op.getDestination().getAccountID().getEd25519().getUint256()); + destination = StrKey.encodeStellarMuxedAccount(op.getDestination()); destAsset = Asset.fromXdr(op.getDestAsset()); destAmount = Operation.fromXdrAmount(op.getDestAmount().getInt64().longValue()); path = new Asset[op.getPath().length]; diff --git a/src/main/java/org/stellar/sdk/PathPaymentStrictSendOperation.java b/src/main/java/org/stellar/sdk/PathPaymentStrictSendOperation.java index 38ed62bb0..f0b5dfefa 100644 --- a/src/main/java/org/stellar/sdk/PathPaymentStrictSendOperation.java +++ b/src/main/java/org/stellar/sdk/PathPaymentStrictSendOperation.java @@ -92,7 +92,7 @@ org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { sendAmount.setInt64(Operation.toXdrAmount(this.sendAmount)); op.setSendAmount(sendAmount); // destination - op.setDestination(StrKey.encodeToXDRAccountId(this.destination)); + op.setDestination(StrKey.encodeToXDRMuxedAccount(this.destination)); // destAsset op.setDestAsset(destAsset.toXdr()); // destMin @@ -130,7 +130,7 @@ public static class Builder { Builder(PathPaymentStrictSendOp op) { sendAsset = Asset.fromXdr(op.getSendAsset()); sendAmount = Operation.fromXdrAmount(op.getSendAmount().getInt64().longValue()); - destination = StrKey.encodeStellarAccountId(op.getDestination().getAccountID().getEd25519().getUint256()); + destination = StrKey.encodeStellarMuxedAccount(op.getDestination()); destAsset = Asset.fromXdr(op.getDestAsset()); destMin = Operation.fromXdrAmount(op.getDestMin().getInt64().longValue()); path = new Asset[op.getPath().length]; diff --git a/src/main/java/org/stellar/sdk/PaymentOperation.java b/src/main/java/org/stellar/sdk/PaymentOperation.java index d8256b300..28b65b560 100644 --- a/src/main/java/org/stellar/sdk/PaymentOperation.java +++ b/src/main/java/org/stellar/sdk/PaymentOperation.java @@ -51,7 +51,7 @@ org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { PaymentOp op = new PaymentOp(); // destination - op.setDestination(StrKey.encodeToXDRAccountId(this.destination)); + op.setDestination(StrKey.encodeToXDRMuxedAccount(this.destination)); // asset op.setAsset(asset.toXdr()); // amount @@ -81,7 +81,7 @@ public static class Builder { * @param op {@link PaymentOp} */ Builder(PaymentOp op) { - destination = StrKey.encodeStellarAccountId(op.getDestination().getAccountID().getEd25519().getUint256()); + destination = StrKey.encodeStellarMuxedAccount(op.getDestination()); asset = Asset.fromXdr(op.getAsset()); amount = Operation.fromXdrAmount(op.getAmount().getInt64().longValue()); } diff --git a/src/main/java/org/stellar/sdk/SetOptionsOperation.java b/src/main/java/org/stellar/sdk/SetOptionsOperation.java index ecbda7f81..073c342ca 100644 --- a/src/main/java/org/stellar/sdk/SetOptionsOperation.java +++ b/src/main/java/org/stellar/sdk/SetOptionsOperation.java @@ -190,7 +190,7 @@ public static class Builder { Builder(SetOptionsOp op) { if (op.getInflationDest() != null) { - inflationDestination = StrKey.encodeStellarAccountId(op.getInflationDest().getAccountID().getEd25519().getUint256()); + inflationDestination = StrKey.encodeStellarAccountId(op.getInflationDest()); } if (op.getClearFlags() != null) { clearFlags = op.getClearFlags().getUint32(); diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index be866b4d8..187e9710c 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -2,17 +2,20 @@ import com.google.common.io.BaseEncoding; import com.google.common.base.Optional; -import org.stellar.sdk.xdr.AccountID; -import org.stellar.sdk.xdr.PublicKey; -import org.stellar.sdk.xdr.PublicKeyType; -import org.stellar.sdk.xdr.Uint256; +import com.google.common.primitives.Bytes; +import org.stellar.sdk.xdr.*; import java.io.*; import java.util.Arrays; class StrKey { + + public static final int ACCOUNT_ID_ADDRESS_LENGTH = 56; + public static final int MUXED_ACCOUNT_ADDRESS_LENGTH = 69; + public enum VersionByte { ACCOUNT_ID((byte)(6 << 3)), // G + MUXED_ACCOUNT((byte)(12 << 3)), // M SEED((byte)(18 << 3)), // S PRE_AUTH_TX((byte)(19 << 3)), // T SHA256_HASH((byte)(23 << 3)); // X @@ -41,6 +44,32 @@ public static String encodeStellarAccountId(byte[] data) { return String.valueOf(encoded); } + public static String encodeStellarAccountId(AccountID accountID) { + char[] encoded = encodeCheck(VersionByte.ACCOUNT_ID, accountID.getAccountID().getEd25519().getUint256()); + return String.valueOf(encoded); + } + + + public static String encodeStellarMuxedAccount(MuxedAccount account) { + if (account.getDiscriminant().equals(CryptoKeyType.KEY_TYPE_ED25519)) { + return encodeStellarAccountId(account.getEd25519().getUint256()); + } else if (account.getDiscriminant().equals(CryptoKeyType.KEY_TYPE_MUXED_ED25519)) { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + + try { + account.getMed25519().getId().encode(new XdrDataOutputStream(byteStream)); + byteStream.write(account.getMed25519().getEd25519().getUint256()); + } catch (IOException e) { + throw new IllegalArgumentException("invalid muxed account", e); + } + + char[] encoded = encodeCheck(VersionByte.MUXED_ACCOUNT, byteStream.toByteArray()); + return String.valueOf(encoded); + } + throw new IllegalArgumentException("invalid muxed account type: "+account.getDiscriminant()); + } + + public static AccountID encodeToXDRAccountId(String data) { AccountID accountID = new AccountID(); PublicKey publicKey = new PublicKey(); @@ -52,6 +81,37 @@ public static AccountID encodeToXDRAccountId(String data) { return accountID; } + public static MuxedAccount encodeToXDRMuxedAccount(String data) { + if (data.length() == ACCOUNT_ID_ADDRESS_LENGTH) { + MuxedAccount accountID = new MuxedAccount(); + accountID.setDiscriminant(CryptoKeyType.KEY_TYPE_ED25519); + Uint256 uint256 = new Uint256(); + uint256.setUint256(decodeStellarAccountId(data)); + accountID.setEd25519(uint256); + return accountID; + } else if (data.length() == MUXED_ACCOUNT_ADDRESS_LENGTH) { + byte[] decoded = decodeStellarMuxedAccount(data); + + MuxedAccount muxedAccount = new MuxedAccount(); + muxedAccount.setDiscriminant(CryptoKeyType.KEY_TYPE_MUXED_ED25519); + MuxedAccount.MuxedAccountMed25519 m = new MuxedAccount.MuxedAccountMed25519(); + try { + m.setId(Uint64.decode( + new XdrDataInputStream(new ByteArrayInputStream(decoded, 0, 8)) + )); + m.setEd25519(Uint256.decode( + new XdrDataInputStream(new ByteArrayInputStream(decoded, 8, decoded.length - 8)) + )); + } catch (IOException e) { + throw new IllegalArgumentException("invalid address: "+data, e); + } + muxedAccount.setMed25519(m); + return muxedAccount; + } + throw new IllegalArgumentException("invalid address length: "+data); + } + + public static VersionByte decodeVersionByte(String data) { byte[] decoded = StrKey.base32Encoding.decode(java.nio.CharBuffer.wrap(data.toCharArray())); byte decodedVersionByte = decoded[0]; @@ -66,6 +126,11 @@ public static byte[] decodeStellarAccountId(String data) { return decodeCheck(VersionByte.ACCOUNT_ID, data.toCharArray()); } + public static byte[] decodeStellarMuxedAccount(String data) { + return decodeCheck(VersionByte.MUXED_ACCOUNT, data.toCharArray()); + } + + public static char[] encodeStellarSecretSeed(byte[] data) { return encodeCheck(VersionByte.SEED, data); } diff --git a/src/main/java/org/stellar/sdk/Transaction.java b/src/main/java/org/stellar/sdk/Transaction.java index c653879ff..6b6540b1f 100644 --- a/src/main/java/org/stellar/sdk/Transaction.java +++ b/src/main/java/org/stellar/sdk/Transaction.java @@ -88,6 +88,27 @@ public byte[] hash() { return Util.hash(this.signatureBase()); } + private org.stellar.sdk.xdr.Transaction convertV0Tx(TransactionV0 v0Tx) { + org.stellar.sdk.xdr.Transaction v1Tx = new org.stellar.sdk.xdr.Transaction(); + + v1Tx.setMemo(v0Tx.getMemo()); + v1Tx.setFee(v0Tx.getFee()); + v1Tx.setOperations(v0Tx.getOperations()); + v1Tx.setSeqNum(v0Tx.getSeqNum()); + v1Tx.setTimeBounds(v0Tx.getTimeBounds()); + + org.stellar.sdk.xdr.Transaction.TransactionExt ext = new org.stellar.sdk.xdr.Transaction.TransactionExt(); + ext.setDiscriminant(0); + v1Tx.setExt(ext); + + MuxedAccount sourceAccount = new MuxedAccount(); + sourceAccount.setDiscriminant(CryptoKeyType.KEY_TYPE_ED25519); + sourceAccount.setEd25519(v0Tx.getSourceAccountEd25519()); + v1Tx.setSourceAccount(sourceAccount); + + return v1Tx; + } + /** * Returns signature base. */ @@ -101,7 +122,7 @@ public byte[] signatureBase() { // Transaction XDR bytes ByteArrayOutputStream txOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrOutputStream = new XdrDataOutputStream(txOutputStream); - org.stellar.sdk.xdr.Transaction.encode(xdrOutputStream, this.toXdr()); + convertV0Tx(this.toXdr()).encode(xdrOutputStream); outputStream.write(txOutputStream.toByteArray()); return outputStream.toByteArray(); @@ -154,14 +175,14 @@ public Operation[] getOperations() { /** * Generates Transaction XDR object. */ - public org.stellar.sdk.xdr.Transaction toXdr() { + public TransactionV0 toXdr() { // fee - org.stellar.sdk.xdr.Uint32 fee = new org.stellar.sdk.xdr.Uint32(); + Uint32 fee = new Uint32(); fee.setUint32(mFee); // sequenceNumber - org.stellar.sdk.xdr.Int64 sequenceNumberUint = new org.stellar.sdk.xdr.Int64(); + Int64 sequenceNumberUint = new Int64(); sequenceNumberUint.setInt64(mSequenceNumber); - org.stellar.sdk.xdr.SequenceNumber sequenceNumber = new org.stellar.sdk.xdr.SequenceNumber(); + SequenceNumber sequenceNumber = new SequenceNumber(); sequenceNumber.setSequenceNumber(sequenceNumberUint); // operations org.stellar.sdk.xdr.Operation[] operations = new org.stellar.sdk.xdr.Operation[mOperations.length]; @@ -169,13 +190,13 @@ public org.stellar.sdk.xdr.Transaction toXdr() { operations[i] = mOperations[i].toXdr(); } // ext - org.stellar.sdk.xdr.Transaction.TransactionExt ext = new org.stellar.sdk.xdr.Transaction.TransactionExt(); + TransactionV0.TransactionV0Ext ext = new TransactionV0.TransactionV0Ext(); ext.setDiscriminant(0); - org.stellar.sdk.xdr.Transaction transaction = new org.stellar.sdk.xdr.Transaction(); + TransactionV0 transaction = new TransactionV0(); transaction.setFee(fee); transaction.setSeqNum(sequenceNumber); - transaction.setSourceAccount(StrKey.encodeToXDRAccountId(this.mSourceAccount)); + transaction.setSourceAccountEd25519(StrKey.encodeToXDRAccountId(this.mSourceAccount).getAccountID().getEd25519()); transaction.setOperations(operations); transaction.setMemo(mMemo.toXdr()); transaction.setTimeBounds(mTimeBounds == null ? null : mTimeBounds.toXdr()); @@ -197,31 +218,53 @@ public static Transaction fromEnvelopeXdr(String envelope, Network network) thro return fromEnvelopeXdr(transactionEnvelope, network); } - /** - * Creates a Transaction instance from previously build TransactionEnvelope - * @param envelope - * @return - */ - public static Transaction fromEnvelopeXdr(TransactionEnvelope envelope, Network network) { - org.stellar.sdk.xdr.Transaction tx = envelope.getTx(); - int mFee = tx.getFee().getUint32(); - Long mSequenceNumber = tx.getSeqNum().getSequenceNumber().getInt64(); - Memo mMemo = Memo.fromXdr(tx.getMemo()); - TimeBounds mTimeBounds = TimeBounds.fromXdr(tx.getTimeBounds()); - - Operation[] mOperations = new Operation[tx.getOperations().length]; - for (int i = 0; i < tx.getOperations().length; i++) { - mOperations[i] = Operation.fromXdr(tx.getOperations()[i]); + public static Transaction fromV0EnvelopeXdr(TransactionV0Envelope envelope, Network network) { + int mFee = envelope.getTx().getFee().getUint32(); + Long mSequenceNumber = envelope.getTx().getSeqNum().getSequenceNumber().getInt64(); + Memo mMemo = Memo.fromXdr(envelope.getTx().getMemo()); + TimeBounds mTimeBounds = TimeBounds.fromXdr(envelope.getTx().getTimeBounds()); + + Operation[] mOperations = new Operation[envelope.getTx().getOperations().length]; + for (int i = 0; i < envelope.getTx().getOperations().length; i++) { + mOperations[i] = Operation.fromXdr(envelope.getTx().getOperations()[i]); + } + + Transaction transaction = new Transaction( + StrKey.encodeStellarAccountId(envelope.getTx().getSourceAccountEd25519().getUint256()), + mFee, + mSequenceNumber, + mOperations, + mMemo, + mTimeBounds, + network + ); + + for (DecoratedSignature signature : envelope.getSignatures()) { + transaction.mSignatures.add(signature); + } + + return transaction; + } + + public static Transaction fromV1EnvelopeXdr(TransactionV1Envelope envelope, Network network) { + int mFee = envelope.getTx().getFee().getUint32(); + Long mSequenceNumber = envelope.getTx().getSeqNum().getSequenceNumber().getInt64(); + Memo mMemo = Memo.fromXdr(envelope.getTx().getMemo()); + TimeBounds mTimeBounds = TimeBounds.fromXdr(envelope.getTx().getTimeBounds()); + + Operation[] mOperations = new Operation[envelope.getTx().getOperations().length]; + for (int i = 0; i < envelope.getTx().getOperations().length; i++) { + mOperations[i] = Operation.fromXdr(envelope.getTx().getOperations()[i]); } Transaction transaction = new Transaction( - StrKey.encodeStellarAccountId(tx.getSourceAccount().getAccountID().getEd25519().getUint256()), - mFee, - mSequenceNumber, - mOperations, - mMemo, - mTimeBounds, - network + StrKey.encodeStellarMuxedAccount(envelope.getTx().getSourceAccount()), + mFee, + mSequenceNumber, + mOperations, + mMemo, + mTimeBounds, + network ); for (DecoratedSignature signature : envelope.getSignatures()) { @@ -231,17 +274,35 @@ public static Transaction fromEnvelopeXdr(TransactionEnvelope envelope, Network return transaction; } + /** + * Creates a Transaction instance from previously build TransactionEnvelope + * @param envelope + * @return + */ + public static Transaction fromEnvelopeXdr(TransactionEnvelope envelope, Network network) { + switch (envelope.getDiscriminant()) { + case ENVELOPE_TYPE_TX: + return fromV1EnvelopeXdr(envelope.getV1(), network); + case ENVELOPE_TYPE_TX_V0: + return fromV0EnvelopeXdr(envelope.getV0(), network); + default: + throw new IllegalArgumentException("transaction type is not supported: "+envelope.getDiscriminant()); + } + } + /** * Generates TransactionEnvelope XDR object. */ - public org.stellar.sdk.xdr.TransactionEnvelope toEnvelopeXdr() { - org.stellar.sdk.xdr.TransactionEnvelope xdr = new org.stellar.sdk.xdr.TransactionEnvelope(); - org.stellar.sdk.xdr.Transaction transaction = this.toXdr(); - xdr.setTx(transaction); + public TransactionEnvelope toEnvelopeXdr() { + TransactionEnvelope xdr = new TransactionEnvelope(); + TransactionV0Envelope v0Envelope = new TransactionV0Envelope(); + xdr.setDiscriminant(EnvelopeType.ENVELOPE_TYPE_TX_V0); + v0Envelope.setTx(this.toXdr()); DecoratedSignature[] signatures = new DecoratedSignature[mSignatures.size()]; signatures = mSignatures.toArray(signatures); - xdr.setSignatures(signatures); + v0Envelope.setSignatures(signatures); + xdr.setV0(v0Envelope); return xdr; } @@ -250,10 +311,10 @@ public org.stellar.sdk.xdr.TransactionEnvelope toEnvelopeXdr() { */ public String toEnvelopeXdrBase64() { try { - org.stellar.sdk.xdr.TransactionEnvelope envelope = this.toEnvelopeXdr(); + TransactionEnvelope envelope = this.toEnvelopeXdr(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrOutputStream = new XdrDataOutputStream(outputStream); - org.stellar.sdk.xdr.TransactionEnvelope.encode(xdrOutputStream, envelope); + TransactionEnvelope.encode(xdrOutputStream, envelope); BaseEncoding base64Encoding = BaseEncoding.base64(); return base64Encoding.encode(outputStream.toByteArray()); diff --git a/src/main/java/org/stellar/sdk/responses/TransactionDeserializer.java b/src/main/java/org/stellar/sdk/responses/TransactionDeserializer.java index 9bf14bf9d..771d0f762 100644 --- a/src/main/java/org/stellar/sdk/responses/TransactionDeserializer.java +++ b/src/main/java/org/stellar/sdk/responses/TransactionDeserializer.java @@ -12,6 +12,23 @@ import java.lang.reflect.Type; public class TransactionDeserializer implements JsonDeserializer { + + private Memo extractTextMemo(TransactionEnvelope transactionEnvelope) { + switch (transactionEnvelope.getDiscriminant()) { + case ENVELOPE_TYPE_TX: + return Memo.text(transactionEnvelope.getV1().getTx().getMemo().getText().getBytes()); + case ENVELOPE_TYPE_TX_V0: + return Memo.text(transactionEnvelope.getV0().getTx().getMemo().getText().getBytes()); + case ENVELOPE_TYPE_TX_FEE_BUMP: + return Memo.text( + transactionEnvelope.getFeeBump().getTx().getInnerTx() + .getV1().getTx().getMemo().getText().getBytes() + ); + default: + throw new IllegalArgumentException("invalid transaction type: "+transactionEnvelope.getDiscriminant()); + } + } + @Override public TransactionResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { // Create new Gson object with adapters needed in Transaction @@ -50,7 +67,7 @@ public TransactionResponse deserialize(JsonElement json, Type typeOfT, JsonDeser // so we must throw it as a runtime exception throw new RuntimeException(e); } - memo = Memo.text(transactionEnvelope.getTx().getMemo().getText().getBytes()); + memo = extractTextMemo(transactionEnvelope); } } else { String memoValue = json.getAsJsonObject().get("memo").getAsString(); diff --git a/src/test/java/org/stellar/sdk/OperationTest.java b/src/test/java/org/stellar/sdk/OperationTest.java index 5a0800d9d..be1a5249c 100644 --- a/src/test/java/org/stellar/sdk/OperationTest.java +++ b/src/test/java/org/stellar/sdk/OperationTest.java @@ -551,9 +551,9 @@ public void testManageSellOfferOperation_BadArithmeticRegression() throws IOExce byte[] bytes = base64Encoding.decode(transactionEnvelopeToDecode); org.stellar.sdk.xdr.TransactionEnvelope transactionEnvelope = org.stellar.sdk.xdr.TransactionEnvelope.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - assertEquals(1, transactionEnvelope.getTx().getOperations().length); + assertEquals(1, transactionEnvelope.getV0().getTx().getOperations().length); - ManageSellOfferOperation op = (ManageSellOfferOperation) Operation.fromXdr(transactionEnvelope.getTx().getOperations()[0]); + ManageSellOfferOperation op = (ManageSellOfferOperation) Operation.fromXdr(transactionEnvelope.getV0().getTx().getOperations()[0]); assertEquals("3397.893306099996", op.getPrice()); } @@ -567,9 +567,9 @@ public void testManageBuyOfferOperation_BadArithmeticRegression() throws IOExcep byte[] bytes = base64Encoding.decode(transactionEnvelopeToDecode); org.stellar.sdk.xdr.TransactionEnvelope transactionEnvelope = org.stellar.sdk.xdr.TransactionEnvelope.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - assertEquals(1, transactionEnvelope.getTx().getOperations().length); + assertEquals(1, transactionEnvelope.getV0().getTx().getOperations().length); - ManageBuyOfferOperation op = (ManageBuyOfferOperation) Operation.fromXdr(transactionEnvelope.getTx().getOperations()[0]); + ManageBuyOfferOperation op = (ManageBuyOfferOperation) Operation.fromXdr(transactionEnvelope.getV0().getTx().getOperations()[0]); assertEquals("3397.893306099996", op.getPrice()); } diff --git a/src/test/java/org/stellar/sdk/xdr/TransactionDecodeTest.java b/src/test/java/org/stellar/sdk/xdr/TransactionDecodeTest.java index 442e31879..9f14070df 100644 --- a/src/test/java/org/stellar/sdk/xdr/TransactionDecodeTest.java +++ b/src/test/java/org/stellar/sdk/xdr/TransactionDecodeTest.java @@ -22,7 +22,7 @@ public void testDecodeTxBody() throws IOException { byte[] bytes = base64Encoding.decode(txBody); TransactionEnvelope transactionEnvelope = TransactionEnvelope.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - assertEquals(new Long(2373025265623291L), transactionEnvelope.getTx().getSeqNum().getSequenceNumber().getInt64()); + assertEquals(new Long(2373025265623291L), transactionEnvelope.getV0().getTx().getSeqNum().getSequenceNumber().getInt64()); } @Test @@ -56,8 +56,8 @@ public void testTransactionEnvelopeWithMemo() throws IOException { byte[] bytes = base64Encoding.decode(transactionEnvelopeToDecode); TransactionEnvelope transactionEnvelope = TransactionEnvelope.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - assertEquals(1, transactionEnvelope.getTx().getOperations().length); - assertTrue(Arrays.equals(new byte[]{'G', 'O', 'L', 'D'}, transactionEnvelope.getTx().getOperations()[0].getBody().getPaymentOp().getAsset().getAlphaNum4().getAssetCode().getAssetCode4())); + assertEquals(1, transactionEnvelope.getV0().getTx().getOperations().length); + assertTrue(Arrays.equals(new byte[]{'G', 'O', 'L', 'D'}, transactionEnvelope.getV0().getTx().getOperations()[0].getBody().getPaymentOp().getAsset().getAlphaNum4().getAssetCode().getAssetCode4())); } @Test From 1d54bc733ba93ff82f09044b8219538c8cbac1d9 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Thu, 23 Apr 2020 13:11:34 +0200 Subject: [PATCH 4/7] Add StrKey tests --- src/main/java/org/stellar/sdk/StrKey.java | 35 +- src/test/java/org/stellar/sdk/StrKeyTest.java | 369 ++++++++++++++++-- 2 files changed, 368 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index 187e9710c..9cd6f1c00 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -2,7 +2,6 @@ import com.google.common.io.BaseEncoding; import com.google.common.base.Optional; -import com.google.common.primitives.Bytes; import org.stellar.sdk.xdr.*; import java.io.*; @@ -167,6 +166,10 @@ protected static char[] encodeCheck(VersionByte versionByte, byte[] data) { outputStream.write(checksum); byte unencoded[] = outputStream.toByteArray(); + if (VersionByte.SEED != versionByte) { + return StrKey.base32Encoding.encode(unencoded).toCharArray(); + } + // Why not use base32Encoding.encode here? // We don't want secret seed to be stored as String in memory because of security reasons. It's impossible // to erase it from memory when we want it to be erased (ASAP). @@ -195,6 +198,10 @@ protected static char[] encodeCheck(VersionByte versionByte, byte[] data) { } protected static byte[] decodeCheck(VersionByte versionByte, char[] encoded) { + if (encoded.length == 0) { + throw new IllegalArgumentException("Encoded char array cannot be empty."); + } + byte[] bytes = new byte[encoded.length]; for (int i = 0; i < encoded.length; i++) { if (encoded[i] > 127) { @@ -203,6 +210,19 @@ protected static byte[] decodeCheck(VersionByte versionByte, char[] encoded) { bytes[i] = (byte) encoded[i]; } + int leftoverBits = (bytes.length * 5) % 8; + if (leftoverBits > 0) { + byte lastChar = bytes[bytes.length-1]; + byte decodedLastChar = b32Table[lastChar]; + + + + byte leftoverBitsMask = (byte)(0x0f >> (4 - leftoverBits)); + if ((decodedLastChar & leftoverBitsMask) != 0) { + throw new IllegalArgumentException("Unused bits should be set to 0."); + } + } + byte[] decoded = StrKey.base32Encoding.decode(java.nio.CharBuffer.wrap(encoded)); byte decodedVersionByte = decoded[0]; byte[] payload = Arrays.copyOfRange(decoded, 0, decoded.length-2); @@ -254,4 +274,17 @@ protected static byte[] calculateChecksum(byte[] bytes) { (byte)crc, (byte)(crc >>> 8)}; } + + private static final byte[] b32Table = decodingTable(); + private static byte[] decodingTable() { + byte[] table = new byte[256]; + for (int i=0; i <256; i++) { + table[i] = (byte)0xff; + } + String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + for(int i=0; i < alphabet.length(); i++) { + table[(int)alphabet.charAt(i)] = (byte)i; + } + return table; + } } diff --git a/src/test/java/org/stellar/sdk/StrKeyTest.java b/src/test/java/org/stellar/sdk/StrKeyTest.java index 3937a4028..f4a4e200c 100644 --- a/src/test/java/org/stellar/sdk/StrKeyTest.java +++ b/src/test/java/org/stellar/sdk/StrKeyTest.java @@ -1,56 +1,355 @@ package org.stellar.sdk; +import com.google.common.primitives.UnsignedLongs; import org.junit.Test; +import org.stellar.sdk.xdr.AccountID; +import org.stellar.sdk.xdr.CryptoKeyType; +import org.stellar.sdk.xdr.MuxedAccount; import java.io.IOException; import static org.junit.Assert.*; public class StrKeyTest { - @Test - public void testDecodeEncode() throws IOException, FormatException { - String seed = "SDJHRQF4GCMIIKAAAQ6IHY42X73FQFLHUULAPSKKD4DFDM7UXWWCRHBE"; - byte[] secret = StrKey.decodeCheck(StrKey.VersionByte.SEED, seed.toCharArray()); - char[] encoded = StrKey.encodeCheck(StrKey.VersionByte.SEED, secret); - assertEquals(seed, String.valueOf(encoded)); + @Test + public void testDecodeEncode() throws IOException, FormatException { + String seed = "SDJHRQF4GCMIIKAAAQ6IHY42X73FQFLHUULAPSKKD4DFDM7UXWWCRHBE"; + byte[] secret = StrKey.decodeCheck(StrKey.VersionByte.SEED, seed.toCharArray()); + char[] encoded = StrKey.encodeCheck(StrKey.VersionByte.SEED, secret); + assertEquals(seed, String.valueOf(encoded)); + } + + @Test() + public void testDecodeInvalidVersionByte() { + String address = "GCZHXL5HXQX5ABDM26LHYRCQZ5OJFHLOPLZX47WEBP3V2PF5AVFK2A5D"; + try { + StrKey.decodeCheck(StrKey.VersionByte.SEED, address.toCharArray()); + fail(); + } catch (FormatException e) { + } + } + + @Test() + public void testDecodeInvalidSeed() { + String seed = "SAA6NXOBOXP3RXGAXBW6PGFI5BPK4ODVAWITS4VDOMN5C2M4B66ZML"; + try { + StrKey.decodeCheck(StrKey.VersionByte.SEED, seed.toCharArray()); + fail(); + } catch (Exception e) { + } + } + + @Test() + public void testDecodedVersionByte() { + assertEquals(StrKey.decodeVersionByte("MBU2RRGLXH3E5CQHTD3ODLDF2BWDCYUSSBLLZ5GNW7JXHDIYKXZWGTOG"), StrKey.VersionByte.MUXED_ACCOUNT); + assertEquals(StrKey.decodeVersionByte("GDW6AUTBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6VXRB5NR"), StrKey.VersionByte.ACCOUNT_ID); + assertEquals(StrKey.decodeVersionByte("SDJHRQF4GCMIIKAAAQ6IHY42X73FQFLHUULAPSKKD4DFDM7UXWWCRHBE"), StrKey.VersionByte.SEED); + assertEquals(StrKey.decodeVersionByte("TAQCSRX2RIDJNHFIFHWD63X7D7D6TRT5Y2S6E3TEMXTG5W3OECHZ2OG4"), StrKey.VersionByte.PRE_AUTH_TX); + assertEquals(StrKey.decodeVersionByte("XDRPF6NZRR7EEVO7ESIWUDXHAOMM2QSKIQQBJK6I2FB7YKDZES5UCLWD"), StrKey.VersionByte.SHA256_HASH); + } + + @Test() + public void testDecodedVersionByteThrows() { + try { + StrKey.decodeVersionByte("INVALIDBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6INVALID"); + fail(); + } catch (FormatException e) { + assertEquals("Version byte is invalid", e.getMessage()); + } + } + + private byte[] rawBytes(int... values) { + byte[] data = new byte[values.length]; + for (int i = 0; i < values.length; i++) { + data[i] = (byte) values[i]; + } + return data; + } + + @Test + public void testRoundTripAccountIdFromBytes() { + byte[] data = rawBytes( + 0x36, 0x3e, 0xaa, 0x38, 0x67, 0x84, 0x1f, 0xba, + 0xd0, 0xf4, 0xed, 0x88, 0xc7, 0x79, 0xe4, 0xfe, + 0x66, 0xe5, 0x6a, 0x24, 0x70, 0xdc, 0x98, 0xc0, + 0xec, 0x9c, 0x07, 0x3d, 0x05, 0xc7, 0xb1, 0x03 + ); + String accountId = "GA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQHES5"; + assertEquals( + accountId, + String.valueOf(StrKey.encodeCheck(StrKey.VersionByte.ACCOUNT_ID, data)) + ); + assertArrayEquals(data, StrKey.decodeCheck(StrKey.VersionByte.ACCOUNT_ID, accountId.toCharArray())); + } + + @Test + public void testRoundTripSeedFromBytes() { + byte[] data = rawBytes( + 0x69, 0xa8, 0xc4, 0xcb, 0xb9, 0xf6, 0x4e, 0x8a, + 0x07, 0x98, 0xf6, 0xe1, 0xac, 0x65, 0xd0, 0x6c, + 0x31, 0x62, 0x92, 0x90, 0x56, 0xbc, 0xf4, 0xcd, + 0xb7, 0xd3, 0x73, 0x8d, 0x18, 0x55, 0xf3, 0x63 + ); + String seed = "SBU2RRGLXH3E5CQHTD3ODLDF2BWDCYUSSBLLZ5GNW7JXHDIYKXZWHOKR"; + assertEquals( + seed, + String.valueOf(StrKey.encodeCheck(StrKey.VersionByte.SEED, data)) + ); + assertArrayEquals(data, StrKey.decodeCheck(StrKey.VersionByte.SEED, seed.toCharArray())); + } + + @Test + public void testRoundTripHashTxFromBytes() { + byte[] data = rawBytes( + 0x69, 0xa8, 0xc4, 0xcb, 0xb9, 0xf6, 0x4e, 0x8a, + 0x07, 0x98, 0xf6, 0xe1, 0xac, 0x65, 0xd0, 0x6c, + 0x31, 0x62, 0x92, 0x90, 0x56, 0xbc, 0xf4, 0xcd, + 0xb7, 0xd3, 0x73, 0x8d, 0x18, 0x55, 0xf3, 0x63 + ); + String hashTx = "TBU2RRGLXH3E5CQHTD3ODLDF2BWDCYUSSBLLZ5GNW7JXHDIYKXZWHXL7"; + assertEquals( + hashTx, + String.valueOf(StrKey.encodeCheck(StrKey.VersionByte.PRE_AUTH_TX, data)) + ); + assertArrayEquals(data, StrKey.decodeCheck(StrKey.VersionByte.PRE_AUTH_TX, hashTx.toCharArray())); + } + + @Test + public void testRoundTripHashXFromBytes() { + byte[] data = rawBytes( + 0x69, 0xa8, 0xc4, 0xcb, 0xb9, 0xf6, 0x4e, 0x8a, + 0x07, 0x98, 0xf6, 0xe1, 0xac, 0x65, 0xd0, 0x6c, + 0x31, 0x62, 0x92, 0x90, 0x56, 0xbc, 0xf4, 0xcd, + 0xb7, 0xd3, 0x73, 0x8d, 0x18, 0x55, 0xf3, 0x63 + ); + String hashX = "XBU2RRGLXH3E5CQHTD3ODLDF2BWDCYUSSBLLZ5GNW7JXHDIYKXZWGTOG"; + assertEquals( + hashX, + String.valueOf(StrKey.encodeCheck(StrKey.VersionByte.SHA256_HASH, data)) + ); + assertArrayEquals(data, StrKey.decodeCheck(StrKey.VersionByte.SHA256_HASH, hashX.toCharArray())); + } + + @Test + public void testRoundTripMuxedFromBytes() { + byte[] data = rawBytes( + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x0c, 0x34, 0xbf, 0x93, 0xad, 0x0d, 0x99, + 0x71, 0xd0, 0x4c, 0xcc, 0x90, 0xf7, 0x05, 0x51, + 0x1c, 0x83, 0x8a, 0xad, 0x97, 0x34, 0xa4, 0xa2, + 0xfb, 0x0d, 0x7a, 0x03, 0xfc, 0x7f, 0xe8, 0x9a + ); + String muxed = "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOG"; + assertEquals( + muxed, + String.valueOf(StrKey.encodeCheck(StrKey.VersionByte.MUXED_ACCOUNT, data)) + ); + assertArrayEquals(data, StrKey.decodeCheck(StrKey.VersionByte.MUXED_ACCOUNT, muxed.toCharArray())); + } + + + @Test + public void testDecodeEmpty() { + try { + StrKey.decodeCheck(StrKey.VersionByte.ACCOUNT_ID, "".toCharArray()); + fail(); + } catch (Exception e) { + assertEquals("Encoded char array cannot be empty.", e.getMessage()); + } + } + + @Test + public void testCorruptedChecksum() { + try { + StrKey.decodeCheck(StrKey.VersionByte.ACCOUNT_ID, "GA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQHE55".toCharArray()); + fail(); + } catch (Exception e) { + assertEquals("Checksum invalid", e.getMessage()); + } + } + + @Test + public void testCorruptedPayload() { + try { + StrKey.decodeCheck(StrKey.VersionByte.ACCOUNT_ID, "GA3D5KRYM6CB7OWOOOORR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQHES5".toCharArray()); + fail(); + } catch (Exception e) { + assertEquals("Unused bits should be set to 0.", e.getMessage()); + } + } + + + @Test + public void testMuxedDecodeErrors() { + // non-canonical representation due to extra character + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOGA".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Invalid input length")); + + } + + // non-canonical representation due to leftover bits set to 1 (some of the test strkeys are too short for a muxed account + + // 1 unused bit (length 69) + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOH".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + + } + + + // 4 unused bits (length 68) + + // 'B' is equivalent to 0b00001 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNB".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + + } + + // 'C' is equivalent to 0b00010 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNC".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + + } + + // 'E' is equivalent to 0b00100 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNE".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + } - @Test() - public void testDecodeInvalidVersionByte() { - String address = "GCZHXL5HXQX5ABDM26LHYRCQZ5OJFHLOPLZX47WEBP3V2PF5AVFK2A5D"; - try { - StrKey.decodeCheck(StrKey.VersionByte.SEED, address.toCharArray()); - fail(); - } catch (FormatException e) {} + // 'I' is equivalent to 0b01000 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNI".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + } - @Test() - public void testDecodeInvalidSeed() { - String seed = "SAA6NXOBOXP3RXGAXBW6PGFI5BPK4ODVAWITS4VDOMN5C2M4B66ZML"; - try { - StrKey.decodeCheck(StrKey.VersionByte.SEED, seed.toCharArray()); - fail(); - } catch (Exception e) {} + // '7' is equivalent to 0b11111 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKN7".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + } - @Test() - public void testDecodedVersionByte() { - assertEquals(StrKey.decodeVersionByte("GDW6AUTBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6VXRB5NR"), StrKey.VersionByte.ACCOUNT_ID); - assertEquals(StrKey.decodeVersionByte("SDJHRQF4GCMIIKAAAQ6IHY42X73FQFLHUULAPSKKD4DFDM7UXWWCRHBE"), StrKey.VersionByte.SEED); - assertEquals(StrKey.decodeVersionByte("TAQCSRX2RIDJNHFIFHWD63X7D7D6TRT5Y2S6E3TEMXTG5W3OECHZ2OG4"), StrKey.VersionByte.PRE_AUTH_TX); - assertEquals(StrKey.decodeVersionByte("XDRPF6NZRR7EEVO7ESIWUDXHAOMM2QSKIQQBJK6I2FB7YKDZES5UCLWD"), StrKey.VersionByte.SHA256_HASH); + // '6' is equivalent to 0b11110 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKN6".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + } - @Test() - public void testDecodedVersionByteThrows() { - try { - StrKey.decodeVersionByte("INVALIDBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6INVALID"); - fail(); - } catch (FormatException e) { - assertEquals("Version byte is invalid", e.getMessage()); - } + // '4' is equivalent to 0b11100 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKN4".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + + } + + // 'Y' is equivalent to 0b11000 + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNY".toCharArray() + ); + fail(); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Unused bits should be set to 0.")); + } - // TODO more tests + // 'Q' is equivalent to 0b10000, so there should be no unused bits error + // However, there will be a checksum error + try { + StrKey.decodeCheck( + StrKey.VersionByte.MUXED_ACCOUNT, + "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNQ".toCharArray() + ); + } catch (Exception e) { + assertEquals("Checksum invalid", e.getMessage()); + } + } + + @Test + public void testEncodeToXdrRoundTrip() { + String address = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; + byte[] ed25519 = rawBytes( + 63, 12, 52, 191, 147, 173, 13, 153, 113, 208, + 76, 204, 144, 247, 5, 81, 28, 131, 138, 173, 151, 52, + 164, 162, 251, 13, 122, 3, 252, 127, 232, 154 + ); + AccountID account = StrKey.encodeToXDRAccountId(address); + assertArrayEquals(ed25519, account.getAccountID().getEd25519().getUint256()); + assertEquals(address, StrKey.encodeStellarAccountId(account)); + + MuxedAccount muxedAccount = StrKey.encodeToXDRMuxedAccount(address); + assertEquals(CryptoKeyType.KEY_TYPE_ED25519, muxedAccount.getDiscriminant()); + assertArrayEquals(ed25519, muxedAccount.getEd25519().getUint256()); + assertEquals(address, StrKey.encodeStellarMuxedAccount(muxedAccount)); + + String muxedAddress = "MCAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITKNOG"; + muxedAccount = StrKey.encodeToXDRMuxedAccount(muxedAddress); + assertEquals(CryptoKeyType.KEY_TYPE_MUXED_ED25519, muxedAccount.getDiscriminant()); + assertArrayEquals(ed25519, muxedAccount.getMed25519().getEd25519().getUint256()); + long memoId = UnsignedLongs.parseUnsignedLong("9223372036854775808"); + assertEquals(memoId, muxedAccount.getMed25519().getId().getUint64().longValue()); + assertEquals(muxedAddress, StrKey.encodeStellarMuxedAccount(muxedAccount)); + + muxedAddress = "MAAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITLVL6"; + muxedAccount = StrKey.encodeToXDRMuxedAccount(muxedAddress); + assertEquals(CryptoKeyType.KEY_TYPE_MUXED_ED25519, muxedAccount.getDiscriminant()); + assertArrayEquals(ed25519, muxedAccount.getMed25519().getEd25519().getUint256()); + assertEquals(0, muxedAccount.getMed25519().getId().getUint64().longValue()); + assertEquals(muxedAddress, StrKey.encodeStellarMuxedAccount(muxedAccount)); + } + } From 9409250f691239029ce9cd3103c00c5dbb6d5427 Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Mon, 27 Apr 2020 11:35:04 +0200 Subject: [PATCH 5/7] Code review fixes --- .../org/stellar/sdk/AllowTrustOperation.java | 6 +- src/main/java/org/stellar/sdk/StrKey.java | 56 +++++++++---------- .../java/org/stellar/sdk/Transaction.java | 2 +- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/stellar/sdk/AllowTrustOperation.java b/src/main/java/org/stellar/sdk/AllowTrustOperation.java index 2ffab62b3..02a682d8c 100644 --- a/src/main/java/org/stellar/sdk/AllowTrustOperation.java +++ b/src/main/java/org/stellar/sdk/AllowTrustOperation.java @@ -113,9 +113,11 @@ public static class Builder { } else if (flag == TrustLineFlags.AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG.getValue()) { authorize = false; authorizeToMaintainLiabilities = true; + } else if (flag != 0) { + throw new IllegalArgumentException("invalid authorize flag "+flag); } else { - authorize = false; - authorizeToMaintainLiabilities = false; + authorize = false; + authorizeToMaintainLiabilities = false; } } diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index 9cd6f1c00..83eefbdd7 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -56,8 +56,7 @@ public static String encodeStellarMuxedAccount(MuxedAccount account) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); try { - account.getMed25519().getId().encode(new XdrDataOutputStream(byteStream)); - byteStream.write(account.getMed25519().getEd25519().getUint256()); + account.getMed25519().encode(new XdrDataOutputStream(byteStream)); } catch (IOException e) { throw new IllegalArgumentException("invalid muxed account", e); } @@ -73,9 +72,13 @@ public static AccountID encodeToXDRAccountId(String data) { AccountID accountID = new AccountID(); PublicKey publicKey = new PublicKey(); publicKey.setDiscriminant(PublicKeyType.PUBLIC_KEY_TYPE_ED25519); - Uint256 uint256 = new Uint256(); - uint256.setUint256(decodeStellarAccountId(data)); - publicKey.setEd25519(uint256); + try { + publicKey.setEd25519(Uint256.decode( + new XdrDataInputStream(new ByteArrayInputStream(decodeStellarAccountId(data))) + )); + } catch (IOException e) { + throw new IllegalArgumentException("invalid address: "+data, e); + } accountID.setAccountID(publicKey); return accountID; } @@ -84,27 +87,24 @@ public static MuxedAccount encodeToXDRMuxedAccount(String data) { if (data.length() == ACCOUNT_ID_ADDRESS_LENGTH) { MuxedAccount accountID = new MuxedAccount(); accountID.setDiscriminant(CryptoKeyType.KEY_TYPE_ED25519); - Uint256 uint256 = new Uint256(); - uint256.setUint256(decodeStellarAccountId(data)); - accountID.setEd25519(uint256); + try { + accountID.setEd25519(Uint256.decode( + new XdrDataInputStream(new ByteArrayInputStream(decodeStellarAccountId(data))) + )); + } catch (IOException e) { + throw new IllegalArgumentException("invalid address: "+data, e); + } return accountID; } else if (data.length() == MUXED_ACCOUNT_ADDRESS_LENGTH) { - byte[] decoded = decodeStellarMuxedAccount(data); - MuxedAccount muxedAccount = new MuxedAccount(); muxedAccount.setDiscriminant(CryptoKeyType.KEY_TYPE_MUXED_ED25519); - MuxedAccount.MuxedAccountMed25519 m = new MuxedAccount.MuxedAccountMed25519(); try { - m.setId(Uint64.decode( - new XdrDataInputStream(new ByteArrayInputStream(decoded, 0, 8)) - )); - m.setEd25519(Uint256.decode( - new XdrDataInputStream(new ByteArrayInputStream(decoded, 8, decoded.length - 8)) + muxedAccount.setMed25519(MuxedAccount.MuxedAccountMed25519.decode( + new XdrDataInputStream(new ByteArrayInputStream(decodeStellarMuxedAccount(data))) )); } catch (IOException e) { throw new IllegalArgumentException("invalid address: "+data, e); } - muxedAccount.setMed25519(m); return muxedAccount; } throw new IllegalArgumentException("invalid address length: "+data); @@ -178,18 +178,16 @@ protected static char[] encodeCheck(VersionByte versionByte, byte[] data) { charOutputStream.write(unencoded); char[] charsEncoded = charArrayWriter.toCharArray(); - if (VersionByte.SEED == versionByte) { - Arrays.fill(unencoded, (byte) 0); - Arrays.fill(payload, (byte) 0); - Arrays.fill(checksum, (byte) 0); - - // Clean charArrayWriter internal buffer - int bufferSize = charArrayWriter.size(); - char[] zeros = new char[bufferSize]; - Arrays.fill(zeros, '0'); - charArrayWriter.reset(); - charArrayWriter.write(zeros); - } + Arrays.fill(unencoded, (byte) 0); + Arrays.fill(payload, (byte) 0); + Arrays.fill(checksum, (byte) 0); + + // Clean charArrayWriter internal buffer + int bufferSize = charArrayWriter.size(); + char[] zeros = new char[bufferSize]; + Arrays.fill(zeros, '0'); + charArrayWriter.reset(); + charArrayWriter.write(zeros); return charsEncoded; } catch (IOException e) { diff --git a/src/main/java/org/stellar/sdk/Transaction.java b/src/main/java/org/stellar/sdk/Transaction.java index 6b6540b1f..71742939a 100644 --- a/src/main/java/org/stellar/sdk/Transaction.java +++ b/src/main/java/org/stellar/sdk/Transaction.java @@ -175,7 +175,7 @@ public Operation[] getOperations() { /** * Generates Transaction XDR object. */ - public TransactionV0 toXdr() { + private TransactionV0 toXdr() { // fee Uint32 fee = new Uint32(); fee.setUint32(mFee); From 56684eb78ce9216f0e2b8c5edb518665f05d553c Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Mon, 27 Apr 2020 11:35:29 +0200 Subject: [PATCH 6/7] Add Add authorize_to_maintain_liabilities to AllowTrust operation --- .../AllowTrustOperationResponse.java | 10 +++- .../responses/OperationDeserializerTest.java | 47 ++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/stellar/sdk/responses/operations/AllowTrustOperationResponse.java b/src/main/java/org/stellar/sdk/responses/operations/AllowTrustOperationResponse.java index 991283960..9d648ffa5 100644 --- a/src/main/java/org/stellar/sdk/responses/operations/AllowTrustOperationResponse.java +++ b/src/main/java/org/stellar/sdk/responses/operations/AllowTrustOperationResponse.java @@ -24,9 +24,12 @@ public class AllowTrustOperationResponse extends OperationResponse { protected final String assetIssuer; @SerializedName("authorize") protected final boolean authorize; + @SerializedName("authorize_to_maintain_liabilities") + protected final boolean authorizeToMaintainLiabilities; - AllowTrustOperationResponse(boolean authorize, String assetIssuer, String assetCode, String assetType, String trustee, String trustor) { + AllowTrustOperationResponse(boolean authorize, boolean authorizeToMaintainLiabilities, String assetIssuer, String assetCode, String assetType, String trustee, String trustor) { this.authorize = authorize; + this.authorizeToMaintainLiabilities = authorizeToMaintainLiabilities; this.assetIssuer = assetIssuer; this.assetCode = assetCode; this.assetType = assetType; @@ -46,6 +49,11 @@ public boolean isAuthorize() { return authorize; } + public boolean isAuthorizedToMaintainLiabilities() { + return authorizeToMaintainLiabilities; + } + + public Asset getAsset() { if (assetType.equals("native")) { return new AssetTypeNative(); diff --git a/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java b/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java index dd822e80e..b56cbcef6 100644 --- a/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java +++ b/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java @@ -175,7 +175,8 @@ public void testDeserializeAllowTrustOperation() { " \"asset_issuer\": \"GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM\",\n" + " \"trustee\": \"GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM\",\n" + " \"trustor\": \"GDZ55LVXECRTW4G36EZPTHI4XIYS5JUC33TUS22UOETVFVOQ77JXWY4F\",\n" + - " \"authorize\": true\n" + + " \"authorize\": true\n," + + " \"authorize_to_maintain_liabilities\": false\n" + " }"; AllowTrustOperationResponse operation = (AllowTrustOperationResponse) GsonSingleton.getInstance().fromJson(json, OperationResponse.class); @@ -183,6 +184,50 @@ public void testDeserializeAllowTrustOperation() { assertEquals(operation.getTrustee(), "GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM"); assertEquals(operation.getTrustor(), "GDZ55LVXECRTW4G36EZPTHI4XIYS5JUC33TUS22UOETVFVOQ77JXWY4F"); assertEquals(operation.isAuthorize(), true); + assertEquals(operation.isAuthorizedToMaintainLiabilities(), false); + assertEquals(operation.getAsset(), Asset.createNonNativeAsset("EUR", "GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM")); + } + + @Test + public void testDeserializeAllowTrustOperationAuthorizeToMaintainLiabilities() { + String json = "{\n" + + " \"_links\": {\n" + + " \"self\": {\n" + + " \"href\": \"//horizon-testnet.stellar.org/operations/3602979345141761\"\n" + + " },\n" + + " \"transaction\": {\n" + + " \"href\": \"//horizon-testnet.stellar.org/transactions/1f265c075e8559ee4c21a32ae53337658e52d7504841adad4144c37143ea01a2\"\n" + + " },\n" + + " \"effects\": {\n" + + " \"href\": \"//horizon-testnet.stellar.org/operations/3602979345141761/effects\"\n" + + " },\n" + + " \"succeeds\": {\n" + + " \"href\": \"//horizon-testnet.stellar.org/effects?order=desc\\u0026cursor=3602979345141761\"\n" + + " },\n" + + " \"precedes\": {\n" + + " \"href\": \"//horizon-testnet.stellar.org/effects?order=asc\\u0026cursor=3602979345141761\"\n" + + " }\n" + + " },\n" + + " \"id\": \"3602979345141761\",\n" + + " \"paging_token\": \"3602979345141761\",\n" + + " \"source_account\": \"GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM\",\n" + + " \"type\": \"allow_trust\",\n" + + " \"type_i\": 7,\n" + + " \"asset_type\": \"credit_alphanum4\",\n" + + " \"asset_code\": \"EUR\",\n" + + " \"asset_issuer\": \"GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM\",\n" + + " \"trustee\": \"GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM\",\n" + + " \"trustor\": \"GDZ55LVXECRTW4G36EZPTHI4XIYS5JUC33TUS22UOETVFVOQ77JXWY4F\",\n" + + " \"authorize\": false\n," + + " \"authorize_to_maintain_liabilities\": true\n" + + " }"; + + AllowTrustOperationResponse operation = (AllowTrustOperationResponse) GsonSingleton.getInstance().fromJson(json, OperationResponse.class); + + assertEquals(operation.getTrustee(), "GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM"); + assertEquals(operation.getTrustor(), "GDZ55LVXECRTW4G36EZPTHI4XIYS5JUC33TUS22UOETVFVOQ77JXWY4F"); + assertEquals(operation.isAuthorize(), false); + assertEquals(operation.isAuthorizedToMaintainLiabilities(), true); assertEquals(operation.getAsset(), Asset.createNonNativeAsset("EUR", "GDIROJW2YHMSFZJJ4R5XWWNUVND5I45YEWS5DSFKXCHMADZ5V374U2LM")); } From 91150661157a7162a37319c7e0ecb6785187d47d Mon Sep 17 00:00:00 2001 From: Tamir Sen Date: Mon, 27 Apr 2020 15:15:13 +0200 Subject: [PATCH 7/7] Strkey fixes --- src/main/java/org/stellar/sdk/StrKey.java | 19 ++++++++++++------- src/test/java/org/stellar/sdk/StrKeyTest.java | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index 83eefbdd7..222622a3e 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -196,19 +196,24 @@ protected static char[] encodeCheck(VersionByte versionByte, byte[] data) { } protected static byte[] decodeCheck(VersionByte versionByte, char[] encoded) { - if (encoded.length == 0) { - throw new IllegalArgumentException("Encoded char array cannot be empty."); - } - byte[] bytes = new byte[encoded.length]; for (int i = 0; i < encoded.length; i++) { - if (encoded[i] > 127) { - throw new IllegalArgumentException("Illegal characters in encoded char array."); - } bytes[i] = (byte) encoded[i]; } + // The minimal binary decoded length is 3 bytes (version byte and 2-byte CRC) which, + // in unpadded base32 (since each character provides 5 bits) corresponds to ceiling(8*3/5) = 5 + if (bytes.length < 5) { + throw new IllegalArgumentException("Encoded char array must have a length of at least 5."); + } + int leftoverBits = (bytes.length * 5) % 8; + // 1. Make sure there is no full unused leftover byte at the end + // (i.e. there shouldn't be 5 or more leftover bits) + if (leftoverBits >= 5) { + throw new IllegalArgumentException("Encoded char array has leftover character."); + } + if (leftoverBits > 0) { byte lastChar = bytes[bytes.length-1]; byte decodedLastChar = b32Table[lastChar]; diff --git a/src/test/java/org/stellar/sdk/StrKeyTest.java b/src/test/java/org/stellar/sdk/StrKeyTest.java index f4a4e200c..cace981be 100644 --- a/src/test/java/org/stellar/sdk/StrKeyTest.java +++ b/src/test/java/org/stellar/sdk/StrKeyTest.java @@ -154,7 +154,7 @@ public void testDecodeEmpty() { StrKey.decodeCheck(StrKey.VersionByte.ACCOUNT_ID, "".toCharArray()); fail(); } catch (Exception e) { - assertEquals("Encoded char array cannot be empty.", e.getMessage()); + assertEquals("Encoded char array must have a length of at least 5.", e.getMessage()); } } @@ -189,7 +189,7 @@ public void testMuxedDecodeErrors() { ); fail(); } catch (Exception e) { - assertTrue(e.getMessage().contains("Invalid input length")); + assertTrue(e.getMessage().contains("Encoded char array has leftover character.")); }