Flexible Privacy Groups feature - Support to Tessera's EC encryptor (#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 <miguelangel.rojofernandez@mastercard.com>
Signed-off-by: Miguel Angel Rojo <miguelangel.rojofernandez@mastercard.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/4499/head
Miguel Angel Rojo 2 years ago committed by GitHub
parent 9bc210b2d4
commit 2bcd2a7eec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      CHANGELOG.md
  2. 16
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java
  3. 57
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java
  4. 24
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTest.java
  5. 36
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/FlexiblePrivacyAcceptanceTestBase.java
  6. 36
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyGroupTest.java
  7. 12
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/contracts/PrivacyProxyTest.java
  8. 23
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/multitenancy/FlexibleMultiTenancyAcceptanceTest.java
  9. 19
      acceptance-tests/tests/src/test/resources/authentication/auth_priv_ec_pubkey.toml
  10. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyController.java
  11. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyGroupContract.java
  12. 50
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/FlexibleUtil.java
  13. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/group/FlexibleGroupManagement.java
  14. 9
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java
  15. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/FlexiblePrivacyControllerTest.java
  16. 87
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/FlexibleUtilTest.java
  17. 26
      privacy-contracts/src/main/java/org/hyperledger/besu/privacy/contracts/generated/DefaultFlexiblePrivacyGroupManagementContract.java
  18. 13
      privacy-contracts/src/main/java/org/hyperledger/besu/privacy/contracts/generated/FlexiblePrivacyGroupManagementInterface.java
  19. 19
      privacy-contracts/src/main/java/org/hyperledger/besu/privacy/contracts/generated/FlexiblePrivacyGroupManagementProxy.java
  20. 33
      privacy-contracts/src/main/solidity/DefaultFlexiblePrivacyGroupManagementContract.sol
  21. 10
      privacy-contracts/src/main/solidity/FlexiblePrivacyGroupManagementInterface.sol
  22. 18
      privacy-contracts/src/main/solidity/FlexiblePrivacyGroupManagementProxy.sol
  23. 2
      privacy-contracts/src/main/solidity/generateWrappers.sh
  24. 4
      testutil/src/main/java/org/hyperledger/enclave/testutil/EnclaveKeyConfiguration.java

@ -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
@ -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)
@ -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

@ -19,6 +19,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfigur
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;
@ -233,8 +234,11 @@ public class PrivacyNodeFactory {
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(
@ -252,7 +256,9 @@ public class PrivacyNodeFactory {
.keyFilePath(privacyAccount.getPrivateKeyPath())
.build(),
new EnclaveKeyConfiguration(
privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths())),
privacyAccount.getEnclaveKeyPaths(),
privacyAccount.getEnclavePrivateKeyPaths(),
privacyAccount.getEnclaveEncryptorType())),
enclaveType,
containerNetwork);
}
@ -279,7 +285,9 @@ public class PrivacyNodeFactory {
.webSocketEnabled()
.build(),
new EnclaveKeyConfiguration(
privacyAccount.getEnclaveKeyPaths(), privacyAccount.getEnclavePrivateKeyPaths())),
privacyAccount.getEnclaveKeyPaths(),
privacyAccount.getEnclavePrivateKeyPaths(),
privacyAccount.getEnclaveEncryptorType())),
enclaveType,
containerNetwork);
}

@ -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;
@ -41,6 +40,14 @@ import java.util.stream.Collectors;
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;
@ -102,8 +109,6 @@ public class PrivacyRequestFactory {
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> {}
@ -232,7 +237,13 @@ public class PrivacyRequestFactory {
}
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(
@ -588,29 +599,19 @@ public class PrivacyRequestFactory {
}
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));
}
}

@ -17,6 +17,9 @@ package org.hyperledger.besu.tests.acceptance.privacy;
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;
@ -53,14 +56,21 @@ import org.web3j.tx.Contract;
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;
@ -82,21 +92,21 @@ public class FlexiblePrivacyAcceptanceTest extends FlexiblePrivacyAcceptanceTest
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));

