From ddba21b962d5a81089a2da4a7b8db4f1dd7b0e3f Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Wed, 13 Jan 2021 22:29:37 +0800 Subject: [PATCH] Fix several bugs in revoke operations. (#317) * fix: fix a bug that no `discriminant` is set for LedgerKey in the revoke operations. * fix: fix a bug that RevokeClaimableBalanceSponsorshipOperation cannot resolve balanceId properly. * fix: Fix a bug in RevokeOfferSponsorshipOperation where necessary parameter is missing. * test: add test cases for revoke operations. * release: 0.22.1 --- CHANGELOG.md | 3 + build.gradle | 2 +- .../RevokeAccountSponsorshipOperation.java | 1 + ...eClaimableBalanceSponsorshipOperation.java | 27 ++++-- .../sdk/RevokeDataSponsorshipOperation.java | 1 + .../sdk/RevokeOfferSponsorshipOperation.java | 20 ++++- .../RevokeTrustlineSponsorshipOperation.java | 1 + .../java/org/stellar/sdk/OperationTest.java | 86 +++++++++++++++++++ 8 files changed, 130 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7365f25a..cea93552e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ As this project is pre 1.0, breaking changes may happen for minor version bumps. A breaking change will get clearly notified in this log. +## 0.22.1 +- Fix several bugs in revoke operations. ([#317](https://github.com/stellar/java-stellar-sdk/pull/317)) + ## 0.22.0 - The XDR classes have been regenerated using the latest version of xdrgen which provides the following two features: diff --git a/build.gradle b/build.gradle index 50642500c..022008379 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ apply plugin: 'com.github.ben-manes.versions' // gradle dependencyUpdates -Drevi apply plugin: 'project-report' // gradle htmlDependencyReport sourceCompatibility = 1.6 -version = '0.22.0' +version = '0.22.1' group = 'stellar' jar { diff --git a/src/main/java/org/stellar/sdk/RevokeAccountSponsorshipOperation.java b/src/main/java/org/stellar/sdk/RevokeAccountSponsorshipOperation.java index d72d72d01..99dec0a4a 100644 --- a/src/main/java/org/stellar/sdk/RevokeAccountSponsorshipOperation.java +++ b/src/main/java/org/stellar/sdk/RevokeAccountSponsorshipOperation.java @@ -20,6 +20,7 @@ public String getAccountId() { org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { RevokeSponsorshipOp op = new RevokeSponsorshipOp(); LedgerKey key = new LedgerKey(); + key.setDiscriminant(LedgerEntryType.ACCOUNT); LedgerKey.LedgerKeyAccount account = new LedgerKey.LedgerKeyAccount(); account.setAccountID(StrKey.encodeToXDRAccountId(accountId)); key.setAccount(account); diff --git a/src/main/java/org/stellar/sdk/RevokeClaimableBalanceSponsorshipOperation.java b/src/main/java/org/stellar/sdk/RevokeClaimableBalanceSponsorshipOperation.java index e83a140af..08466837d 100644 --- a/src/main/java/org/stellar/sdk/RevokeClaimableBalanceSponsorshipOperation.java +++ b/src/main/java/org/stellar/sdk/RevokeClaimableBalanceSponsorshipOperation.java @@ -4,6 +4,10 @@ import com.google.common.io.BaseEncoding; import org.stellar.sdk.xdr.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + import static com.google.common.base.Preconditions.checkNotNull; public class RevokeClaimableBalanceSponsorshipOperation extends Operation { @@ -21,13 +25,17 @@ public String getBalanceId() { org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { RevokeSponsorshipOp op = new RevokeSponsorshipOp(); LedgerKey key = new LedgerKey(); + key.setDiscriminant(LedgerEntryType.CLAIMABLE_BALANCE); LedgerKey.LedgerKeyClaimableBalance claimableBalance = new LedgerKey.LedgerKeyClaimableBalance(); - ClaimableBalanceID id = new ClaimableBalanceID(); - id.setDiscriminant(ClaimableBalanceIDType.CLAIMABLE_BALANCE_ID_TYPE_V0); - Hash hash = new Hash(); - hash.setHash(BaseEncoding.base16().lowerCase().decode(balanceId.toLowerCase())); - id.setV0(hash); + byte[] balanceIdBytes = BaseEncoding.base16().lowerCase().decode(balanceId.toLowerCase()); + XdrDataInputStream balanceIdXdrDataInputStream = new XdrDataInputStream(new ByteArrayInputStream(balanceIdBytes)); + ClaimableBalanceID id; + try { + id = ClaimableBalanceID.decode(balanceIdXdrDataInputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid balanceId: " + balanceId, e); + } claimableBalance.setBalanceID(id); key.setClaimableBalance(claimableBalance); @@ -51,7 +59,14 @@ public static class Builder { * @param op {@link RevokeSponsorshipOp} */ Builder(RevokeSponsorshipOp op) { - balanceId = BaseEncoding.base16().lowerCase().encode(op.getLedgerKey().getClaimableBalance().getBalanceID().getV0().getHash()); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + op.getLedgerKey().getClaimableBalance().getBalanceID().encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid revokeSponsorshipOp.", e); + } + balanceId = BaseEncoding.base16().lowerCase().encode(byteArrayOutputStream.toByteArray()); } /** diff --git a/src/main/java/org/stellar/sdk/RevokeDataSponsorshipOperation.java b/src/main/java/org/stellar/sdk/RevokeDataSponsorshipOperation.java index 0b7423e04..11ce977ef 100644 --- a/src/main/java/org/stellar/sdk/RevokeDataSponsorshipOperation.java +++ b/src/main/java/org/stellar/sdk/RevokeDataSponsorshipOperation.java @@ -26,6 +26,7 @@ public String getDataName() { org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { RevokeSponsorshipOp op = new RevokeSponsorshipOp(); LedgerKey key = new LedgerKey(); + key.setDiscriminant(LedgerEntryType.DATA); LedgerKey.LedgerKeyData data = new LedgerKey.LedgerKeyData(); data.setAccountID(StrKey.encodeToXDRAccountId(accountId)); String64 dn = new String64(); diff --git a/src/main/java/org/stellar/sdk/RevokeOfferSponsorshipOperation.java b/src/main/java/org/stellar/sdk/RevokeOfferSponsorshipOperation.java index 6a931b2e9..191587bae 100644 --- a/src/main/java/org/stellar/sdk/RevokeOfferSponsorshipOperation.java +++ b/src/main/java/org/stellar/sdk/RevokeOfferSponsorshipOperation.java @@ -6,12 +6,18 @@ import static com.google.common.base.Preconditions.checkNotNull; public class RevokeOfferSponsorshipOperation extends Operation { + private final String seller; private final Long offerId; - private RevokeOfferSponsorshipOperation(Long offerId) { + private RevokeOfferSponsorshipOperation(String seller, Long offerId) { + this.seller = seller; this.offerId = offerId; } + public String getSeller() { + return seller; + } + public Long getOfferId() { return offerId; } @@ -20,10 +26,12 @@ public Long getOfferId() { org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { RevokeSponsorshipOp op = new RevokeSponsorshipOp(); LedgerKey key = new LedgerKey(); + key.setDiscriminant(LedgerEntryType.OFFER); LedgerKey.LedgerKeyOffer offer = new LedgerKey.LedgerKeyOffer(); Int64 id = new Int64(); id.setInt64(offerId); offer.setOfferID(id); + offer.setSellerID(StrKey.encodeToXDRAccountId(seller)); key.setOffer(offer); op.setLedgerKey(key); @@ -37,6 +45,7 @@ org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { } public static class Builder { + private final String seller; private final Long offerId; private String mSourceAccount; @@ -47,13 +56,16 @@ public static class Builder { */ Builder(RevokeSponsorshipOp op) { offerId = op.getLedgerKey().getOffer().getOfferID().getInt64(); + seller = StrKey.encodeStellarAccountId(op.getLedgerKey().getOffer().getSellerID()); } /** * Creates a new RevokeOfferSponsorshipOperation builder. + * @param seller The account ID which created the offer. * @param offerId The id of the offer whose sponsorship will be revoked. */ - public Builder(Long offerId) { + public Builder(String seller, Long offerId) { + this.seller = seller; this.offerId = offerId; } @@ -71,7 +83,7 @@ public RevokeOfferSponsorshipOperation.Builder setSourceAccount(String sourceAcc * Builds an operation */ public RevokeOfferSponsorshipOperation build() { - RevokeOfferSponsorshipOperation operation = new RevokeOfferSponsorshipOperation(offerId); + RevokeOfferSponsorshipOperation operation = new RevokeOfferSponsorshipOperation(seller, offerId); if (mSourceAccount != null) { operation.setSourceAccount(mSourceAccount); } @@ -91,7 +103,7 @@ public boolean equals(Object object) { } RevokeOfferSponsorshipOperation other = (RevokeOfferSponsorshipOperation) object; - return Objects.equal(this.offerId, other.offerId) && + return Objects.equal(this.seller, other.seller) && Objects.equal(this.offerId, other.offerId) && Objects.equal(this.getSourceAccount(), other.getSourceAccount()); } } diff --git a/src/main/java/org/stellar/sdk/RevokeTrustlineSponsorshipOperation.java b/src/main/java/org/stellar/sdk/RevokeTrustlineSponsorshipOperation.java index 6deef38b6..079ca1fb4 100644 --- a/src/main/java/org/stellar/sdk/RevokeTrustlineSponsorshipOperation.java +++ b/src/main/java/org/stellar/sdk/RevokeTrustlineSponsorshipOperation.java @@ -26,6 +26,7 @@ public Asset getAsset() { org.stellar.sdk.xdr.Operation.OperationBody toOperationBody() { RevokeSponsorshipOp op = new RevokeSponsorshipOp(); LedgerKey key = new LedgerKey(); + key.setDiscriminant(LedgerEntryType.TRUSTLINE); LedgerKey.LedgerKeyTrustLine trustLine = new LedgerKey.LedgerKeyTrustLine(); trustLine.setAccountID(StrKey.encodeToXDRAccountId(accountId)); trustLine.setAsset(asset.toXdr()); diff --git a/src/test/java/org/stellar/sdk/OperationTest.java b/src/test/java/org/stellar/sdk/OperationTest.java index c1b134065..fca8c8813 100644 --- a/src/test/java/org/stellar/sdk/OperationTest.java +++ b/src/test/java/org/stellar/sdk/OperationTest.java @@ -806,4 +806,90 @@ public void testClaimClaimableBalanceOperationInvalidClaimableBalanceIDBodyMissi assertEquals("invalid balanceId: " + balanceId, e.getMessage()); } } + + @Test + public void testRevokeAccountSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String accountId = "GAGQ7DNQUVQR6OWYOI563L5EMJE6KCAHPQSFCZFLY5PDRYMRCA5UWCMP"; + RevokeAccountSponsorshipOperation operation = new RevokeAccountSponsorshipOperation.Builder(accountId).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAAAAAAAAAAAAAAND42wpWEfOthyO+2vpGJJ5QgHfCRRZKvHXjjhkRA7Sw==", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeAccountSponsorshipOperation parsedOperation = (RevokeAccountSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(accountId, parsedOperation.getAccountId()); + assertEquals(source, parsedOperation.getSourceAccount()); + } + + @Test + public void testRevokeDataSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String accountId = "GAGQ7DNQUVQR6OWYOI563L5EMJE6KCAHPQSFCZFLY5PDRYMRCA5UWCMP"; + String dataName = "data_name"; + RevokeDataSponsorshipOperation operation = new RevokeDataSponsorshipOperation.Builder(accountId, dataName).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAAAAAAAAwAAAAAND42wpWEfOthyO+2vpGJJ5QgHfCRRZKvHXjjhkRA7SwAAAAlkYXRhX25hbWUAAAA=", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeDataSponsorshipOperation parsedOperation = (RevokeDataSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(accountId, parsedOperation.getAccountId()); + assertEquals(source, parsedOperation.getSourceAccount()); + assertEquals(dataName, parsedOperation.getDataName()); + } + + @Test + public void testRevokeClaimableBalanceSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String balanceId = "00000000550e14acbdafcd3089289363b3b0c8bec9b4edd87298c690655b4b2456d68ba0"; + RevokeClaimableBalanceSponsorshipOperation operation = new RevokeClaimableBalanceSponsorshipOperation.Builder(balanceId).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAAAAAAABAAAAABVDhSsva/NMIkok2OzsMi+ybTt2HKYxpBlW0skVtaLoA==", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeClaimableBalanceSponsorshipOperation parsedOperation = (RevokeClaimableBalanceSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(balanceId, parsedOperation.getBalanceId()); + assertEquals(source, parsedOperation.getSourceAccount()); + } + + @Test + public void testRevokeOfferSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String seller = "GAGQ7DNQUVQR6OWYOI563L5EMJE6KCAHPQSFCZFLY5PDRYMRCA5UWCMP"; + Long offerId = 123456L; + RevokeOfferSponsorshipOperation operation = new RevokeOfferSponsorshipOperation.Builder(seller, offerId).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAAAAAAAAgAAAAAND42wpWEfOthyO+2vpGJJ5QgHfCRRZKvHXjjhkRA7SwAAAAAAAeJA", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeOfferSponsorshipOperation parsedOperation = (RevokeOfferSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(offerId, parsedOperation.getOfferId()); + assertEquals(seller, parsedOperation.getSeller()); + assertEquals(source, parsedOperation.getSourceAccount()); + } + + @Test + public void testRevokeSignerSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String accountId = "GAGQ7DNQUVQR6OWYOI563L5EMJE6KCAHPQSFCZFLY5PDRYMRCA5UWCMP"; + SignerKey signerKey = KeyPair.fromAccountId("GBOSQJIV4VJMWMPVPB7EFVIRJT7A7SAAAB4FA23ZDJRUMXMYHBYWY57L").getXdrSignerKey(); + RevokeSignerSponsorshipOperation operation = new RevokeSignerSponsorshipOperation.Builder(accountId, signerKey).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAABAAAAAA0PjbClYR862HI77a+kYknlCAd8JFFkq8deOOGREDtLAAAAAF0oJRXlUssx9Xh+QtURTP4PyAAAeFBreRpjRl2YOHFs", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeSignerSponsorshipOperation parsedOperation = (RevokeSignerSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(accountId, parsedOperation.getAccountId()); + assertEquals(source, parsedOperation.getSourceAccount()); + assertEquals(signerKey, parsedOperation.getSigner()); + } + + @Test + public void testRevokeTrustlineSponsorshipOperation() { + String source = "GA2N7NI5WEMJILMK4UPDTF2ZX2BIRQUM3HZUE27TRUNRFN5M5EXU6RQV"; + String accountId = "GAGQ7DNQUVQR6OWYOI563L5EMJE6KCAHPQSFCZFLY5PDRYMRCA5UWCMP"; + Asset asset = new AssetTypeCreditAlphaNum4("DEMO", "GCWPICV6IV35FQ2MVZSEDLORHEMMIAODRQPVDEIKZOW2GC2JGGDCXVVV"); + RevokeTrustlineSponsorshipOperation operation = new RevokeTrustlineSponsorshipOperation.Builder(accountId, asset).setSourceAccount(source).build(); + assertEquals("AAAAAQAAAAA037UdsRiULYrlHjmXWb6CiMKM2fNCa/ONGxK3rOkvTwAAABIAAAAAAAAAAQAAAAAND42wpWEfOthyO+2vpGJJ5QgHfCRRZKvHXjjhkRA7SwAAAAFERU1PAAAAAKz0Cr5Fd9LDTK5kQa3RORjEAcOMH1GRCsutowtJMYYr", operation.toXdrBase64()); + + org.stellar.sdk.xdr.Operation xdr = operation.toXdr(); + RevokeTrustlineSponsorshipOperation parsedOperation = (RevokeTrustlineSponsorshipOperation) Operation.fromXdr(xdr); + assertEquals(accountId, parsedOperation.getAccountId()); + assertEquals(source, parsedOperation.getSourceAccount()); + assertEquals(asset, parsedOperation.getAsset()); + } }