Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FOR REVIEW ONLY - java-algorand-sdk 1.18.0 #378

Merged
merged 7 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .test-env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Configs for testing repo download:
SDK_TESTING_URL="https://github.com/algorand/algorand-sdk-testing"
SDK_TESTING_BRANCH="master"
SDK_TESTING_HARNESS="test-harness"

VERBOSE_HARNESS=0

# WARNING: If set to 1, new features will be LOST when downloading the test harness.
# REGARDLESS: modified features are ALWAYS overwritten.
REMOVE_LOCAL_FEATURES=0

# WARNING: Be careful when turning on the next variable.
# In that case you'll need to provide all variables expected by `algorand-sdk-testing`'s `.env`
OVERWRITE_TESTING_ENVIRONMENT=0
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# 1.18.0-beta-1
## What's Changed
### Bugfixes
* Bug-Fix: Pass verbosity to the harness and sandbox by @tzaffi in https://github.com/algorand/java-algorand-sdk/pull/371
### New Features
* StateProofs: Add State Proof support. by @winder in https://github.com/algorand/java-algorand-sdk/pull/360
### Enhancements
* Enhancement: Use Sandbox for Testing by @tzaffi in https://github.com/algorand/java-algorand-sdk/pull/363
* Enhancement: Deprecating use of langspec by @ahangsu in https://github.com/algorand/java-algorand-sdk/pull/367

## New Contributors
* @tzaffi made their first contribution in https://github.com/algorand/java-algorand-sdk/pull/363

**Full Changelog**: https://github.com/algorand/java-algorand-sdk/compare/1.17.0...1.18.0-beta-1

# 1.17.0
### New Features
* DevTools: adding source map decoder by @barnjamin in https://github.com/algorand/java-algorand-sdk/pull/352
Expand Down
26 changes: 20 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
UNIT_TAGS := "$(subst :, or ,$(shell awk '{print $2}' src/test/unit.tags | paste -s -d: -))"
INTEGRATION_TAGS := "$(subst :, or ,$(shell awk '{print $2}' src/test/integration.tags | paste -s -d: -))"

unit:
mvn test -Dcucumber.filter.tags="@unit.offline or @unit.algod or @unit.indexer or @unit.rekey or @unit.indexer.rekey or @unit.transactions or @unit.transactions.keyreg or @unit.responses or @unit.applications or @unit.dryrun or @unit.tealsign or @unit.responses.messagepack or @unit.responses.231 or @unit.responses.messagepack.231 or @unit.feetest or @unit.indexer.logs or @unit.abijson or @unit.abijson.byname or @unit.atomic_transaction_composer or @unit.transactions.payment or @unit.responses.unlimited_assets or @unit.algod.ledger_refactoring or @unit.indexer.ledger_refactoring or @unit.dryrun.trace.application or @unit.sourcemap"
mvn test -Dcucumber.filter.tags=$(UNIT_TAGS)

integration:
mvn test \
-Dtest=com.algorand.algosdk.integration.RunCucumberIntegrationTest \
-Dcucumber.filter.tags="@algod or @assets or @auction or @kmd or @send or @send.keyregtxn or @indexer or @rekey_v1 or @applications.verified or @applications or @compile or @dryrun or @indexer.applications or @indexer.231 or @abi or @c2c or @compile.sourcemap"
mvn test -Dtest=com.algorand.algosdk.integration.RunCucumberIntegrationTest -Dcucumber.filter.tags=$(INTEGRATION_TAGS)

display-all-java-steps:
find src/test/java/com/algorand/algosdk -name "*.java" | xargs grep "io.cucumber.java.en" 2>/dev/null | grep -v Binary | cut -d: -f1 | sort | uniq | xargs grep -E "@(Given|Then|When)"

harness:
./test-harness.sh

docker-javasdk-build:
# Build SDK testing environment
docker build -t java-sdk-testing .

docker-javasdk-run:
# Launch SDK testing
docker run -it --network host java-sdk-testing:latest

