Skip to content

Commit

Permalink
Merge branch 'main' into Energy-to-ccd
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
magnusbechwind committed Mar 6, 2024
2 parents 81dd233 + 76951be commit 9c5d8ce
Show file tree
Hide file tree
Showing 38 changed files with 815 additions and 155 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
## Unreleased changes
- Removed unnecessary `amount` parameter from `InvokeInstanceRequest`.
- Added utility functions for converting between `CCDAmount` and `Energy`. Present in utility class `Converter`.
- Fixed a bug in `CustomEvent`. Removed unnecessary `tag` field.
- Added `Web3IdProof` class with `getWeb3IdProof` method to create Presentations. (And supporting classes)
- Fixed an issue where `ConcordiumHdWallet.fromSeedPhrase` always produced an invalid seed as hex.

## 7.0.0
- Make the `energy` parameter for invoking an instance `Optional`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package com.concordium.example.wallet
import android.content.Context
import android.content.SharedPreferences
import androidx.activity.ComponentActivity
import cash.z.ecc.android.bip39.Mnemonics
import cash.z.ecc.android.bip39.toSeed
import com.concordium.sdk.crypto.wallet.ConcordiumHdWallet

/***
Expand All @@ -23,11 +21,9 @@ class Storage(context: Context) {
val accountAddress = StorageAccessor(sharedPreferences, "account_address")
val identity = StorageAccessor(sharedPreferences, "identity")

@OptIn(ExperimentalStdlibApi::class)
fun getWallet(): ConcordiumHdWallet {
val seedPhrase = this.seedPhrase.get()
val seedAsHex = Mnemonics.MnemonicCode(seedPhrase!!.toCharArray()).toSeed().toHexString()
return ConcordiumHdWallet.fromHex(seedAsHex, Constants.NETWORK)
return ConcordiumHdWallet.fromSeedPhrase(seedPhrase, Constants.NETWORK)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import androidx.compose.ui.unit.sp
import com.concordium.sdk.crypto.ed25519.ED25519SecretKey
import com.concordium.sdk.requests.AccountQuery
import com.concordium.sdk.requests.BlockQuery
import com.concordium.sdk.transactions.AccountNonce
import com.concordium.sdk.transactions.CCDAmount
import com.concordium.sdk.transactions.Expiry
import com.concordium.sdk.transactions.Index
Expand Down Expand Up @@ -70,13 +69,13 @@ class AccountActivity : ComponentActivity() {

val client = ConcordiumClientService.getClient()
val senderInfo = client.getAccountInfo(BlockQuery.BEST, AccountQuery.from(sender))
val nonce = senderInfo.accountNonce
val nonce = senderInfo.nonce
val transactionHash = client.sendTransaction(
TransactionFactory.newTransfer()
.sender(sender)
.receiver(receiver)
.amount(amount)
.nonce(AccountNonce.from(nonce))
.nonce(nonce)
.expiry(expiry)
.signer(signer)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ public static Cis2Event deserializeCis2Event(byte[] eventBytes) {
case TOKEN_METADATA:
return SerializationUtils.deserializeTokenMetadataEvent(buffer);
case CUSTOM:
return SerializationUtils.deserializeCustomEvent(tag, buffer);
return SerializationUtils.deserializeCustomEvent(buffer);
}
throw new IllegalArgumentException("Malformed CIS2 event");
}

private static Cis2Event deserializeCustomEvent(byte tag, ByteBuffer buffer) {
return new CustomEvent(tag, buffer.array());
private static Cis2Event deserializeCustomEvent(ByteBuffer buffer) {
return new CustomEvent(buffer.array());
}

@SneakyThrows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@
@Getter
public class CustomEvent implements Cis2Event {

private final byte tag;
private final byte[] data;

public CustomEvent(byte tag, byte[] data) {
this.tag = tag;
public CustomEvent(byte[] data) {
this.data = data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static ConcordiumHdWallet fromSeedPhrase(List<String> seedPhrase, Network
byte[] seed = MnemonicCode.toSeed(seedPhrase, "");
StringBuilder sb = new StringBuilder();
for (byte b : seed) {
sb.append(String.format("%02X ", b));
sb.append(String.format("%02X", b));
}
return new ConcordiumHdWallet(sb.toString(), network);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,15 @@ public String getValue() {
default: throw new IllegalArgumentException("An unsupported network was provided");
}
}

static public Network fromLowerCase(String value) {
switch (value) {
case "mainnet":
return MAINNET;
case "testnet":
return TESTNET;
default:
throw new IllegalArgumentException("An unsupported network was provided");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.concordium.sdk.crypto.wallet.identityobject;

import java.util.Map;

import com.concordium.sdk.responses.accountinfo.credential.AttributeType;

import lombok.Getter;

@Getter
Expand All @@ -9,4 +13,11 @@ public class IdentityObject {
private PreIdentityObject preIdentityObject;
private String signature;

public String getChosenAttribute(AttributeType attribute) throws MissingAttributeException {
Map<AttributeType, String> chosenAttributes = this.getAttributeList().getChosenAttributes();
if (!chosenAttributes.containsKey(attribute)) {
throw new MissingAttributeException(attribute);
}
return chosenAttributes.get(attribute);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.concordium.sdk.crypto.wallet.identityobject;

import com.concordium.sdk.responses.accountinfo.credential.AttributeType;

import lombok.Getter;

@Getter
public class MissingAttributeException extends Exception {
private AttributeType attribute;

public MissingAttributeException(AttributeType attribute) {
this.attribute = attribute;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.concordium.sdk.crypto.wallet.web3Id;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
Expand All @@ -21,8 +23,8 @@
@JsonDeserialize(using = CredentialAttribute.CredentialAttributieTypeDeserializer.class)
@Builder
@Getter
public class CredentialAttribute {
enum CredentialAttributeType {
public final class CredentialAttribute {
public enum CredentialAttributeType {
INT,
STRING,
TIMESTAMP;
Expand All @@ -31,8 +33,59 @@ enum CredentialAttributeType {
private String value;
private CredentialAttributeType type;

static class CredentialAttributieTypeDeserializer extends JsonDeserializer<CredentialAttribute> {
private int compareStringAttributes(byte[] aBytes, byte[] bBytes) {
if (aBytes.length < bBytes.length) return -1;
if (aBytes.length > bBytes.length) return 1;

for (int i = 0; i < aBytes.length; i++) {
byte aByte = aBytes[i];
byte bByte = bBytes[i];

if (aByte == bByte) continue;
return aByte < bByte ? -1 : 1;
}

return 0;
}

public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) throws IllegalArgumentException {
if (!this.getType().equals(lower.getType()) || !this.getType().equals(upper.getType())) {
throw new IllegalArgumentException("Attribute types must match");
}
switch (this.type) {
case INT: {
long lowerVal = Long.parseUnsignedLong(lower.getValue());
long upperVal = Long.parseUnsignedLong(upper.getValue());
long val = Long.parseUnsignedLong(this.getValue());
return Long.compareUnsigned(lowerVal, val) <= 0 && Long.compareUnsigned(upperVal, val) > 0;
}
case TIMESTAMP: {
LocalDateTime lowerVal = LocalDateTime.parse(lower.getValue());
LocalDateTime upperVal = LocalDateTime.parse(upper.getValue());
LocalDateTime val = LocalDateTime.parse(this.getValue());
return !lowerVal.isAfter(val) && upperVal.isAfter(val);
}
case STRING: {
byte[] lowerVal = lower.getValue().getBytes(StandardCharsets.UTF_8);
byte[] upperVal = upper.getValue().getBytes(StandardCharsets.UTF_8);
byte[] val = this.getValue().getBytes(StandardCharsets.UTF_8);
return this.compareStringAttributes(val, lowerVal) >= 0 && this.compareStringAttributes(val, upperVal) < 0;
}
default:
throw new IllegalArgumentException("Unknown attribute type");
}
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof CredentialAttribute)) {
return false;
}
CredentialAttribute cred = (CredentialAttribute) obj;
return this.type.equals(cred.type) && this.value.equals(cred.value);
}

static class CredentialAttributieTypeDeserializer extends JsonDeserializer<CredentialAttribute> {
@Override
public CredentialAttribute deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.QualifiedRequestStatement;

import lombok.Builder;
import lombok.Getter;
Expand All @@ -11,7 +11,7 @@
@Getter
@Builder
@Jacksonized
public class Request {
public class QualifiedRequest {
private final String challenge;
private final List<RequestStatement> credentialStatements;
private final List<QualifiedRequestStatement> credentialStatements;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,29 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME;
import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject;
import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException;
import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute;
import com.concordium.sdk.responses.accountinfo.credential.AttributeType;

@JsonTypeInfo(use = NAME, include = As.PROPERTY, property = "type", visible = true)
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type", visible = true)
@JsonSubTypes ({@Type (value = RevealStatement.class), @Type (value = RangeStatement.class), @Type (value = MembershipStatement.class), @Type (value = NonMembershipStatement.class)})
public abstract class AtomicStatement {
@JsonProperty("attributeTag")
public abstract String getAttributeTag();

// TODO: add overload for web3Id credential
protected CredentialAttribute getAttributeValue(IdentityObject identityObject) throws JsonProcessingException, JsonParseException, MissingAttributeException {
AttributeType type = AttributeType.fromJSON(this.getAttributeTag());
String raw = identityObject.getChosenAttribute(type);
return CredentialAttribute.builder().value(raw).type(CredentialAttribute.CredentialAttributeType.STRING).build();
}

// TODO: add overload for web3Id credential
public abstract boolean canBeProvedBy(IdentityObject identityObject) throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

import lombok.Getter;

@Getter
@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type", visible = true)
@JsonSubTypes({ @Type(value = IdentityQualifier.class), @Type(value = VerifiableCredentialQualifier.class) })
public class IdQualifier {
@JsonUnwrapped
StatementType type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonTypeName;

import lombok.Getter;

@Getter
@JsonTypeName("cred")
public class IdentityQualifier extends IdQualifier {
private List<Long> issuers;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import java.util.List;

import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject;
import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException;
import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;

import lombok.Getter;

Expand All @@ -12,4 +16,15 @@
public class MembershipStatement extends AtomicStatement {
private String attributeTag;
private List<CredentialAttribute> set;

@Override
public boolean canBeProvedBy(IdentityObject identityObject) throws JsonParseException, JsonProcessingException {
try {
CredentialAttribute value = this.getAttributeValue(identityObject);
return set.contains(value);
} catch (MissingAttributeException e) {
// If the identityObject does not have the relevant attribute, it does not satisfy the statement
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import java.util.List;

import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject;
import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException;
import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;

import lombok.Getter;

Expand All @@ -12,4 +16,15 @@
public class NonMembershipStatement extends AtomicStatement {
private String attributeTag;
private List<CredentialAttribute> set;

@Override
public boolean canBeProvedBy(IdentityObject identityObject) throws JsonParseException, JsonProcessingException {
try {
CredentialAttribute value = this.getAttributeValue(identityObject);
return !set.contains(value);
} catch (MissingAttributeException e) {
// If the identityObject does not have the relevant attribute, it does not satisfy the statement
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.RequestIdentifier;

import lombok.Getter;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

@Getter
@SuperBuilder
@Jacksonized
public class QualifiedRequestStatement extends RequestStatement {
private RequestIdentifier id;

public StatementType getStatementType() {
return this.id.getType();
}
}
Loading

0 comments on commit 9c5d8ce

Please sign in to comment.