Skip to content

Commit

Permalink
Flexible Privacy Groups feature - Support to Tessera's EC encryptor (#…
Browse files Browse the repository at this point in the history
…4282)

    modified flexibleutil so it works with dynamic byte arrays, some logs to remove
    smart contracts adapted, changed bytecodes
    solidity contracts changed so they use bytes instead of bytes32
    modified flexibleutil to support ec keys
    flexible privacy tests adapted

Signed-off-by: Miguel Rojo <[email protected]>
Signed-off-by: Miguel Angel Rojo <[email protected]>
Co-authored-by: Sally MacFarlane <[email protected]>
  • Loading branch information
freemanzMrojo and macfarla authored Oct 7, 2022
1 parent 9bc210b commit 2bcd2a7
Show file tree
Hide file tree
Showing 24 changed files with 374 additions and 177 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog
## 22.10.0-RC2

### Breaking Changes
- Flexible Privacy Groups (early access) support to Tessera's EC encryptor (contracts modified) [#4282](https://github.com/hyperledger/besu/pull/4282)
* Before this change, the `bytes32` type was used for the enclave public keys, just supporting encryptors with public keys of that length (like the default NaCl)
* For the EC encryptor, the encoded public key length is 91

### Additions and Improvements

### Bug Fixes
Expand Down Expand Up @@ -42,7 +47,6 @@ https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.5/besu-22.7.5.t

## 22.7.4


### Bug Fixes
- Remove records that track transactions by sender when they are empty to same memory in the transaction pool [#4415](https://github.com/hyperledger/besu/pull/4415)
- Add Toml configuration file support for _--Xplugin-rocksdb-high-spec-enabled_ flag [#4438](https://github.com/hyperledger/besu/pull/4438)
Expand All @@ -51,7 +55,6 @@ https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.5/besu-22.7.5.t
- https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.4/besu-22.7.4.zip / sha256: 4f2a0c20bee7f266ec1dcb45fa90ae1ca42f4b22e9b21a601b7705357259aea9
- https://hyperledger.jfrog.io/hyperledger/besu-binaries/besu/22.7.4/besu-22.7.4.tar.gz / sha256: a60efc4d515ac94710bbc6d61a24f409b03fcfc02323bee2a2d75c883fc99dce


## 22.7.3

### Additions and Improvements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccount;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.EnclaveType;

Expand Down Expand Up @@ -233,8 +234,11 @@ public PrivacyNode createFlexiblePrivacyGroupEnabledMinerNode(
final BesuNodeConfigurationBuilder besuNodeConfigurationBuilder =
new BesuNodeConfigurationBuilder();
if (multiTenancyEnabled) {
besuNodeConfigurationBuilder.jsonRpcAuthenticationConfiguration(
"authentication/auth_priv.toml");
final String authPrivTomlPath =
EnclaveEncryptorType.EC.equals(privacyAccount.getEnclaveEncryptorType())
? "authentication/auth_priv_ec_pubkey.toml"
: "authentication/auth_priv.toml";
besuNodeConfigurationBuilder.jsonRpcAuthenticationConfiguration(authPrivTomlPath);
}
return create(
new PrivacyNodeConfiguration(
Expand All @@ -252,7 +256,9 @@ public PrivacyNode createFlexiblePrivacyGroupEnabledMinerNode(
.keyFilePath(privacyAccount.getPrivateKeyPath())
.build(),
new EnclaveKeyConfiguration(
privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths())),
privacyAccount.getEnclaveKeyPaths(),
privacyAccount.getEnclavePrivateKeyPaths(),
privacyAccount.getEnclaveEncryptorType())),
enclaveType,
containerNetwork);
}
Expand All @@ -279,7 +285,9 @@ public PrivacyNode createFlexiblePrivacyGroupEnabledNode(
.webSocketEnabled()
.build(),
new EnclaveKeyConfiguration(
privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths())),
privacyAccount.getEnclaveKeyPaths(),
privacyAccount.getEnclavePrivateKeyPaths(),
privacyAccount.getEnclaveEncryptorType())),
enclaveType,
containerNetwork);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
Expand All @@ -41,6 +40,14 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.Utils;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicBytes;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.besu.Besu;
Expand Down Expand Up @@ -102,8 +109,6 @@ public static class GetPrivacyPrecompileAddressResponse extends Response<Address
public static class GetPrivateTransactionResponse
extends Response<PrivateTransactionGroupResponse> {}

public static class JsonRpcSuccessResponseResponse extends Response<String> {}

public static class CreatePrivacyGroupResponse extends Response<String> {}

public static class DeletePrivacyGroupResponse extends Response<String> {}
Expand Down Expand Up @@ -232,7 +237,13 @@ public String privxRemoveFromPrivacyGroup(
}