docker-test:
./run_integration_tests.sh
docker-test: harness docker-javasdk-build docker-javasdk-run
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Maven:
<dependency>
<groupId>com.algorand</groupId>
<artifactId>algosdk</artifactId>
<version>1.17.0</version>
<version>1.18.0-beta-1</version>
</dependency>
```

Expand Down Expand Up @@ -219,6 +219,13 @@ There is also a special integration test environment, and shared tests. To run t
~$ make docker-test
```

To stand up the test harness, without running the entire test suite use the Makefile:
```
~$ make harness
```
You can then run specific cucumber-based unit and integration tests directly.


## deploying artifacts

The generated pom file provides maven compatibility and deploy capabilities.
Expand All @@ -229,6 +236,14 @@ mvn clean site -P github,default # for javadoc
mvn clean deploy -P release,default
```

# Testing

Many cross-SDK tests are defined in [algorand-sdk-testing](https://github.com/algorand/algorand-sdk-testing/). Some are integration tests with additional dependencies. These dependencies are containerized in a docker file, which can be executed with `make docker-test`.

It is occasionally useful to run locally, or against alternate integration branches. To do this:
1. Install feature files for your test branch "./run_integration_tests.sh -feature-only -test-branch <branch here>"
2. Run locally with `make integration` and `make unit`, or from the IDE by running "RunCucumberUnitTest.java"

# Android Support

Significant work has been taken to ensure Android compatibility (in particular for `minSdkVersion` 16). Note that the
Expand All @@ -245,7 +260,7 @@ A testing framework can also be generated with: `com.algorand.sdkutils.RunQueryM

## Regenerate the Client Code