@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat;
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;
@ -32,6 +31,10 @@ import java.util.Optional;
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;
@ -79,8 +82,7 @@ public class FlexiblePrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase
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(
@ -103,7 +105,7 @@ public class FlexiblePrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase
}
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);
}
@ -112,18 +114,26 @@ public class FlexiblePrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase
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,

@ -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";
@ -73,28 +73,28 @@ public class PrivacyGroupTest extends AcceptanceTestBase {
.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

@ -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
@ -76,14 +76,14 @@ public class PrivacyProxyTest extends AcceptanceTestBase {
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

@ -16,6 +16,9 @@ package org.hyperledger.besu.tests.acceptance.privacy.multitenancy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
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 org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
@ -32,6 +35,7 @@ import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -53,14 +57,21 @@ import org.web3j.utils.Restriction;
public class FlexibleMultiTenancyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase {
private final EnclaveType enclaveType;
private final EnclaveEncryptorType enclaveEncryptorType;
public FlexibleMultiTenancyAcceptanceTest(final EnclaveType enclaveType) {
public FlexibleMultiTenancyAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) {
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
}
@Parameterized.Parameters(name = "{0}")
public static Collection<EnclaveType> enclaveTypes() {
return EnclaveType.valuesForTests();
@Parameterized.Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
private static final PermissioningTransactions permissioningTransactions =
@ -75,7 +86,7 @@ public class FlexibleMultiTenancyAcceptanceTest extends FlexiblePrivacyAcceptanc
alice =
privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode(
"node1",
PrivacyAccountResolver.MULTI_TENANCY.resolve(EnclaveEncryptorType.NACL),
PrivacyAccountResolver.MULTI_TENANCY.resolve(enclaveEncryptorType),
true,
enclaveType,
Optional.empty());
@ -448,7 +459,7 @@ public class FlexibleMultiTenancyAcceptanceTest extends FlexiblePrivacyAcceptanc
privacyGroupId, groupCreatorNode, groupCreatorTenant);
final PrivateTransactionReceipt expectedReceipt =
buildExpectedAddMemberTransactionReceipt(
privacyGroupId, groupCreatorNode, groupCreatorTenant, members.toArray(new String[] {}));
privacyGroupId, groupCreatorNode, groupCreatorTenant, members);
for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) {
final PrivacyNode privacyNode = mtpn.getPrivacyNode();

@ -0,0 +1,19 @@
[Users.user]
password = "$2a$10$l3GA7K8g6rJ/Yv.YFSygCuI9byngpEzxgWS9qEg5emYDZomQW7fGC"
permissions = ["fakePermission", "*:*"]
privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMA=="
[Users.user2]
password = "$2a$10$0ikMUcSYugKmnXilimhc1eGNnfMRvKt2PxQJPo1oCemN16QL2NNo."
permissions = ["fakePermission", "*:*"]
privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXIgZqRA25V+3nN+Do6b5r0jiUunub6ubjPhqwHpPxP44uUYh9RKCQNRnsqCJ9PjeTnC8R3ieJk7HWAlycU1bug=="
[Users.user3]
password = "$2a$10$Mydyzpul6CtgPRbUd6It2OpZDOfqOocpi6.UYhlyU5aphQHi1iQZq"
permissions = ["fakePermission", "*:*"]
privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFl85WnNPyzSEX+evc774xoqUQdjSnQMTE1uIyMOve+iVwjs6dUEUwz5teiKuUUf63a/qYe4n6SGnQ7HnmtDViQ=="
[Users.failUser]
password = "$2a$10$l3GA7K8g6rJ/Yv.YFSygCuI9byngpEzxgWS9qEg5emYDZomQW7fGC"
permissions = ["fakePermission", "*:*"]
privacyPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE30vyCv2v4EHwqnr0LEGaCX6GWfmYIIxLRw1PISeFsOk1tmY2hAYjEHkaZzu31SlFx0ickh10MEublBnrxCiJIA=="

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
import static org.hyperledger.besu.ethereum.privacy.FlexiblePrivacyGroupContract.decodeList;
import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE;
import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_VERSION_METHOD_SIGNATURE;
@ -130,7 +129,11 @@ public class FlexiblePrivacyController extends AbstractRestrictedPrivacyControll
if (rlpInput.nextSize() > 0) {
return Optional.of(
new PrivacyGroup(
privacyGroupId, PrivacyGroup.Type.FLEXIBLE, "", "", decodeList(rlpInput.raw())));
privacyGroupId,
PrivacyGroup.Type.FLEXIBLE,
"",
"",
FlexibleUtil.decodeList(rlpInput.raw())));
}
}
return Optional.empty();
@ -283,6 +286,7 @@ public class FlexiblePrivacyController extends AbstractRestrictedPrivacyControll
enclave.send(bytes.toBase64String(), privacyUserId, privateFor).getKey());
}
}
return Optional.empty();
}

