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

[PAN-3096] privacy on mainnet [WIP] #61

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
c349c2e
WIP - need to fix AT
iikirilov Sep 29, 2019
aec2ab1
fix ATs
iikirilov Sep 30, 2019
1b1b41d
fix integration test and refactor private state root resolver
iikirilov Sep 30, 2019
71fab9f
refactor
iikirilov Sep 30, 2019
0bc50e1
address comments
iikirilov Oct 2, 2019
d4f9184
add test
iikirilov Oct 2, 2019
21ff2db
post-rebase fix get transaction hash
iikirilov Oct 18, 2019
6ca87b3
wip - add integration test
iikirilov Nov 8, 2019
4837b58
wip test
iikirilov Nov 13, 2019
9c355a8
fix call
iikirilov Nov 17, 2019
8749151
revert visibility of method for testing
iikirilov Nov 17, 2019
571fe1d
spotless
iikirilov Nov 17, 2019
ed7825e
add public and private enclave keys for test
iikirilov Nov 17, 2019
fc8f5b5
move reorg test to separate class
iikirilov Nov 17, 2019
bb1d496
privacy mainnet reorg tests
iikirilov Nov 17, 2019
c926bc8
fix flakiness
iikirilov Nov 17, 2019
8cdc741
fix javadoc
iikirilov Nov 17, 2019
6658695
post-rebase spotless
iikirilov Nov 17, 2019
12d5d28
post-rebase fixes
iikirilov Nov 17, 2019
5a12f0c
post-rebase fix AT
iikirilov Nov 18, 2019
7b4ddaf
fix cyclical block generation
iikirilov Nov 18, 2019
2248a8e
post-rebase fix
iikirilov Nov 22, 2019
2a0ae7a
address comments
iikirilov Nov 22, 2019
2870900
fix create private storage factory
iikirilov Nov 22, 2019
8573071
add key value pair and test
iikirilov Nov 24, 2019
8b05836
sketch
iikirilov Nov 24, 2019
3bccd48
refactor storage
iikirilov Nov 25, 2019
07e63f9
track-privacy-head
iikirilov Nov 25, 2019
88c631f
track-privacy-head
iikirilov Nov 25, 2019
173e891
track-privacy-head refactor to BlockAddedObserver
iikirilov Nov 25, 2019
1708e53
fix for blocks with multiple PMTs for the same privacy group
iikirilov Nov 25, 2019
a9a3ce3
fix ATs
iikirilov Nov 25, 2019
44a3eb8
read and update map in PrivacyPrecompiledContract
pinges Nov 26, 2019
68a19ee
refactor
iikirilov Nov 26, 2019
ebaf19c
refactor
iikirilov Nov 26, 2019
b072b25
refactor, add tests and fix nonce provider
iikirilov Nov 27, 2019
12d8a30
tweaks
iikirilov Nov 28, 2019
a662a68
spotless
iikirilov Nov 28, 2019
4633046
post-rebase fix
iikirilov Nov 28, 2019
38f2ba6
post-rebase fix
iikirilov Nov 28, 2019
eff05df
post-rebase fix
iikirilov Nov 28, 2019
f3d00a3
post-rebase fix
iikirilov Nov 29, 2019
df29ef3
post-rebase fix
iikirilov Dec 5, 2019
79bc4d9
post-rebase fix
iikirilov Jan 6, 2020
72818d3
compile warning fix
iikirilov Jan 6, 2020
7de7a6f
IT fix
iikirilov Jan 6, 2020
6a792e5
address comments
iikirilov Jan 6, 2020
2073833
remove unused variable
iikirilov Jan 6, 2020
c5af45b
remove unused import
iikirilov Jan 6, 2020
1a9961a
fix import
iikirilov Jan 6, 2020
47af58d
address comments
iikirilov Jan 7, 2020
627ccd3
post-rebase fix
iikirilov Jan 7, 2020
8af4f6d
fix unused variable
iikirilov Jan 7, 2020
ecddf61
refactor reorg test
iikirilov Jan 8, 2020
3bf0040
extract constants to local variable
iikirilov Jan 8, 2020
85d9a3f
fix ATs
iikirilov Jan 8, 2020
33321e6
remove unused field
iikirilov Jan 8, 2020
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
Prev Previous commit
Next Next commit
track-privacy-head
Signed-off-by: Ivaylo Kirilov <iikirilov@gmail.com>
  • Loading branch information
