Skip to content

Commit

Permalink
SSZ - encoding (hyperledger#4979)
Browse files Browse the repository at this point in the history
* Adding preliminary SSZ encoding/decoding of Transaction Network Payload

* Adding ssz snapshot jar, delete it before moving to main

also removing licenses....

Signed-off-by: Jiri Peinlich <jiri.peinlich@gmail.com>
(cherry picked from commit bd147e0)
(cherry picked from commit 4e19926eb7b85fda7d40a0f565d46c0d9b27075d)
  • Loading branch information
gezero authored and jflo committed May 16, 2023
1 parent c85841d commit b3aa6ad
Show file tree
Hide file tree
Showing 18 changed files with 1,188 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;

public class IbftExtraDataEncoderTest {
public class IbftExtraDataRLPEncoderTest {

private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.plugin.data.TransactionType;

Expand Down Expand Up @@ -99,9 +99,7 @@ public TransactionPendingResult(final Transaction transaction) {
this.input = transaction.getPayload().toString();
this.nonce = Quantity.create(transaction.getNonce());
this.publicKey = transaction.getPublicKey().orElse(null);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
transaction.writeTo(out);
this.raw = out.encoded().toString();
this.raw = TransactionEncoder.encodeOpaqueBytes(transaction).toString();
this.to = transaction.getTo().map(Address::toHexString).orElse(null);
this.type =
transactionType.equals(TransactionType.FRONTIER)
Expand Down
22 changes: 22 additions & 0 deletions ethereum/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,31 @@ jar {
}
}

//repositories {
// mavenLocal()
//}
//
//sourceControl {
// gitRepository("https://github.com/apache/incubator-tuweni.git") {
// producesModule("org.apache.tuweni:ssz")
// }
//}
//
//
//includeBuild('tuweni-library') {
// dependencySubstitution {
// substitute module('org.apache.tuweni:tuweni-ssz') using project(':')
// }
//}


dependencies {
api 'org.slf4j:slf4j-api'

annotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess'

// implementation fileTree(dir: '/Users/jiripeinlich/consensys/src/incubator-tuweni/ssz/build/classes', include: '*.class')

implementation project(':config')
implementation project(':crypto:algorithms')
implementation project(':datatypes')
Expand All @@ -57,6 +77,8 @@ dependencies {
implementation 'org.apache.tuweni:tuweni-concurrent'
implementation 'org.apache.tuweni:tuweni-units'
implementation 'org.apache.tuweni:tuweni-rlp'
implementation 'org.apache.tuweni:tuweni-ssz'
implementation files('libs/tuweni-ssz-2.4.0-SNAPSHOT.jar')
implementation 'org.hyperledger.besu:bls12-381'
implementation 'org.immutables:value-annotations'

Expand Down
Binary file added ethereum/core/libs/tuweni-ssz-2.4.0-SNAPSHOT.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
package org.hyperledger.besu.ethereum.core;

import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.apache.tuweni.bytes.Bytes;

Expand Down Expand Up @@ -57,18 +60,26 @@ public void writeTo(final RLPOutput out) {
out.startList();

header.writeTo(out);
body.writeTo(out);
out.writeList(body.getTransactions(), TransactionEncoder::encodeOpaqueBytes);
out.writeList(body.getOmmers(), BlockHeader::writeTo);
body.getWithdrawals().ifPresent(withdrawals -> out.writeList(withdrawals, Withdrawal::writeTo));
body.getDeposits().ifPresent(deposits -> out.writeList(deposits, Deposit::writeTo));

out.endList();
}

public static Block readFrom(final RLPInput in, final BlockHeaderFunctions hashFunction) {
in.enterList();
final BlockHeader header = BlockHeader.readFrom(in, hashFunction);
final BlockBody body = BlockBody.readFrom(in, hashFunction);
final List<Transaction> transactions = in.readList(Transaction::readFrom);
final List<BlockHeader> ommers = in.readList(rlp -> BlockHeader.readFrom(rlp, hashFunction));
final Optional<List<Withdrawal>> withdrawals =
in.isEndOfCurrentList() ? Optional.empty() : Optional.of(in.readList(Withdrawal::readFrom));
final Optional<List<Deposit>> deposits =
in.isEndOfCurrentList() ? Optional.empty() : Optional.of(in.readList(Deposit::readFrom));
in.leaveList();

return new Block(header, body);
return new Block(header, new BlockBody(transactions, ommers, withdrawals, deposits));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.core;

import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;

Expand All @@ -28,9 +29,7 @@ public class BlockBody implements org.hyperledger.besu.plugin.data.BlockBody {
new BlockBody(Collections.emptyList(), Collections.emptyList());
/**
* Adding a new field with a corresponding root hash in the block header will require a change in
* {@link org.hyperledger.besu.ethereum.eth.manager.task.GetBodiesFromPeerTask.BodyIdentifier}
* Also requires adding the new field to the constructor used in the {@link
* org.hyperledger.besu.ethereum.util.RawBlockIterator }
* {@link org.hyperledger.besu.ethereum.eth.manager.task.GetBodiesFromPeerTask.BodyIdentifier }
*/
private final List<Transaction> transactions;

Expand Down Expand Up @@ -101,35 +100,23 @@ public Optional<List<Deposit>> getDeposits() {
*
* @param output Output to write to
*/
public void writeWrappedBodyTo(final RLPOutput output) {
public void writeTo(final RLPOutput output) {
output.startList();
writeTo(output);
output.endList();
}

public void writeTo(final RLPOutput output) {
output.writeList(getTransactions(), Transaction::writeTo);
output.writeList(getTransactions(), TransactionEncoder::encodeOpaqueBytes);
output.writeList(getOmmers(), BlockHeader::writeTo);
withdrawals.ifPresent(withdrawals -> output.writeList(withdrawals, Withdrawal::writeTo));
deposits.ifPresent(deposits -> output.writeList(deposits, Deposit::writeTo));

output.endList();
}

public static BlockBody readWrappedBodyFrom(
public static BlockBody readFrom(
final RLPInput input, final BlockHeaderFunctions blockHeaderFunctions) {
return readWrappedBodyFrom(input, blockHeaderFunctions, false);
return readFrom(input, blockHeaderFunctions, false);
}

/**
* Read all fields from the block body expecting a list wrapping them An example of valid body
* structure that this method would be able to read is: [[txs],[ommers],[withdrawals]] This is
* used for decoding list of bodies
*
* @param input The RLP-encoded input
* @param blockHeaderFunctions The block header functions used for parsing block headers
* @param allowEmptyBody A flag indicating whether an empty body is allowed
* @return the decoded BlockBody from the RLP
*/
public static BlockBody readWrappedBodyFrom(
public static BlockBody readFrom(
final RLPInput input,
final BlockHeaderFunctions blockHeaderFunctions,
final boolean allowEmptyBody) {
Expand All @@ -139,33 +126,21 @@ public static BlockBody readWrappedBodyFrom(
input.leaveList();
return empty();
}
final BlockBody body = readFrom(input, blockHeaderFunctions);
// TODO: Support multiple hard fork transaction formats.
final BlockBody body =
new BlockBody(
input.readList(Transaction::readFrom),
input.readList(rlp -> BlockHeader.readFrom(rlp, blockHeaderFunctions)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Withdrawal::readFrom)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Deposit::readFrom)));
input.leaveList();
return body;
}

/**
* Read all fields from the block body expecting no list wrapping them. An example of a valid body
* would be: [txs],[ommers],[withdrawals],[deposits] this method is called directly when importing
* a single block
*
* @param input The RLP-encoded input
* @param blockHeaderFunctions The block header functions used for parsing block headers
* @return the BlockBody decoded from the RLP
*/
public static BlockBody readFrom(
final RLPInput input, final BlockHeaderFunctions blockHeaderFunctions) {
return new BlockBody(
input.readList(Transaction::readFrom),
input.readList(rlp -> BlockHeader.readFrom(rlp, blockHeaderFunctions)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Withdrawal::readFrom)),
input.isEndOfCurrentList()
? Optional.empty()
: Optional.of(input.readList(Deposit::readFrom)));
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
Expand Down
Loading

0 comments on commit b3aa6ad

Please sign in to comment.