@ -39,15 +39,12 @@ import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.data.Restriction;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
/*
This class is an abstraction on top of the privacy group management smart contract.
@ -67,6 +64,7 @@ import org.apache.tuweni.units.bigints.UInt256;
that is not on a block boundary. Used this way, the object's lifetime is intended to be short.
*/
public class FlexiblePrivacyGroupContract {
@FunctionalInterface
public interface TransactionSimulator {
Optional<TransactionProcessingResult> simulate(
@ -167,7 +165,11 @@ public class FlexiblePrivacyGroupContract {
if (rlpInput.nextSize() > 0) {
final PrivacyGroup privacyGroup =
new PrivacyGroup(
privacyGroupId, PrivacyGroup.Type.FLEXIBLE, "", "", decodeList(rlpInput.raw()));
privacyGroupId,
PrivacyGroup.Type.FLEXIBLE,
"",
"",
FlexibleUtil.decodeList(rlpInput.raw()));
return Optional.of(privacyGroup);
} else {
return Optional.empty();
@ -227,20 +229,4 @@ public class FlexiblePrivacyGroupContract {
return new CallParameter(
Address.ZERO, FLEXIBLE_PRIVACY_PROXY, 3000000, Wei.of(1000), Wei.ZERO, methodCall);
}
public static List<String> decodeList(final Bytes rlpEncodedList) {
final ArrayList<String> decodedElements = new ArrayList<>();
// first 32 bytes is dynamic list offset
if (rlpEncodedList.size() < 64) return decodedElements;
// Bytes uses a byte[] for the content which can only have up to Integer.MAX_VALUE-5 elements
final int lengthOfList =
UInt256.fromBytes(rlpEncodedList.slice(32, 32)).toInt(); // length of list
if (rlpEncodedList.size() < 64 + lengthOfList * 32) return decodedElements;
for (int i = 0; i < lengthOfList; ++i) {
decodedElements.add(
Bytes.wrap(rlpEncodedList.slice(64 + (32 * i), 32)).toBase64String()); // participant
}
return decodedElements;
}
}

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
public class FlexibleUtil {
@ -40,11 +41,54 @@ public class FlexibleUtil {
}
public static List<String> getParticipantsFromParameter(final Bytes input) {
if (input.size() < 68) return new ArrayList<>();
final int numberOfParticipants = UInt256.fromBytes(input.slice(4 + 32, 32)).toInt();
// Method selector + offset + number of participants + (offset * number of participants)
final Bytes encodedParticipants = input.slice(4 + 32 + 32 + (32 * numberOfParticipants));
return getParticipantsFromEncodedParticipants(encodedParticipants, numberOfParticipants);
}
public static List<String> decodeList(final Bytes rlpEncodedList) {
if (rlpEncodedList.size() < 64) return new ArrayList<>();
// Bytes uses a byte[] for the content which can only have up to Integer.MAX_VALUE-5 elements
final int lengthOfList =
UInt256.fromBytes(rlpEncodedList.slice(32, 32)).toInt(); // length of list
final Bytes encodedParticipants = rlpEncodedList.slice(32 + 32 + (32 * lengthOfList));
return getParticipantsFromEncodedParticipants(encodedParticipants, lengthOfList);
}
private static List<String> getParticipantsFromEncodedParticipants(
final Bytes encodedParticipants, final int numberOfParticipants) {
final List<String> participants = new ArrayList<>();
final Bytes mungedParticipants = input.slice(4 + 32 + 32);
for (int i = 0; i <= mungedParticipants.size() - 32; i += 32) {
participants.add(mungedParticipants.slice(i, 32).toBase64String());
if (numberOfParticipants == 0) return participants;
// The participant value is enclosed in the closest multiple of 32 (for instance, 91 would be
// enclosed in 96)
final int sliceSize = encodedParticipants.size() / numberOfParticipants;
// All the participants have to have the same size, so it is enough to check the first one
final int participantSize = UInt256.fromBytes(encodedParticipants.slice(0, 32)).toInt();
// Each slice should have a size of 32 bytes (because of the size value of each participant) +
// the actual participant wrapped in a 32 byte long multiple (96 for 91)
final int mod32ParticipantsSize = participantSize % 32;
final int participantSizeBytes32Wrapped =
mod32ParticipantsSize != 0
? (32 - mod32ParticipantsSize) + participantSize
: participantSize;
if (sliceSize != 32 + participantSizeBytes32Wrapped) return participants;
for (int i = 0; i <= encodedParticipants.size() - sliceSize; i += sliceSize) {
// The size of each participant (as of now, either 32 or 91 because of the enclave public key
// size for NaCl and EC) is stored in 32 bytes
participants.add(encodedParticipants.slice(i + 32, participantSize).toBase64String());
}
return participants;
}
}

@ -312,9 +312,14 @@ public class FlexiblePrivacyPrecompiledContractTest {
// array length too big
assertThatComputeReturnsEmptyGivenContractMembershipQueryReturns(
Bytes.concatenate(
// offset
Bytes32.fromHexStringLenient("0x0"),
// array length
Bytes32.fromHexStringLenient("0x1"),
// offset
Bytes32.fromHexStringLenient("0x0"),
// member public key size
Bytes32.fromHexStringLenient("0x20"),
// first array content
Bytes32.fromHexStringLenient("0x1")));
}
@ -332,6 +337,10 @@ public class FlexiblePrivacyPrecompiledContractTest {
Bytes32.fromHexStringLenient("0x0"),
// array length
Bytes32.fromHexStringLenient("0x2"),
// offset
Bytes32.fromHexStringLenient("0x0"),
// member public key size
Bytes32.fromHexStringLenient("0x20"),
// first array content
Bytes32.fromHexStringLenient("0x1")));
}

@ -99,11 +99,9 @@ public class FlexiblePrivacyControllerTest {
private static final String TRANSACTION_KEY = "93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=";
private static final List<String> PRIVACY_GROUP_ADDRESSES = List.of(ADDRESS1, ADDRESS2);
private static final Bytes SIMULATOR_RESULT_PREFIX =
Bytes.fromHexString(
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002");
private static final Bytes SIMULATOR_RESULT =
Bytes.concatenate(SIMULATOR_RESULT_PREFIX, Base64.decode(ADDRESS1), Base64.decode(ADDRESS2));
Bytes.fromHexString(
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020035695b4cc4b0941e60551d7a19cf30603db5bfc23e5ac43a56f57f25f75486a00000000000000000000000000000000000000000000000000000000000000202a8d9b56a0fe9cd94d60be4413bcb721d3a7be27ed8e28b3a6346df874ee141b");
private static final PrivacyGroup EXPECTED_PRIVACY_GROUP =
new PrivacyGroup(
PRIVACY_GROUP_ID, PrivacyGroup.Type.FLEXIBLE, "", "", PRIVACY_GROUP_ADDRESSES);
@ -197,7 +195,7 @@ public class FlexiblePrivacyControllerTest {
}
@Test
public void findFleixblePrivacyGroups() {
public void findFlexiblePrivacyGroups() {
mockingForFindPrivacyGroupByMembers();
mockingForFindPrivacyGroupById();

@ -0,0 +1,87 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class FlexibleUtilTest {
private static final String EXPECTED_EC_PARTICIPANT_1 =
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMA==";
private static final String EXPECTED_EC_PARTICIPANT_2 =
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXIgZqRA25V+3nN+Do6b5r0jiUunub6ubjPhqwHpPxP44uUYh9RKCQNRnsqCJ9PjeTnC8R3ieJk7HWAlycU1bug==";
@Test
public void testGetParticipantsFromParameter() {
final String parameterNaCl =
"llol7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADVpW0zEsJQeYFUdehnPMGA9tb/CPlrEOlb1fyX3VIagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKo2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=";
final String expectedNaClParticipant1 = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
final String expectedNaClParticipant2 = "Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=";
List<String> actualParticipants =
FlexibleUtil.getParticipantsFromParameter(Bytes.fromBase64String(parameterNaCl));
assertThat(actualParticipants).hasSize(2);
assertThat(actualParticipants.get(0)).isEqualTo(expectedNaClParticipant1);
assertThat(actualParticipants.get(1)).isEqualTo(expectedNaClParticipant2);
final String parameterEC =
"llol7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARLycLipP8p2gChNIXeqz/jsNSwOKHJVtaJGNkCLK+qn15IOSpXVHOUz7nyg7CekVHC9Y1kz4DExXFP4y/F2yowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFyIGakQNuVft5zfg6Om+a9I4lLp7m+rm4z4asB6T8T+OLlGIfUSgkDUZ7KgifT43k5wvEd4niZOx1gJcnFNW7oAAAAAAA==";
actualParticipants =
FlexibleUtil.getParticipantsFromParameter(Bytes.fromBase64String(parameterEC));
assertThat(actualParticipants).hasSize(2);
assertThat(actualParticipants.get(0)).isEqualTo(EXPECTED_EC_PARTICIPANT_1);
assertThat(actualParticipants.get(1)).isEqualTo(EXPECTED_EC_PARTICIPANT_2);
final String parameterEC2 =
"llol7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMAAAAAAA";
actualParticipants =
FlexibleUtil.getParticipantsFromParameter(Bytes.fromBase64String(parameterEC2));
assertThat(actualParticipants).hasSize(1);
assertThat(actualParticipants.get(0)).isEqualTo(EXPECTED_EC_PARTICIPANT_1);
}
@Test
public void testDecodeList() {
final Bytes rlpEncodedOneParticipant =
Bytes.fromBase64String(
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARLycLipP8p2gChNIXeqz/jsNSwOKHJVtaJGNkCLK+qn15IOSpXVHOUz7nyg7CekVHC9Y1kz4DExXFP4y/F2yowAAAAAAA=");
List<String> actualParticipants = FlexibleUtil.decodeList(rlpEncodedOneParticipant);
assertThat(actualParticipants).isEqualTo(Arrays.asList(EXPECTED_EC_PARTICIPANT_1));
final Bytes wrongBytes =
Bytes.fromBase64String(
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
actualParticipants = FlexibleUtil.decodeList(wrongBytes);
assertThat(actualParticipants).isEmpty();
}
}

@ -23,6 +23,7 @@ import java.util.concurrent.Callable;
import org.web3j.abi.TypeReference;
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.abi.datatypes.generated.Bytes32;
@ -44,7 +45,7 @@ import org.web3j.tx.gas.ContractGasProvider;
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the <a
* href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.5.16.
* <p>Generated with web3j version 1.4.1.
*/
@SuppressWarnings("rawtypes")
public class FlexiblePrivacyGroupManagementInterface extends Contract {
@ -107,10 +108,10 @@ public class FlexiblePrivacyGroupManagementInterface extends Contract {
new Function(
FUNC_ADDPARTICIPANTS,
Arrays.<Type>asList(
new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Bytes32>(
org.web3j.abi.datatypes.generated.Bytes32.class,
new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.DynamicBytes>(
org.web3j.abi.datatypes.DynamicBytes.class,
org.web3j.abi.Utils.typeMap(
publicEnclaveKeys, org.web3j.abi.datatypes.generated.Bytes32.class))),
publicEnclaveKeys, org.web3j.abi.datatypes.DynamicBytes.class))),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
@ -136,7 +137,7 @@ public class FlexiblePrivacyGroupManagementInterface extends Contract {
new Function(
FUNC_GETPARTICIPANTS,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<DynamicArray<Bytes32>>() {}));
Arrays.<TypeReference<?>>asList(new TypeReference<DynamicArray<DynamicBytes>>() {}));
return new RemoteFunctionCall<List>(
function,
new Callable<List>() {
@ -168,7 +169,7 @@ public class FlexiblePrivacyGroupManagementInterface extends Contract {
final Function function =
new Function(
FUNC_REMOVEPARTICIPANT,
Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Bytes32(participant)),
Arrays.<Type>asList(new org.web3j.abi.datatypes.DynamicBytes(participant)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}

@ -12,7 +12,8 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity ^0.6.0;
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./FlexiblePrivacyGroupManagementInterface.sol";
contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupManagementInterface {
@ -20,8 +21,8 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
address private _owner;
bool private _canExecute;
bytes32 private _version;
bytes32[] private distributionList;
mapping(bytes32 => uint256) private distributionIndexOf;
bytes[] private distributionList;
mapping(bytes => uint256) private distributionIndexOf;
function getVersion() external view override returns (bytes32) {
return _version;
@ -43,10 +44,10 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
_canExecute = true;
}
function addParticipants(bytes32[] memory _publicEnclaveKeys) public override returns (bool) {
function addParticipants(bytes[] calldata _publicEnclaveKeys) public override returns (bool) {
require(!_canExecute);
if (_owner == address(0x0)) {
// The account creating this group is set to be the owner
// The account creating this group is set to be the owner
_owner = tx.origin;
}
require(tx.origin == _owner, "Origin not the owner.");
@ -56,7 +57,7 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
return result;
}
function removeParticipant(bytes32 _participant) public override returns (bool) {
function removeParticipant(bytes calldata _participant) public override returns (bool) {
require(_canExecute);
require(tx.origin == _owner, "Origin not the owner.");
bool result = removeInternal(_participant);
@ -64,17 +65,17 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
return result;
}
function getParticipants() public view override returns (bytes32[] memory) {
function getParticipants() public view override returns (bytes[] memory) {
return distributionList;
}
function canUpgrade() external override returns (bool) {
function canUpgrade() external view override returns (bool) {
return tx.origin == _owner;
}
//internal functions
function addAll(bytes32[] memory _publicEnclaveKeys) internal returns (bool) {
function addAll(bytes[] calldata _publicEnclaveKeys) internal returns (bool) {
bool allAdded = true;
for (uint i = 0; i < _publicEnclaveKeys.length; i++) {
if (isMember(_publicEnclaveKeys[i])) {
@ -90,11 +91,11 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
return allAdded;
}
function isMember(bytes32 _publicEnclaveKey) internal view returns (bool) {
function isMember(bytes calldata _publicEnclaveKey) internal view returns (bool) {
return distributionIndexOf[_publicEnclaveKey] != 0;
}
function addParticipant(bytes32 _publicEnclaveKey) internal returns (bool) {
function addParticipant(bytes calldata _publicEnclaveKey) internal returns (bool) {
if (distributionIndexOf[_publicEnclaveKey] == 0) {
distributionList.push(_publicEnclaveKey);
distributionIndexOf[_publicEnclaveKey] = distributionList.length;
@ -103,12 +104,12 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
return false;
}
function removeInternal(bytes32 _participant) internal returns (bool) {
function removeInternal(bytes calldata _participant) internal returns (bool) {
uint256 index = distributionIndexOf[_participant];
if (index > 0 && index <= distributionList.length) {
//move last address into index being vacated (unless we are dealing with last index)
if (index != distributionList.length) {
bytes32 lastPublicKey = distributionList[distributionList.length - 1];
bytes storage lastPublicKey = distributionList[distributionList.length - 1];
distributionList[index - 1] = lastPublicKey;
distributionIndexOf[lastPublicKey] = index;
}
@ -119,13 +120,13 @@ contract DefaultFlexiblePrivacyGroupManagementContract is FlexiblePrivacyGroupMa
return false;
}
function updateVersion() internal returns (int) {
_version = keccak256(abi.encodePacked(blockhash(block.number-1), block.coinbase, distributionList));
function updateVersion() internal {
_version = keccak256(abi.encode(blockhash(block.number-1), block.coinbase, distributionList));
}
event ParticipantAdded(
bool success,
bytes32 publicEnclaveKey,
bytes publicEnclaveKey,
string message
);
}

@ -12,14 +12,16 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity ^0.6.0;
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
interface FlexiblePrivacyGroupManagementInterface {
function addParticipants(bytes32[] calldata publicEnclaveKeys) external returns (bool);
function addParticipants(bytes[] calldata publicEnclaveKeys) external returns (bool);
function removeParticipant(bytes32 participant) external returns (bool);
function removeParticipant(bytes calldata participant) external returns (bool);
function getParticipants() external view returns (bytes32[] memory);
function getParticipants() external view returns (bytes[] memory);
function lock() external;

@ -12,14 +12,15 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity ^0.6.0;
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./FlexiblePrivacyGroupManagementInterface.sol";
contract FlexiblePrivacyGroupManagementProxy is FlexiblePrivacyGroupManagementInterface {
address public implementation;
constructor(address _implementation) public {
constructor(address _implementation) {
implementation = _implementation;
}
@ -27,23 +28,23 @@ contract FlexiblePrivacyGroupManagementProxy is FlexiblePrivacyGroupManagementIn
implementation = _newImp;
}
function addParticipants(bytes32[] memory _publicEnclaveKeys) public override returns (bool) {
function addParticipants(bytes[] calldata _publicEnclaveKeys) public override returns (bool) {
FlexiblePrivacyGroupManagementInterface privacyInterface = FlexiblePrivacyGroupManagementInterface(implementation);
return privacyInterface.addParticipants(_publicEnclaveKeys);
}
function getParticipants() view public override returns (bytes32[] memory) {
function getParticipants() view public override returns (bytes[] memory) {
FlexiblePrivacyGroupManagementInterface privacyInterface = FlexiblePrivacyGroupManagementInterface(implementation);
return privacyInterface.getParticipants();
}
function removeParticipant(bytes32 _participant) public override returns (bool) {
function removeParticipant(bytes calldata _participant) public override returns (bool) {
FlexiblePrivacyGroupManagementInterface privacyInterface = FlexiblePrivacyGroupManagementInterface(implementation);
bool result = privacyInterface.removeParticipant(_participant);
if (result) {
emit ParticipantRemoved(_participant);
}
return result;
return result;
}
function lock() public override {
@ -75,15 +76,14 @@ contract FlexiblePrivacyGroupManagementProxy is FlexiblePrivacyGroupManagementIn
require(this.canExecute(), "The contract is locked.");
require(implementation != _newImplementation, "The contract to upgrade to has to be different from the current management contract.");
require(this.canUpgrade(), "Not allowed to upgrade the management contract.");
bytes32[] memory participants = this.getParticipants();
bytes[] memory participants = this.getParticipants();
_setImplementation(_newImplementation);
FlexiblePrivacyGroupManagementInterface privacyInterface = FlexiblePrivacyGroupManagementInterface(implementation);
privacyInterface.addParticipants(participants);
}
event ParticipantRemoved(
bytes32 publicEnclaveKey
bytes publicEnclaveKey
);
}

@ -16,7 +16,7 @@ done
for target in ${targets}; do
web3j solidity generate \
web3j generate solidity \
-b build/${target}.bin \
-a build/${target}.abi \
-o ../java \

@ -33,10 +33,6 @@ public class EnclaveKeyConfiguration {
this.enclaveEncryptorType = enclaveEncryptorType;
}
public EnclaveKeyConfiguration(final String[] pubKeyPaths, final String[] privKeyPaths) {
this(pubKeyPaths, privKeyPaths, EnclaveEncryptorType.NACL);
}
public String[] getPubKeyPaths() {
return pubKeyPaths;
}

Loading…
Cancel
Save