To actually regenerate the code, use `run_generator.sh` with paths to the `*.oas2.json` files mentioned above.
The actual generation is done using the `generate_java.sh` script in the [generator](https://github.com/algorand/generator/) repo.

# Updating the `kmd` REST client
The `kmd` REST client has not been upgraded to use the new code generation, it is still largely autogenerated by `swagger-codegen`. [https://github.com/swagger-api/swagger-codegen]
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.algorand</groupId>
<artifactId>algosdk</artifactId>
<version>1.17.0</version>
<version>1.18.0-beta-1</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down
82 changes: 0 additions & 82 deletions run_integration_tests.sh

This file was deleted.

68 changes: 56 additions & 12 deletions src/main/java/com/algorand/algosdk/crypto/LogicsigSignature.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.codec.binary.Base64;

/**
* Serializable logicsig class.
Expand All @@ -39,6 +40,59 @@ public class LogicsigSignature {
@JsonProperty("msig")
public MultisigSignature msig;


private static boolean isAsciiPrintable(final byte symbol) {
// linebreak existence check in program byte
boolean isBreakLine = symbol == '\n';
// printable ascii between range 32 (space) and 126 (tilde ~)
boolean isStdPrintable = symbol >= ' ' && symbol <= '~';
return isBreakLine || isStdPrintable;
}

private static boolean isAsciiPrintable(final byte[] program) {
for (byte b : program) {
if (!isAsciiPrintable(b))
return false;
}
return true;
}

/**
* Performs heuristic program validation:
* check if passed in bytes are Algorand address or is B64 encoded, rather than Teal bytes
* @param program
*/
private static void sanityCheckProgram(final byte[] program) {
if (program == null || program.length == 0)
throw new IllegalArgumentException("empty program");
// in any case, if a slice of "program-bytes" is full of ASCII printable,
// then the slice of bytes can't be Teal program bytes.
// need to check what possible kind of bytes are passed in.
if (isAsciiPrintable(program)) {
// maybe the bytes passed in are representing an Algorand address
boolean isAddress = false;
try {
new Address(new String(program));
isAddress = true;
} catch (NoSuchAlgorithmException | IllegalArgumentException e) {
// if exception is IllegalArgException, it means bytes are not Algorand address
if (e instanceof NoSuchAlgorithmException)
throw new IllegalArgumentException("cannot check if program bytes are Algorand address" + e);
}
if (isAddress)
throw new IllegalArgumentException("requesting program bytes, get Algorand address");

// or maybe these bytes are some B64 encoded bytes representation
if (Base64.isBase64(program))
throw new IllegalArgumentException("program should not be b64 encoded");

// can't further analyze, but it is more than just B64 encoding at this point
throw new IllegalArgumentException(
"program bytes are all ASCII printable characters, not looking like Teal byte code"
);
}
}

@JsonCreator
public LogicsigSignature(
@JsonProperty("l") byte[] logic,
Expand All @@ -48,14 +102,8 @@ public LogicsigSignature(
) {
this.logic = Objects.requireNonNull(logic, "program must not be null");
this.args = args;
boolean verified = false;
try {
verified = Logic.checkProgram(this.logic, this.args);
} catch (IOException ex) {
throw new IllegalArgumentException("invalid program", ex);
}

assert verified;
sanityCheckProgram(this.logic);

if (sig != null) this.sig = new Signature(sig);
this.msig = msig;
Expand Down Expand Up @@ -124,11 +172,7 @@ public boolean verify(Address singleSigner) throws NoSuchAlgorithmException {
return false;
}

try {
Logic.checkProgram(this.logic, this.args);
} catch (Exception ex) {
return false;
}
sanityCheckProgram(this.logic);

PublicKey pk;
try {
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/com/algorand/algosdk/logic/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
/**
* Logic class provides static checkProgram function
* that can be used for client-side program validation for size and execution cost.
*
* @deprecated this class is deprecated for relying on metadata (`langspec.json`) that
* does not accurately represent opcode behavior across program versions.
*/
@Deprecated
public class Logic {

private static final int MAX_COST = 20000;
Expand Down Expand Up @@ -103,7 +107,7 @@ protected static class ByteConstBlock {
* Each byte in a varint, except the last byte, has the most significant
* bit (msb) set – this indicates that there are further bytes to come.
* The lower 7 bits of each byte are used to store the two's complement
* representation of the number in groups of 7 bits, least significant
* representation of the number in groups of 7 bits, the least significant
* group first.
* https://developers.google.com/protocol-buffers/docs/encoding
* @param value being serialized
Expand All @@ -128,7 +132,7 @@ public static byte[] putUVarint(int value) {
* Given a varint, get the integer value
* @param buffer serialized varint
* @param bufferOffset position in the buffer to start reading from
* @return pair of values in in array: value, read size
* @return pair of values in an array: value, read size
*/
public static VarintResult getUVarint(byte [] buffer, int bufferOffset) {
int x = 0;
Expand Down Expand Up @@ -164,6 +168,7 @@ public static boolean checkProgram(byte[] program, List<byte[]> args) throws IOE

/**
* Performs basic program validation: instruction count and program cost
*
* @param program Program to validate
* @param args Program arguments to validate
* @return boolean
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/com/algorand/algosdk/transaction/Transaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ public class Transaction implements Serializable {
@JsonProperty("apep")
public Long extraPages = 0L;

/* state proof fields */
@JsonProperty("sptype")
public Integer stateProofType = null;

@JsonProperty("sp")
public Map<String,Object> stateProof = null;

@JsonProperty("spmsg")
public Map<String,Object> stateProofMessage = null;

/**
* Create a payment transaction
* @param fromAddr source address
Expand Down Expand Up @@ -722,7 +732,7 @@ private Transaction(@JsonProperty("type") Type type,
}

/**
* Constructor which takes all the fields of Transaction except for nonpart and state proof.
* Constructor which takes all the fields of Transaction except for nonpart.
* For details about which fields to use with different transaction types, refer to the developer documentation:
* https://developer.algorand.org/docs/reference/transactions/#asset-transfer-transaction
*/
Expand Down Expand Up @@ -1250,7 +1260,8 @@ public enum Type {
AssetConfig("acfg"),
AssetTransfer("axfer"),
AssetFreeze("afrz"),
ApplicationCall("appl");
ApplicationCall("appl"),
StateProof("stpf");

private static Map<String, Type> namesMap = new HashMap<String, Type>(6);

Expand Down
Loading