Skip to content

Commit

Permalink
[feature] Weighted Signature Threshold
Browse files Browse the repository at this point in the history
  • Loading branch information
stevetodd committed Feb 16, 2021
1 parent 537d67e commit 9ec9796
Show file tree
Hide file tree
Showing 36 changed files with 1,304 additions and 341 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Below describes the current capabilities of keri-java:
- [x] Record interactions in the event log
- [x] Simple signing thresholds
- [x] Multi-signature identifiers
- [ ] Weighted signing threshold
- [x] Weighted signing threshold
- [ ] Delegation

**Logs**
Expand Down
7 changes: 0 additions & 7 deletions controller/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>foundation.identity.keri</groupId>
<artifactId>event-storage-in-memory</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import java.util.Arrays;
import java.util.List;

import static foundation.identity.keri.SigningThresholds.unweighted;

public final class Controller {

private static final DigestAlgorithm DEFAULT_DIGEST_ALGO = StandardDigestAlgorithms.BLAKE3_256;
Expand Down Expand Up @@ -61,7 +63,7 @@ private KeyPair generateKeyPair(SignatureAlgorithm algorithm) {
public ControllableIdentifier newPrivateIdentifier() {
var initialKeyPair = this.generateKeyPair(DEFAULT_SIGNATURE_ALGO);
var nextKeyPair = this.generateKeyPair(DEFAULT_SIGNATURE_ALGO);
var nextKeys = KeyConfigurationDigester.digest(1, List.of(nextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);
var nextKeys = KeyConfigurationDigester.digest(unweighted(1), List.of(nextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);

var spec = IdentifierSpec.builder()
.selfAddressing(DEFAULT_DIGEST_ALGO)
Expand All @@ -86,7 +88,7 @@ public ControllableIdentifier newPrivateIdentifier() {
public ControllableIdentifier newPublicIdentifier(BasicIdentifier... witnesses) {
var initialKeyPair = this.generateKeyPair(DEFAULT_SIGNATURE_ALGO);
var nextKeyPair = this.generateKeyPair(DEFAULT_SIGNATURE_ALGO);
var nextKeys = KeyConfigurationDigester.digest(1, List.of(nextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);
var nextKeys = KeyConfigurationDigester.digest(unweighted(1), List.of(nextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);

var spec = IdentifierSpec.builder()
.selfAddressing(DEFAULT_DIGEST_ALGO)
Expand Down Expand Up @@ -135,7 +137,7 @@ public ControllableIdentifier rotate(Identifier identifier, List<Seal> seals) {
}

var newNextKeyPair = this.generateKeyPair(DEFAULT_SIGNATURE_ALGO);
var nextKeys = KeyConfigurationDigester.digest(1, List.of(newNextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);
var nextKeys = KeyConfigurationDigester.digest(unweighted(1), List.of(newNextKeyPair.getPublic()), DEFAULT_DIGEST_ALGO);

var spec = RotationSpec.builder(state)
.key(nextKeyPair.get().getPublic())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import foundation.identity.keri.api.event.EventSignature;
import foundation.identity.keri.api.event.IdentifierEvent;
import foundation.identity.keri.api.event.KeyConfigurationDigest;
import foundation.identity.keri.api.event.SigningThreshold;
import foundation.identity.keri.api.identifier.BasicIdentifier;
import foundation.identity.keri.api.identifier.Identifier;
import foundation.identity.keri.api.seal.Seal;
Expand All @@ -31,7 +32,7 @@ public Identifier identifier() {
}

@Override
public int signingThreshold() {
public SigningThreshold signingThreshold() {
return state.signingThreshold();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ public InteractionEvent interaction(InteractionSpec spec) {
signatures);
}

public ReceiptEvent receipt(
ReceiptSpec spec) {
public ReceiptEvent receipt(ReceiptSpec spec) {
var bytes = this.eventSerializer.serialize(spec);

return new ImmutableReceiptEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import foundation.identity.keri.QualifiedBase64;
Expand All @@ -13,6 +12,8 @@
import foundation.identity.keri.api.event.EventType;
import foundation.identity.keri.api.event.Format;
import foundation.identity.keri.api.event.KeyConfigurationDigest;
import foundation.identity.keri.api.event.SigningThreshold;
import foundation.identity.keri.api.event.SigningThreshold.Weighted.Weight;
import foundation.identity.keri.api.identifier.BasicIdentifier;
import foundation.identity.keri.api.identifier.Identifier;
import foundation.identity.keri.api.identifier.SelfAddressingIdentifier;
Expand All @@ -29,6 +30,8 @@
import org.msgpack.jackson.dataformat.MessagePackFactory;

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static foundation.identity.keri.Hex.hex;
import static foundation.identity.keri.Hex.hexNoPad;
Expand Down Expand Up @@ -59,29 +62,6 @@ static String identifierPlaceholder(IdentifierSpec spec) {
}
}

static void gatherInceptionValues(StringBuilder b, JsonNode jsonNode, boolean root) {
if (jsonNode.isValueNode() && jsonNode.isTextual()) {
b.append(jsonNode.asText());
} else if (jsonNode.isObject()) {
for (var iter = jsonNode.fields(); iter.hasNext(); ) {
var entry = iter.next();

if (root && entry.getKey().equals(IDENTIFIER.label())) {
continue;
}

gatherInceptionValues(b, entry.getValue(), false);
}
} else if (jsonNode.isArray()) {
var arrayNode = (ArrayNode) jsonNode;
for (var i : arrayNode) {
gatherInceptionValues(b, i, false);
}
} else {
throw new IllegalStateException("Should not have non-text values");
}
}

static String version(Version v, Format f, long size) {
return String.format("KERI%x%x%s%06x_", v.minor(), v.major(), format(f), size);
}
Expand Down Expand Up @@ -123,6 +103,37 @@ static ObjectNode seal(Seal seal, ObjectMapper mapper) {
return obj;
}

static JsonNode signingThreshold(SigningThreshold t, ObjectMapper mapper) {
if (t instanceof SigningThreshold.Unweighted) {
return mapper.getNodeFactory().textNode(((SigningThreshold.Unweighted) t).threshold() + "");
} else if (t instanceof SigningThreshold.Weighted) {
var wt = (SigningThreshold.Weighted) t;
var groupArrayNodes = Stream.of(wt.weights())
.map(lw -> {
var textNodes = Stream.of(lw)
.map(EventSerializer::weight)
.map(str -> mapper.getNodeFactory().textNode(str))
.collect(Collectors.toList());
return mapper.getNodeFactory().arrayNode()
.addAll(textNodes);
})
.collect(Collectors.toList());

return mapper.getNodeFactory().arrayNode()
.addAll(groupArrayNodes);
} else {
throw new IllegalArgumentException("Unknown SigningThreshold type: " + t.getClass());
}
}

static String weight(Weight w) {
if (w.denominator().isEmpty()) {
return "" + w.numerator();
}

return w.numerator() + "/" + w.denominator().get();
}

static void writeSize(byte[] bytes) {
// version string is "KERIVVFFFFSSSSSS_"
// VV = version
Expand Down Expand Up @@ -161,13 +172,6 @@ public byte[] inceptionStatement(IdentifierSpec spec) {
return serialize(null, spec);
}

// TODO delete
public byte[] inceptionStatement(JsonNode rootNode) {
var b = new StringBuilder();
gatherInceptionValues(b, rootNode, true);
return b.toString().getBytes(UTF_8);
}

public byte[] serialize(Identifier identifier, IdentifierSpec spec) {
var mapper = mapper(spec.format());
var rootNode = mapper.createObjectNode();
Expand All @@ -181,7 +185,7 @@ public byte[] serialize(Identifier identifier, IdentifierSpec spec) {
rootNode.put(SEQUENCE_NUMBER.label(), hexNoPad(0));
rootNode.put(EVENT_TYPE.label(), type(EventType.INCEPTION));

rootNode.put(SIGNING_THRESHOLD.label(), hexNoPad(spec.signingThreshold()));
rootNode.set(SIGNING_THRESHOLD.label(), signingThreshold(spec.signingThreshold(), mapper));

var keysNode = mapper.createArrayNode();
spec.keys().forEach(k -> keysNode.add(qb64(k)));
Expand Down Expand Up @@ -222,7 +226,7 @@ public byte[] serialize(RotationSpec spec) {
rootNode.put(EVENT_TYPE.label(), type(EventType.ROTATION));
rootNode.put(PRIOR_EVENT_DIGEST.label(), qb64(spec.previous().digest()));

rootNode.put(SIGNING_THRESHOLD.label(), hexNoPad(spec.signingThreshold()));
rootNode.set(SIGNING_THRESHOLD.label(), signingThreshold(spec.signingThreshold(), mapper));

var keysNode = mapper.createArrayNode();
spec.keys().forEach(k -> keysNode.add(qb64(k)));
Expand Down
Loading

0 comments on commit 9ec9796

Please sign in to comment.