iikirilov committed Jan 9, 2020
commit 07e63f90a4ee596e081068f1e49dd418a8425be0
40 changes: 28 additions & 12 deletions besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.Restriction;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateGroupIdToLatestBlockwithTransactionMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
Expand Down Expand Up @@ -168,9 +169,6 @@ public void privacyGroupHeadIsTracked() {
final ProtocolContext<?> protocolContext = besuController.getProtocolContext();
final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain();
final PrivateStateStorage privateStateStorage = privacyParameters.getPrivateStateStorage();
final BytesValue privacyGroupId =
BytesValue.fromHexString(
"0xfd3d679c20d01667629ab31c47efd69b1aca3ae3eafe5096a7cdb7948310baa6");

final Block firstBlock =
gen.block(
Expand All @@ -190,21 +188,32 @@ public void privacyGroupHeadIsTracked() {

appendBlock(besuController, blockchain, protocolContext, firstBlock);

final PrivateGroupIdToLatestBlockwithTransactionMap expected =
new PrivateGroupIdToLatestBlockwithTransactionMap(
Collections.singletonMap(
Bytes32.fromHexString(
"0xf250d523ae9164722b06ca25cfa2a7f3c45df96b09e215236f886c876f715bfa"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constant?

firstBlock.getHash()));

assertThat(
privateStateStorage.getPrivacyGroupHead(
blockchain.getGenesisBlock().getHash(), Bytes32.wrap(privacyGroupId)))
privateStateStorage.getPrivacyGroupToLatestBlockWithTransactionMap(
blockchain.getGenesisBlock().getHash()))
.isEmpty();
assertThat(
privateStateStorage.getPrivacyGroupHead(
firstBlock.getHash(), Bytes32.wrap(privacyGroupId)))
.contains(firstBlock.getHash());
privateStateStorage.getPrivacyGroupToLatestBlockWithTransactionMap(
firstBlock.getHash()))
.isNotEmpty();
assertThat(
privateStateStorage.getPrivacyGroupToLatestBlockWithTransactionMap(
firstBlock.getHash()))
.contains(expected);

final Block secondBlock =
gen.block(
new BlockDataGenerator.BlockOptions()
.setBlockNumber(2)
.setParentHash(firstBlock.getHeader().getHash())
.addTransaction(generateMarker(getEnclaveKey(enclave.clientUrl())))
.hasTransactions(false)
.hasOmmers(false)
.setReceiptsRoot(
Hash.fromHexString(
Expand All @@ -215,10 +224,17 @@ public void privacyGroupHeadIsTracked() {
Hash.fromHexString(
"0x35c315ee7d272e5b612d454ee87c948657310ab33208b57122f8d0525e91f35e")));

appendBlock(besuController, blockchain, protocolContext, secondBlock);

assertThat(
privateStateStorage.getPrivacyGroupToLatestBlockWithTransactionMap(
secondBlock.getHash()))
.isNotEmpty();

assertThat(
privateStateStorage.getPrivacyGroupHead(
secondBlock.getHash(), Bytes32.wrap(privacyGroupId)))
.contains(firstBlock.getHash());
privateStateStorage.getPrivacyGroupToLatestBlockWithTransactionMap(
firstBlock.getHash()))
.contains(expected);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,33 @@

import static org.apache.logging.log4j.LogManager.getLogger;

import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.types.ReceiveRequest;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator;
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator;
import org.hyperledger.besu.ethereum.mainnet.BlockProcessor;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;

import org.hyperledger.besu.ethereum.privacy.storage.PrivateGroupIdToLatestBlockwithTransactionMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.util.bytes.Bytes32;
import org.hyperledger.besu.util.bytes.BytesValue;
import org.hyperledger.besu.util.bytes.BytesValues;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

import com.google.common.collect.Maps;
import org.apache.logging.log4j.Logger;

public class MainnetBlockValidator<C> implements BlockValidator<C> {
Expand All @@ -40,14 +54,30 @@ public class MainnetBlockValidator<C> implements BlockValidator<C> {
private final BlockBodyValidator<C> blockBodyValidator;

private final BlockProcessor blockProcessor;
private PrivacyParameters privacyParameters;

private PrivateStateStorage privateStateStorage;
private Address address;
private Enclave enclave;

public MainnetBlockValidator(
final BlockHeaderValidator<C> blockHeaderValidator,
final BlockBodyValidator<C> blockBodyValidator,
final BlockProcessor blockProcessor) {
final BlockProcessor blockProcessor,
final PrivacyParameters privacyParameters) {
this.blockHeaderValidator = blockHeaderValidator;
this.blockBodyValidator = blockBodyValidator;
this.blockProcessor = blockProcessor;
this.privacyParameters = privacyParameters;
setUpForPrivacy(privacyParameters);
}

private void setUpForPrivacy(final PrivacyParameters privacyParameters) {
if (privacyParameters.isEnabled()) {
privateStateStorage = privacyParameters.getPrivateStateStorage();
address = Address.privacyPrecompiled(privacyParameters.getPrivacyAddress());
enclave = new Enclave(privacyParameters.getEnclaveUri());
}
}

@Override
Expand Down Expand Up @@ -90,9 +120,33 @@ public Optional<BlockProcessingOutputs> validateAndProcessBlock(
return Optional.empty();
}

// get all groups
// for each group check if there is a PMT for that group in this block and update the head
// for all other groups copy the head from the parent of this block being processed
if (privacyParameters.isEnabled()) {
// get all groups
final HashMap<Bytes32, Hash> privacyGroupToLatestBlockWithTransactionMap =
Maps.newHashMap(
privateStateStorage
.getPrivacyGroupToLatestBlockWithTransactionMap(block.getHeader().getParentHash())
.map(PrivateGroupIdToLatestBlockwithTransactionMap::getMap)
.orElse(Collections.emptyMap()));
block.getBody().getTransactions().stream()
.filter(t -> t.getTo().isPresent() && t.getTo().get().equals(address))
.forEach(
t -> {
final String key = BytesValues.asBase64String(t.getData().get());
final ReceiveResponse receiveResponse = enclave.receive(new ReceiveRequest(key));
final BytesValue privacyGroupId =
BytesValues.fromBase64(receiveResponse.getPrivacyGroupId());
privacyGroupToLatestBlockWithTransactionMap.put(
Bytes32.wrap(privacyGroupId), block.getHash());
});
privateStateStorage
.updater()
.putPrivacyGroupToLatestBlockWithTransactionMap(
block.getHash(),
new PrivateGroupIdToLatestBlockwithTransactionMap(
privacyGroupToLatestBlockWithTransactionMap))
.commit();
}

final List<TransactionReceipt> receipts = result.getReceipts();
if (!blockBodyValidator.validateBody(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ public ProtocolSpec<T> build(final ProtocolSchedule<T> protocolSchedule) {
miningBeneficiaryCalculator,
skipZeroBlockRewards);
final BlockValidator<T> blockValidator =
blockValidatorBuilder.apply(blockHeaderValidator, blockBodyValidator, blockProcessor);
blockValidatorBuilder.apply(
blockHeaderValidator, blockBodyValidator, blockProcessor, privacyParameters);
final BlockImporter<T> blockImporter = blockImporterBuilder.apply(blockValidator);
return new ProtocolSpec<>(
name,
Expand Down Expand Up @@ -372,7 +373,8 @@ public interface BlockValidatorBuilder<T> {
BlockValidator<T> apply(
BlockHeaderValidator<T> blockHeaderValidator,
BlockBodyValidator<T> blockBodyValidator,
BlockProcessor blockProcessor);
BlockProcessor blockProcessor,
PrivacyParameters privacyParameters);
}

public interface BlockImporterBuilder<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,54 @@
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.util.bytes.Bytes32;

import java.util.Objects;

public class PrivateGroupIdBlockHashMapEntry {
private final Bytes32 privacyGroup;
private final Hash blockHash;
private final Bytes32 privacyGroup;
private final Hash blockHash;

public PrivateGroupIdBlockHashMapEntry(final Bytes32 privacyGroup, final Hash blockHash) {
this.privacyGroup = privacyGroup;
this.blockHash = blockHash;
}

public Hash getBlockHash() {
return blockHash;
}

public PrivateGroupIdBlockHashMapEntry(final Bytes32 privacyGroup, final Hash blockHash) {
this.privacyGroup = privacyGroup;
this.blockHash = blockHash;
}
public Bytes32 getPrivacyGroup() {
return privacyGroup;
}

public Hash getBlockHash() {
return blockHash;
}
public void writeTo(final RLPOutput out) {
out.startList();

public Bytes32 getPrivacyGroup() {
return privacyGroup;
}
out.writeBytesValue(privacyGroup);
out.writeBytesValue(blockHash);

public void writeTo(final RLPOutput out) {
out.startList();
out.endList();
}

out.writeBytesValue(privacyGroup);
out.writeBytesValue(blockHash);
public static PrivateGroupIdBlockHashMapEntry readFrom(final RLPInput input) {
input.enterList();

out.endList();
}
final PrivateGroupIdBlockHashMapEntry privateTransactionMetadata =
new PrivateGroupIdBlockHashMapEntry(input.readBytes32(), Hash.wrap(input.readBytes32()));

public static PrivateGroupIdBlockHashMapEntry readFrom(final RLPInput input) {
input.enterList();
input.leaveList();
return privateTransactionMetadata;
}

final PrivateGroupIdBlockHashMapEntry privateTransactionMetadata =
new PrivateGroupIdBlockHashMapEntry(input.readBytes32(), Hash.wrap(input.readBytes32()));
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final PrivateGroupIdBlockHashMapEntry that = (PrivateGroupIdBlockHashMapEntry) o;
return privacyGroup.equals(that.privacyGroup) && blockHash.equals(that.blockHash);
}

input.leaveList();
return privateTransactionMetadata;
}
@Override
public int hashCode() {
return Objects.hash(privacyGroup, blockHash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,58 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class PrivateGroupIdToLatestBlockwithTransactionMap {
private final Map<Bytes32, Hash> map;
private final Map<Bytes32, Hash> map;

public final static PrivateGroupIdToLatestBlockwithTransactionMap EMPTY = new PrivateGroupIdToLatestBlockwithTransactionMap(new HashMap<>());
public static final PrivateGroupIdToLatestBlockwithTransactionMap EMPTY =
new PrivateGroupIdToLatestBlockwithTransactionMap(new HashMap<>());

public PrivateGroupIdToLatestBlockwithTransactionMap(final Map<Bytes32, Hash> map) {
this.map= map;
}
public PrivateGroupIdToLatestBlockwithTransactionMap(final Map<Bytes32, Hash> map) {
this.map = map;
}

public Map<Bytes32, Hash> getMap() {
return map;
}
public Map<Bytes32, Hash> getMap() {
return map;
}

public void writeTo(final RLPOutput out) {
out.startList();
public void writeTo(final RLPOutput out) {
out.startList();

map.entrySet().stream().forEach(e -> {
out.writeBytesValue(e.getKey());
out.writeBytesValue(e.getValue());
});
map.entrySet()
.forEach(
e -> {
out.startList();
out.writeBytesValue(e.getKey());
out.writeBytesValue(e.getValue());
out.endList();
});

out.endList();
}
out.endList();
}

public static PrivateGroupIdToLatestBlockwithTransactionMap readFrom(final RLPInput input) {
final List<PrivateGroupIdBlockHashMapEntry> entries = input.readList(PrivateGroupIdBlockHashMapEntry::readFrom);
public static PrivateGroupIdToLatestBlockwithTransactionMap readFrom(final RLPInput input) {
final List<PrivateGroupIdBlockHashMapEntry> entries =
input.readList(PrivateGroupIdBlockHashMapEntry::readFrom);

final HashMap<Bytes32, Hash> map = new HashMap<>();
entries.stream().forEach(e -> map.put(e.getPrivacyGroup(), e.getBlockHash()));
final HashMap<Bytes32, Hash> map = new HashMap<>();
entries.stream().forEach(e -> map.put(e.getPrivacyGroup(), e.getBlockHash()));

return new PrivateGroupIdToLatestBlockwithTransactionMap(map);
}
return new PrivateGroupIdToLatestBlockwithTransactionMap(map);
}

@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final PrivateGroupIdToLatestBlockwithTransactionMap that =
(PrivateGroupIdToLatestBlockwithTransactionMap) o;
return map.equals(that.map);
}

@Override
public int hashCode() {
return Objects.hash(map);
}
}
Loading