Skip to content
This repository has been archived by the owner on Feb 19, 2024. It is now read-only.

Fix Pre-signed blob #182

Merged
merged 6 commits into from
Apr 17, 2021
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
import com.radixdlt.DefaultSerialization;
import com.radixdlt.atom.Atom;
import com.radixdlt.atom.SubstateId;
import com.radixdlt.atom.SubstateSerializer;
import com.radixdlt.atomos.RriId;
import com.radixdlt.constraintmachine.Particle;
import com.radixdlt.constraintmachine.REInstruction;
import com.radixdlt.store.AtomIndex;
import com.radixdlt.store.CMStore;
import com.radixdlt.store.ImmutableIndex;
import com.radixdlt.utils.functional.Result;

import java.nio.ByteBuffer;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.radixdlt.serialization.SerializationUtils.restore;

Expand Down Expand Up @@ -73,10 +73,25 @@ public Optional<Particle> loadUpParticle(Transaction dbTxn, SubstateId substateI
return atomIndex.get(txnId)
.flatMap(txn ->
restore(DefaultSerialization.getInstance(), txn.getPayload(), Atom.class)
.map(a -> a.getInstructions().stream().map(REInstruction::create)
.collect(Collectors.toList()))
.map(i -> i.get(substateId.getIndex().orElseThrow()))
.flatMap(i -> SubstateSerializer.deserializeToResult(i.getData()))
.flatMap(a -> {
var buf = ByteBuffer.wrap(a.getUnsignedBlob());
var index = substateId.getIndex().orElseThrow();
int cur = 0;
while (buf.hasRemaining()) {
try {
var i = REInstruction.readFrom(txn, cur, buf);
if (cur == index) {
Particle p = i.getData();
return Result.ok(p);
}
} catch (Exception e) {
return Result.fail(e.getMessage());
}
cur++;
}

return Result.fail("Not found.");
})
.toOptional()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.google.common.hash.HashCode;
import com.google.inject.Inject;
import com.radixdlt.DefaultSerialization;
import com.radixdlt.atom.Atom;
import com.radixdlt.atom.TxAction;
import com.radixdlt.atom.Txn;
Expand All @@ -31,6 +32,7 @@
import com.radixdlt.fees.NativeToken;
import com.radixdlt.identifiers.AID;
import com.radixdlt.identifiers.RRI;
import com.radixdlt.serialization.DsonOutput;
import com.radixdlt.serialization.Serialization;
import com.radixdlt.statecomputer.RadixEngineStateComputer;
import com.radixdlt.utils.UInt256;
Expand All @@ -40,8 +42,6 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static com.radixdlt.serialization.SerializationUtils.restore;

public class SubmissionService {
private final UInt256 fixedFee = UInt256.TEN.pow(TokenDefinitionUtils.SUB_UNITS_POW_10 - 3).multiply(UInt256.from(50));

Expand Down Expand Up @@ -92,19 +92,24 @@ private List<TxAction> toActions(List<TransactionAction> steps) {
.collect(Collectors.toList());
}


private static Txn atomToTxn(Atom atom) {
var payload = DefaultSerialization.getInstance().toDson(atom, DsonOutput.Output.ALL);
return Txn.create(payload);
}

public Result<AID> calculateTxId(byte[] blob, ECDSASignature recoverable) {
return restore(serialization, blob, Atom.class)
.map(atom -> atom.toSigned(recoverable))
.map(Txn::fromAtom)
return Result.ok(Atom.create(blob, recoverable))
.map(SubmissionService::atomToTxn)
.map(Txn::getId);
}

public Result<AID> submitTx(byte[] blob, ECDSASignature recoverable, AID txId) {
return restore(serialization, blob, Atom.class)
.map(atom -> atom.toSigned(recoverable))
.map(Txn::fromAtom)
.filter(txn -> txn.getId().equals(txId), "Provided txID does not match provided transaction")
.onSuccess(txn -> stateComputer.addToMempool(txn, self)).map(Txn::getId);
var atom = Atom.create(blob, recoverable);
var txn = atomToTxn(atom);
return Result.ok(txn)
.filter(t -> t.getId().equals(txId), "Provided txID does not match provided transaction")
.onSuccess(t -> stateComputer.addToMempool(txn, self)).map(Txn::getId);
}

private PreparedTransaction toPreparedTx(byte[] first, HashCode second) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,13 +575,13 @@ private Optional<Particle> entryToUpParticle(DatabaseEntry e) {

private void updateParticle(com.sleepycat.je.Transaction txn, REParsedInstruction inst) {
if (inst.isBootUp()) {
var buf = inst.getInstruction().getData();
var buf = inst.getInstruction().getDataByteBuffer();
upParticle(txn, buf, inst.getSubstate().getId());

if (inst.getParticle() instanceof TokenDefinitionParticle) {
var p = (TokenDefinitionParticle) inst.getParticle();
var rriId = p.getRriId();
var buf2 = inst.getInstruction().getData();
var buf2 = inst.getInstruction().getDataByteBuffer();
var value = new DatabaseEntry(buf2.array(), buf2.position(), buf2.remaining());
rriDatabase.putNoOverwrite(txn, entry(rriId.asBytes()), value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ public void preparing_system_update_from_vertex_should_fail() throws TxBuilderEx
var illegalTxn = TxLowLevelBuilder.newBuilder()
.down(SubstateId.ofSubstate(txn.getId(), 1))
.up(new SystemParticle(1, 2, 0))
.particleGroup()
.buildWithoutSignature();

// Act
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.radixdlt.ledger.LedgerAccumulator;
import com.radixdlt.ledger.SimpleLedgerAccumulatorAndVerifier;
import com.radixdlt.ledger.VerifiedTxnsAndProof;
import com.radixdlt.serialization.DsonOutput;
import com.radixdlt.statecomputer.checkpoint.MockedGenesisModule;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -92,8 +93,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

import static com.radixdlt.serialization.SerializationUtils.restore;

public class SubmissionServiceTest {
@Inject
@Genesis
Expand Down Expand Up @@ -259,6 +258,11 @@ public void testCalculateTxId() throws Exception {
.onSuccess(Assert::assertNotNull);
}

private static Txn atomToTxn(Atom atom) {
var payload = DefaultSerialization.getInstance().toDson(atom, DsonOutput.Output.ALL);
return Txn.create(payload);
}

@Test
public void testSubmitTx() throws Exception {
var result = buildTransaction();
Expand All @@ -267,9 +271,8 @@ public void testSubmitTx() throws Exception {
result
.onFailureDo(Assert::fail)
.flatMap(prepared ->
signature.flatMap(recoverable -> restore(serialization, prepared.getBlob(), Atom.class)
.map(atom -> atom.toSigned(recoverable))
.map(Txn::fromAtom)
signature.flatMap(recoverable -> Result.ok(Atom.create(prepared.getBlob(), recoverable))
.map(SubmissionServiceTest::atomToTxn)
.map(Txn::getId)
.flatMap(txId -> submissionService.submitTx(prepared.getBlob(), recoverable, txId))))
.onFailureDo(Assert::fail)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ public void when_validating_atom_without_particles__result_has_error() {
.isInstanceOf(RadixEngineException.class);
}


@Test
public void when_validating_atom_with_fee_and_no_change__result_has_no_error() throws Exception {
var atom = TxBuilder.newBuilder(address, engineStore)
Expand Down
54 changes: 17 additions & 37 deletions radixdlt-engine/src/main/java/com/radixdlt/atom/Atom.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,12 @@
import com.radixdlt.serialization.SerializerDummy;
import com.radixdlt.serialization.SerializerId2;

import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.concurrent.Immutable;

import static java.util.Objects.requireNonNull;

/**
* An atom to be processed by radix engine
*/
Expand All @@ -56,57 +50,48 @@ public final class Atom {

@JsonProperty("i")
@DsonOutput({Output.ALL})
private final List<byte[]> instructions;
private final byte[] unsignedBlob;

@JsonProperty("s")
@DsonOutput({Output.ALL})
private final ECDSASignature signature;

@JsonCreator
private Atom(
@JsonProperty("i") List<byte[]> byteInstructions,
@JsonProperty("i") byte[] unsignedBlob,
@JsonProperty("s") ECDSASignature signature
) {
this.instructions = byteInstructions;
this.unsignedBlob = unsignedBlob;
this.signature = signature;
}

static Atom create(
List<byte[]> instructions,
public static Atom create(
byte[] unsignedBlob,
ECDSASignature signature
) {
return new Atom(instructions, signature);
return new Atom(unsignedBlob, signature);
}

public HashCode computeHashToSign() {
return computeHashToSignFromBytes(getInstructions());
}

public static HashCode computeHashToSignFromBytes(Collection<byte[]> instructions) {
return computeHashToSignFromBytes(computeBlobToSign(instructions));
public byte[] getUnsignedBlob() {
return unsignedBlob;
}

public static HashCode computeHashToSignFromBytes(byte[] blob) {
return HashUtils.sha256(HashUtils.sha256(blob).asBytes());
var firstHash = HashUtils.sha256(blob);
return HashUtils.sha256(firstHash.asBytes());
}

public static byte[] computeBlobToSign(Collection<byte[]> instructions) {
var outputStream = new ByteArrayOutputStream();
instructions.forEach(outputStream::writeBytes);
return outputStream.toByteArray();
public HashCode computeHashToSign() {
return computeHashToSignFromBytes(unsignedBlob);
}

public Optional<ECDSASignature> getSignature() {
return Optional.ofNullable(this.signature);
}

public List<byte[]> getInstructions() {
return this.instructions == null ? List.of() : this.instructions;
return Optional.ofNullable(signature);
}

@Override
public int hashCode() {
return Objects.hash(signature, instructions);
return Objects.hash(signature, unsignedBlob);
}

@Override
Expand All @@ -123,14 +108,9 @@ public boolean equals(Object o) {

@Override
public String toString() {
return String.format("%s {instructions=%s}", this.getClass().getSimpleName(),
getInstructions().stream().map(Hex::toHexString).collect(Collectors.toList())
return String.format("%s {blob=%s}",
this.getClass().getSimpleName(),
Hex.toHexString(unsignedBlob)
);
}

public Atom toSigned(ECDSASignature recoverable) {
requireNonNull(recoverable);

return new Atom(instructions, recoverable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.radixdlt.atommodel.validators.ValidatorParticle;
import com.radixdlt.atomos.RRIParticle;
import com.radixdlt.atomos.RriId;
import com.radixdlt.constraintmachine.ConstraintMachine;
import com.radixdlt.constraintmachine.Particle;
import com.radixdlt.identifiers.RRI;
import com.radixdlt.identifiers.RadixAddress;
Expand Down Expand Up @@ -91,7 +90,7 @@ public static Particle deserialize(ByteBuffer buf) throws DeserializeException {
}

public static byte[] serialize(Particle p) {
var buf = ByteBuffer.allocate(ConstraintMachine.DATA_MAX_SIZE);
var buf = ByteBuffer.allocate(1024);
buf.put(classToByte.get(p.getClass())); // substate type
if (p instanceof RRIParticle) {
serializeData((RRIParticle) p, buf);
Expand Down
Loading