From 1461c2fc5b89ab2210237bcabb9d4fe0c0d2fa97 Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Sat, 2 Sep 2023 01:49:51 +0800 Subject: [PATCH] Fix the bug in Transaction.isSorobanTransaction to accommodate BumpFootprintExpirationOperation. (#518) * Fix the bug in Transaction.isSorobanTransaction to accommodate BumpFootprintExpirationOperation. * remove "android-test" in deploy needs. * Switch the system used for Android testing to macos-13. --- .github/workflows/test-deploy.yml | 16 +- CHANGELOG.md | 3 + build.gradle | 2 +- .../java/org/stellar/sdk/Transaction.java | 2 +- .../java/org/stellar/sdk/TransactionTest.java | 191 +++++++++++++++++- 5 files changed, 204 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 95bbf1589..ecaf2c510 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -68,13 +68,17 @@ jobs: android-test: needs: shadow_jar - runs-on: macos-latest - name: android-test (api ${{ matrix.api-level }}) + runs-on: macos-13 + name: android-test (api ${{ matrix.emulator.api-level }}) strategy: fail-fast: false matrix: # minSdk and targetSdk, see ${project_root}/android_test/app/build.gradle.kts - api-level: [ 26, 33 ] + # TODO: Investigate why it is unstable on API 33. + emulator: [ + { api-level: 26, target: google_apis }, + { api-level: 33, target: playstore } + ] steps: - name: checkout uses: actions/checkout@v3 @@ -91,14 +95,14 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: working-directory: ./android_test - api-level: ${{ matrix.api-level }} + api-level: ${{ matrix.emulator.api-level }} + target: ${{ matrix.emulator.target }} script: ./gradlew connectedCheck - target: google_apis arch: x86_64 profile: 'pixel_2' deploy: - needs: [ javadoc, android-test ] + needs: [ javadoc, shadow_jar ] # TODO: add android-test when it is stable. permissions: contents: write if: github.event_name == 'release' && github.event.action == 'created' diff --git a/CHANGELOG.md b/CHANGELOG.md index 702c3eb7c..761defab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ As this project is pre 1.0, breaking changes may happen for minor version bumps. ## Pending +## 0.41.0-beta.3 +* Fix the bug in Transaction.isSorobanTransaction to accommodate BumpFootprintExpirationOperation. ([#518](https://github.com/stellar/java-stellar-sdk/pull/518)) + ## 0.41.0-beta.2 * Migrate from CircleCI to GitHub Actions. ([#512](https://github.com/stellar/java-stellar-sdk/pull/512)) diff --git a/build.gradle b/build.gradle index 02eaede5f..52382c68b 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ spotless { sourceCompatibility = JavaVersion.VERSION_1_8.toString() -version = '0.41.0-beta.2' +version = '0.41.0-beta.3' group = 'stellar' jar.enabled = false diff --git a/src/main/java/org/stellar/sdk/Transaction.java b/src/main/java/org/stellar/sdk/Transaction.java index 316c88c93..56beee7d7 100644 --- a/src/main/java/org/stellar/sdk/Transaction.java +++ b/src/main/java/org/stellar/sdk/Transaction.java @@ -402,7 +402,7 @@ public boolean isSorobanTransaction() { Operation op = mOperations[0]; return op instanceof InvokeHostFunctionOperation - || op instanceof BumpSequenceOperation + || op instanceof BumpFootprintExpirationOperation || op instanceof RestoreFootprintOperation; } } diff --git a/src/test/java/org/stellar/sdk/TransactionTest.java b/src/test/java/org/stellar/sdk/TransactionTest.java index a121ea898..2724d565b 100644 --- a/src/test/java/org/stellar/sdk/TransactionTest.java +++ b/src/test/java/org/stellar/sdk/TransactionTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -12,8 +13,34 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.junit.Test; -import org.stellar.sdk.xdr.*; +import org.stellar.sdk.scval.Scv; +import org.stellar.sdk.xdr.ContractDataDurability; +import org.stellar.sdk.xdr.ContractEntryBodyType; +import org.stellar.sdk.xdr.ContractExecutable; +import org.stellar.sdk.xdr.ContractExecutableType; +import org.stellar.sdk.xdr.ContractIDPreimage; +import org.stellar.sdk.xdr.ContractIDPreimageType; +import org.stellar.sdk.xdr.CreateContractArgs; +import org.stellar.sdk.xdr.DecoratedSignature; +import org.stellar.sdk.xdr.EnvelopeType; +import org.stellar.sdk.xdr.ExtensionPoint; +import org.stellar.sdk.xdr.HostFunction; +import org.stellar.sdk.xdr.HostFunctionType; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.LedgerEntryType; +import org.stellar.sdk.xdr.LedgerFootprint; +import org.stellar.sdk.xdr.LedgerKey; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SignerKey; +import org.stellar.sdk.xdr.SorobanResources; +import org.stellar.sdk.xdr.SorobanTransactionData; +import org.stellar.sdk.xdr.Uint256; +import org.stellar.sdk.xdr.Uint32; +import org.stellar.sdk.xdr.XdrDataInputStream; +import org.stellar.sdk.xdr.XdrUnsignedInteger; public class TransactionTest { @@ -58,7 +85,7 @@ public void testParseV0Transaction() throws FormatException, IOException { (Transaction) Transaction.fromEnvelopeXdr( AccountConverter.enableMuxed(), transaction.toEnvelopeXdrBase64(), Network.PUBLIC); - assertTrue(parsed.equals(transaction)); + assertEquals(parsed, transaction); assertEquals(EnvelopeType.ENVELOPE_TYPE_TX_V0, parsed.toEnvelopeXdr().getDiscriminant()); assertEquals(transaction.toEnvelopeXdrBase64(), parsed.toEnvelopeXdrBase64()); @@ -260,4 +287,164 @@ public void testConstructorWithSorobanData() throws IOException { "AAAAAgAAAABexSIg06FtXzmFBQQtHZsrnyWxUzmthkBEhs/ktoeVYgAAAGQAClWjAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAH8wYjTJienWf2nf2TEZi2APPWzmtkwiQHAftisIgyuHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAfzBiNMmJ6dZ/ad/ZMRmLYA89bOa2TCJAcB+2KwiDK4cAAAAAAACHBwAAArsAAAAAAAAA2AAAAAAAAABkAAAAAA=="; assertEquals(expectedXdr, transaction.toEnvelopeXdrBase64()); } + + @Test + public void testIsSorobanTransactionInvokeHostFunctionOperation() { + KeyPair source = + KeyPair.fromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); + + Account account = new Account(source.getAccountId(), 2908908335136768L); + + String contractId = "CDYUOBUVMZPWIU4GB4XNBAYL6NIHIMYLZFNEXOCDIO33MBJMNPSFBYKU"; + String functionName = "hello"; + List params = Collections.singletonList(Scv.toSymbol("Soroban")); + InvokeHostFunctionOperation operation = + InvokeHostFunctionOperation.invokeContractFunctionOperationBuilder( + contractId, functionName, params) + .build(); + + Transaction transaction = + new Transaction( + AccountConverter.enableMuxed(), + account.getAccountId(), + Transaction.MIN_BASE_FEE, + account.getIncrementedSequenceNumber(), + new org.stellar.sdk.Operation[] {operation}, + null, + new TransactionPreconditions( + null, null, BigInteger.ZERO, 0, new ArrayList(), null), + null, + Network.TESTNET); + assertTrue(transaction.isSorobanTransaction()); + } + + @Test + public void testIsSorobanTransactionBumpFootprintExpirationOperation() { + KeyPair source = + KeyPair.fromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); + + Account account = new Account(source.getAccountId(), 2908908335136768L); + String contractId = "CDYUOBUVMZPWIU4GB4XNBAYL6NIHIMYLZFNEXOCDIO33MBJMNPSFBYKU"; + SorobanTransactionData sorobanData = + new SorobanDataBuilder() + .setReadOnly( + Collections.singletonList( + new LedgerKey.Builder() + .discriminant(LedgerEntryType.CONTRACT_DATA) + .contractData( + new LedgerKey.LedgerKeyContractData.Builder() + .contract(new Address(contractId).toSCAddress()) + .key(Scv.toLedgerKeyContractInstance()) + .durability(ContractDataDurability.PERSISTENT) + .bodyType(ContractEntryBodyType.DATA_ENTRY) + .build()) + .build())) + .build(); + BumpFootprintExpirationOperation operation = + BumpFootprintExpirationOperation.builder().ledgersToExpire(4096L).build(); + Transaction transaction = + new Transaction( + AccountConverter.enableMuxed(), + account.getAccountId(), + Transaction.MIN_BASE_FEE, + account.getIncrementedSequenceNumber(), + new org.stellar.sdk.Operation[] {operation}, + null, + new TransactionPreconditions( + null, null, BigInteger.ZERO, 0, new ArrayList(), null), + sorobanData, + Network.TESTNET); + assertTrue(transaction.isSorobanTransaction()); + } + + @Test + public void testIsSorobanTransactionRestoreFootprintOperation() { + KeyPair source = + KeyPair.fromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); + + Account account = new Account(source.getAccountId(), 2908908335136768L); + String contractId = "CDYUOBUVMZPWIU4GB4XNBAYL6NIHIMYLZFNEXOCDIO33MBJMNPSFBYKU"; + SorobanTransactionData sorobanData = + new SorobanDataBuilder() + .setReadOnly( + Collections.singletonList( + new LedgerKey.Builder() + .discriminant(LedgerEntryType.CONTRACT_DATA) + .contractData( + new LedgerKey.LedgerKeyContractData.Builder() + .contract(new Address(contractId).toSCAddress()) + .key(Scv.toLedgerKeyContractInstance()) + .durability(ContractDataDurability.PERSISTENT) + .bodyType(ContractEntryBodyType.DATA_ENTRY) + .build()) + .build())) + .build(); + RestoreFootprintOperation operation = RestoreFootprintOperation.builder().build(); + Transaction transaction = + new Transaction( + AccountConverter.enableMuxed(), + account.getAccountId(), + Transaction.MIN_BASE_FEE, + account.getIncrementedSequenceNumber(), + new org.stellar.sdk.Operation[] {operation}, + null, + new TransactionPreconditions( + null, null, BigInteger.ZERO, 0, new ArrayList(), null), + sorobanData, + Network.TESTNET); + assertTrue(transaction.isSorobanTransaction()); + } + + @Test + public void testIsSorobanTransactionMultiOperations() { + KeyPair source = + KeyPair.fromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); + + Account account = new Account(source.getAccountId(), 2908908335136768L); + + String contractId = "CDYUOBUVMZPWIU4GB4XNBAYL6NIHIMYLZFNEXOCDIO33MBJMNPSFBYKU"; + String functionName = "hello"; + List params = Collections.singletonList(Scv.toSymbol("Soroban")); + InvokeHostFunctionOperation operation = + InvokeHostFunctionOperation.invokeContractFunctionOperationBuilder( + contractId, functionName, params) + .build(); + + Transaction transaction = + new Transaction( + AccountConverter.enableMuxed(), + account.getAccountId(), + Transaction.MIN_BASE_FEE, + account.getIncrementedSequenceNumber(), + new org.stellar.sdk.Operation[] {operation, operation}, + null, + new TransactionPreconditions( + null, null, BigInteger.ZERO, 0, new ArrayList(), null), + null, + Network.TESTNET); + assertFalse(transaction.isSorobanTransaction()); + } + + @Test + public void testIsSorobanTransactionBumpSequenceOperation() { + KeyPair source = + KeyPair.fromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); + + Account account = new Account(source.getAccountId(), 2908908335136768L); + BumpSequenceOperation operation = new BumpSequenceOperation.Builder(0L).build(); + + Transaction transaction = + new Transaction( + AccountConverter.enableMuxed(), + account.getAccountId(), + Transaction.MIN_BASE_FEE, + account.getIncrementedSequenceNumber(), + new org.stellar.sdk.Operation[] {operation}, + null, + new TransactionPreconditions( + null, null, BigInteger.ZERO, 0, new ArrayList(), null), + null, + Network.TESTNET); + assertFalse(transaction.isSorobanTransaction()); + } }