private Bytes encodeRemoveFromGroupFunctionCall(final Bytes toRemove) {
return Bytes.concatenate(FlexibleGroupManagement.REMOVE_PARTICIPANT_METHOD_SIGNATURE, toRemove);
final Function function =
new Function(
"removeParticipant",
Arrays.asList(new DynamicBytes(toRemove.toArrayUnsafe())),
Arrays.asList(new TypeReference<Bool>() {}));

return Bytes.fromHexString(FunctionEncoder.encode(function));
}

public String privxLockPrivacyGroup(
Expand Down Expand Up @@ -588,29 +599,19 @@ public String getTransactionHash() {
}

private Bytes encodeAddToGroupFunctionCall(final List<Bytes> participants) {
return Bytes.concatenate(
FlexibleGroupManagement.ADD_PARTICIPANTS_METHOD_SIGNATURE, encodeList(participants));
}

private Bytes encodeList(final List<Bytes> participants) {
final Bytes dynamicParameterOffset = encodeLong(32);
final Bytes length = encodeLong(participants.size());
return Bytes.concatenate(
dynamicParameterOffset,
length,
Bytes.fromHexString(
participants.stream()
.map(Bytes::toUnprefixedHexString)
.collect(Collectors.joining(""))));
}

// long to uint256, 8 bytes big endian, so left padded by 24 bytes
private static Bytes encodeLong(final long l) {
checkArgument(l >= 0, "Unsigned value must be positive");
final byte[] longBytes = new byte[8];
for (int i = 0; i < 8; i++) {
longBytes[i] = (byte) ((l >> ((7 - i) * 8)) & 0xFF);
}
return Bytes.concatenate(Bytes.wrap(new byte[24]), Bytes.wrap(longBytes));
final Function function =
new Function(
"addParticipants",
Arrays.asList(
new DynamicArray<>(
DynamicBytes.class,
Utils.typeMap(
participants.stream()
.map(Bytes::toArrayUnsafe)
.collect(Collectors.toList()),
DynamicBytes.class))),
Collections.emptyList());

return Bytes.fromHexString(FunctionEncoder.encode(function));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import static org.junit.runners.Parameterized.Parameters;

import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions;
Expand Down Expand Up @@ -53,14 +56,21 @@
public class FlexiblePrivacyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase {

private final EnclaveType enclaveType;
private final EnclaveEncryptorType enclaveEncryptorType;

public FlexiblePrivacyAcceptanceTest(final EnclaveType enclaveType) {
public FlexiblePrivacyAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) {
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
}

@Parameters(name = "{0}")
public static Collection<EnclaveType> enclaveTypes() {
return EnclaveType.valuesForTests();
@Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}

private PrivacyNode alice;
Expand All @@ -82,21 +92,21 @@ public void setUp() throws Exception {
alice =
privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode(
"node1",
PrivacyAccountResolver.ALICE.resolve(EnclaveEncryptorType.NACL),
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
bob =
privacyBesu.createFlexiblePrivacyGroupEnabledNode(
"node2",
PrivacyAccountResolver.BOB.resolve(EnclaveEncryptorType.NACL),
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
charlie =
privacyBesu.createFlexiblePrivacyGroupEnabledNode(
"node3",
PrivacyAccountResolver.CHARLIE.resolve(EnclaveEncryptorType.NACL),
PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.ExpectValidFlexiblePrivacyGroupCreated;
Expand All @@ -32,6 +31,10 @@
import java.util.stream.Collectors;

import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.Utils;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicBytes;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
Expand Down Expand Up @@ -79,8 +82,7 @@ protected String createFlexiblePrivacyGroup(
final String commitmentHash =
callGetParticipantsMethodAndReturnCommitmentHash(privacyGroupId, groupCreator, privateFrom);
final PrivateTransactionReceipt expectedReceipt =
buildExpectedAddMemberTransactionReceipt(
privacyGroupId, groupCreator, addresses.toArray(new String[] {}));
buildExpectedAddMemberTransactionReceipt(privacyGroupId, groupCreator, addresses);

for (final PrivacyNode member : members) {
member.verify(
Expand All @@ -103,7 +105,7 @@ protected String callGetParticipantsMethodAndReturnCommitmentHash(
}

protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt(
final String privacyGroupId, final PrivacyNode groupCreator, final String[] members) {
final String privacyGroupId, final PrivacyNode groupCreator, final List<String> members) {
return buildExpectedAddMemberTransactionReceipt(
privacyGroupId, groupCreator, groupCreator.getEnclaveKey(), members);
}
Expand All @@ -112,18 +114,26 @@ protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt(
final String privacyGroupId,
final PrivacyNode groupCreator,
final String privateFrom,
final String[] members) {
final List<String> members) {

final StringBuilder output = new StringBuilder();
// hex prefix
output.append("0x");
// Dynamic array offset
output.append("0000000000000000000000000000000000000000000000000000000000000020");
// Length of the array (with padded zeros to the left)
output.append(Quantity.longToPaddedHex(members.length, 32).substring(2));
// Each member enclave key converted from Base64 to bytes
for (final String member : members) {
output.append(Bytes.fromBase64String(member).toUnprefixedHexString());
}

final String encodedParameters =
FunctionEncoder.encode(
"",
Arrays.asList(
new DynamicArray<>(
DynamicBytes.class,
Utils.typeMap(
members.stream()
.map(Bytes::fromBase64String)
.map(Bytes::toArrayUnsafe)
.collect(Collectors.toList()),
DynamicBytes.class))));

output.append(encodedParameters);

return new PrivateTransactionReceipt(
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public class PrivacyGroupTest extends AcceptanceTestBase {

private static final String RAW_FIRST_PARTICIPANT = "0x5aa68ac0";
private static final String RAW_ADD_PARTICIPANT =
"0xb4926e25000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000012a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b";
"0x965a25ef00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b";
private static final String RAW_REMOVE_PARTICIPANT =
"0xfd0177972a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b";
"0x1f52a8ee000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b";
private static final String RAW_LOCK = "0xf83d08ba";
private static final String RAW_UNLOCK = "0xa69df4b5";
private static final String RAW_CAN_EXECUTE = "0x78b90337";
Expand All @@ -73,28 +73,28 @@ public void rlp() throws Exception {
.validTransactionReceipt(contractAddress)
.verify(defaultPrivacyGroupManagementContract);
// 0x0b0235be
assertThat(RAW_FIRST_PARTICIPANT)
.isEqualTo(defaultPrivacyGroupManagementContract.getParticipants().encodeFunctionCall());
assertThat(defaultPrivacyGroupManagementContract.getParticipants().encodeFunctionCall())
.isEqualTo(RAW_FIRST_PARTICIPANT);
// 0xf744b089
assertThat(RAW_ADD_PARTICIPANT)
.isEqualTo(
assertThat(
defaultPrivacyGroupManagementContract
.addParticipants(Collections.singletonList(secondParticipant.raw()))
.encodeFunctionCall());
.encodeFunctionCall())
.isEqualTo(RAW_ADD_PARTICIPANT);
// 0xf744b089
assertThat(RAW_REMOVE_PARTICIPANT)
.isEqualTo(
assertThat(
defaultPrivacyGroupManagementContract
.removeParticipant(secondParticipant.raw())
.encodeFunctionCall());
assertThat(RAW_LOCK)
.isEqualTo(defaultPrivacyGroupManagementContract.lock().encodeFunctionCall());
assertThat(RAW_UNLOCK)
.isEqualTo(defaultPrivacyGroupManagementContract.unlock().encodeFunctionCall());
assertThat(RAW_CAN_EXECUTE)
.isEqualTo(defaultPrivacyGroupManagementContract.canExecute().encodeFunctionCall());
assertThat(RAW_GET_VERSION)
.isEqualTo(defaultPrivacyGroupManagementContract.getVersion().encodeFunctionCall());
.encodeFunctionCall())
.isEqualTo(RAW_REMOVE_PARTICIPANT);
assertThat(defaultPrivacyGroupManagementContract.lock().encodeFunctionCall())
.isEqualTo(RAW_LOCK);
assertThat(defaultPrivacyGroupManagementContract.unlock().encodeFunctionCall())
.isEqualTo(RAW_UNLOCK);
assertThat(defaultPrivacyGroupManagementContract.canExecute().encodeFunctionCall())
.isEqualTo(RAW_CAN_EXECUTE);
assertThat(defaultPrivacyGroupManagementContract.getVersion().encodeFunctionCall())
.isEqualTo(RAW_GET_VERSION);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class PrivacyProxyTest extends AcceptanceTestBase {

private static final String RAW_GET_PARTICIPANTS = "0x5aa68ac0";
private static final String RAW_ADD_PARTICIPANT =
"0xb4926e2500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001f772b2ee55f016431cefe724a05814324bb96e9afdb73e338665a693d4653678";
"0x965a25ef0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020f772b2ee55f016431cefe724a05814324bb96e9afdb73e338665a693d4653678";

private BesuNode minerNode;
private DefaultFlexiblePrivacyGroupManagementContract
Expand All @@ -76,14 +76,14 @@ public void rlp() throws Exception {
contractVerifier
.validTransactionReceipt(flexiblePrivacyGroupManagementProxy.getContractAddress())
.verify(flexiblePrivacyGroupManagementProxy);
assertThat(RAW_GET_PARTICIPANTS)
.isEqualTo(flexiblePrivacyGroupManagementProxy.getParticipants().encodeFunctionCall());
assertThat(flexiblePrivacyGroupManagementProxy.getParticipants().encodeFunctionCall())
.isEqualTo(RAW_GET_PARTICIPANTS);

assertThat(RAW_ADD_PARTICIPANT)
.isEqualTo(
assertThat(
flexiblePrivacyGroupManagementProxy
.addParticipants(List.of(firstParticipant.raw()))
.encodeFunctionCall());
.encodeFunctionCall())
.isEqualTo(RAW_ADD_PARTICIPANT);
}

@Test
Expand Down
Loading

0 comments on commit 2bcd2a7

Please sign in to comment.