mirror of https://github.com/hyperledger/besu
Privacy plugin pmt factory (#2557)
* Refactor: clarify intent of arg when testing permissioning plugin Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * Refactor: remove duplicate createPrivateMarkerTransaction Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * PrivateMarkerTransactionFactory: add option to delegate to plugin if defined the plugin will be responsible for creating the pmt Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * Implement locking strategy for eea_sendRawTransaction - this will lock per address being sent to prevent nonce too low errors Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * Refactor plugin integration to use a more explicit poco - the plugin will need to sign the transaction with the data it's given - it will not need to query anything e.g nonce etc Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * refactor: update naming and tidy up based on comments Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> * Isolate code for calculating gas limit when using privacy plugin Signed-off-by: Antony Denyer <git@antonydenyer.co.uk> Co-authored-by: Vijay Michalik <vijay.michalik@consensys.net>pull/2584/head
parent
bdb9c1ad85
commit
41521b6c03
@ -0,0 +1,87 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.plugins; |
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger; |
||||
import static org.hyperledger.besu.ethereum.core.Address.extract; |
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair; |
||||
import org.hyperledger.besu.crypto.SECPPrivateKey; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.ethereum.core.Hash; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.core.Wei; |
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; |
||||
import org.hyperledger.besu.plugin.data.Address; |
||||
import org.hyperledger.besu.plugin.data.PrivateTransaction; |
||||
import org.hyperledger.besu.plugin.data.TransactionType; |
||||
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction; |
||||
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory; |
||||
|
||||
import org.apache.logging.log4j.Logger; |
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.apache.tuweni.bytes.Bytes32; |
||||
|
||||
public class TestSigningPrivateMarkerTransactionFactory implements PrivateMarkerTransactionFactory { |
||||
|
||||
private static final Logger LOG = getLogger(); |
||||
|
||||
final KeyPair aliceFixedSigningKey; |
||||
final Address sender; |
||||
|
||||
public TestSigningPrivateMarkerTransactionFactory( |
||||
final String privateMarkerTransactionSigningKey) { |
||||
final SignatureAlgorithm algorithm = SignatureAlgorithmFactory.getInstance(); |
||||
final SECPPrivateKey privateKey = |
||||
algorithm.createPrivateKey(Bytes32.fromHexString(privateMarkerTransactionSigningKey)); |
||||
|
||||
aliceFixedSigningKey = algorithm.createKeyPair(privateKey); |
||||
sender = extract(Hash.hash(aliceFixedSigningKey.getPublicKey().getEncodedBytes())); |
||||
} |
||||
|
||||
@Override |
||||
public Bytes create( |
||||
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction, |
||||
final PrivateTransaction privateTransaction, |
||||
final String privacyUserId) { |
||||
|
||||
final Transaction transaction = |
||||
Transaction.builder() |
||||
.type(TransactionType.FRONTIER) |
||||
.nonce(unsignedPrivateMarkerTransaction.getNonce()) |
||||
.gasPrice( |
||||
unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null)) |
||||
.gasLimit(unsignedPrivateMarkerTransaction.getGasLimit()) |
||||
.to( |
||||
org.hyperledger.besu.ethereum.core.Address.fromPlugin( |
||||
unsignedPrivateMarkerTransaction.getTo().get())) |
||||
.value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue())) |
||||
.payload(unsignedPrivateMarkerTransaction.getPayload()) |
||||
.signAndBuild(aliceFixedSigningKey); |
||||
|
||||
LOG.info("Signing PMT from " + sender); |
||||
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput(); |
||||
transaction.writeTo(out); |
||||
return out.encoded(); |
||||
} |
||||
|
||||
@Override |
||||
public Address getSender( |
||||
final PrivateTransaction privateTransaction, final String privacyUserId) { |
||||
return sender; |
||||
} |
||||
} |
@ -0,0 +1,99 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.tests.acceptance.privacy; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver.BOB; |
||||
import static org.web3j.utils.Restriction.UNRESTRICTED; |
||||
|
||||
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder; |
||||
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeConfiguration; |
||||
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase; |
||||
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; |
||||
import org.hyperledger.besu.tests.web3j.generated.EventEmitter; |
||||
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration; |
||||
import org.hyperledger.enclave.testutil.EnclaveType; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.web3j.protocol.core.methods.response.TransactionReceipt; |
||||
|
||||
public class PluginPrivacySigningAcceptanceTest extends PrivacyAcceptanceTestBase { |
||||
private PrivacyNode minerNode; |
||||
|
||||
@Before |
||||
public void setup() throws IOException { |
||||
minerNode = |
||||
privacyBesu.create( |
||||
new PrivacyNodeConfiguration( |
||||
false, |
||||
false, |
||||
true, |
||||
new BesuNodeConfigurationBuilder() |
||||
.name("miner") |
||||
.miningEnabled() |
||||
.jsonRpcEnabled() |
||||
.webSocketEnabled() |
||||
.enablePrivateTransactions() |
||||
.keyFilePath(BOB.getPrivateKeyPath()) |
||||
.plugins(Collections.singletonList("testPlugins")) |
||||
.extraCLIOptions( |
||||
List.of( |
||||
"--plugin-privacy-service-encryption-prefix=0xAA", |
||||
"--plugin-privacy-service-signing-enabled=true", |
||||
"--plugin-privacy-service-signing-key=8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63")) |
||||
.build(), |
||||
new EnclaveKeyConfiguration( |
||||
BOB.getEnclaveKeyPaths(), BOB.getEnclavePrivateKeyPaths())), |
||||
EnclaveType.NOOP, |
||||
Optional.empty()); |
||||
|
||||
privacyCluster.start(minerNode); |
||||
} |
||||
|
||||
@Test |
||||
public void canDeployContractSignedByPlugin() throws Exception { |
||||
final String contractAddress = "0xd0152772c54cecfa7684f09f7616dcc825545dff"; |
||||
|
||||
final EventEmitter eventEmitter = |
||||
minerNode.execute( |
||||
privateContractTransactions.createSmartContract( |
||||
EventEmitter.class, |
||||
minerNode.getTransactionSigningKey(), |
||||
UNRESTRICTED, |
||||
minerNode.getEnclaveKey())); |
||||
|
||||
privateContractVerifier |
||||
.validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString()) |
||||
.verify(eventEmitter); |
||||
privateContractVerifier.validContractCodeProvided().verify(eventEmitter); |
||||
|
||||
final TransactionReceipt pmtReceipt = |
||||
minerNode |
||||
.execute( |
||||
ethTransactions.getTransactionReceipt( |
||||
"0x5586b8321e26cdabd68e0139955b90f97c0fc082519d07e1c0b9db26862ff2ff")) |
||||
.get(); |
||||
|
||||
assertThat(pmtReceipt.getStatus()).isEqualTo("0x1"); |
||||
|
||||
assertThat(pmtReceipt.getFrom()).isEqualTo("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"); |
||||
} |
||||
} |
@ -1,59 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.markertransaction; |
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair; |
||||
import org.hyperledger.besu.ethereum.core.Address; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; |
||||
import org.hyperledger.besu.plugin.data.TransactionType; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public abstract class PrivateMarkerTransactionFactory { |
||||
|
||||
private final Address privacyPrecompileAddress; |
||||
|
||||
protected PrivateMarkerTransactionFactory(final Address privacyPrecompileAddress) { |
||||
this.privacyPrecompileAddress = privacyPrecompileAddress; |
||||
} |
||||
|
||||
public Transaction create( |
||||
final String privateMarkerTransactionPayload, final PrivateTransaction privateTransaction) { |
||||
return create(privateMarkerTransactionPayload, privateTransaction, privacyPrecompileAddress); |
||||
} |
||||
|
||||
public abstract Transaction create( |
||||
final String privateMarkerTransactionPayload, |
||||
final PrivateTransaction privateTransaction, |
||||
final Address precompileAddress); |
||||
|
||||
protected Transaction create( |
||||
final String privateMarkerTransactionPayload, |
||||
final PrivateTransaction privateTransaction, |
||||
final long nonce, |
||||
final KeyPair signingKey, |
||||
final Address precompileAddress) { |
||||
return Transaction.builder() |
||||
.type(TransactionType.FRONTIER) |
||||
.nonce(nonce) |
||||
.gasPrice(privateTransaction.getGasPrice()) |
||||
.gasLimit(privateTransaction.getGasLimit()) |
||||
.to(precompileAddress) |
||||
.value(privateTransaction.getValue()) |
||||
.payload(Bytes.fromBase64String(privateMarkerTransactionPayload)) |
||||
.signAndBuild(signingKey); |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.markertransaction; |
||||
|
||||
import org.hyperledger.besu.crypto.KeyPair; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.core.Wei; |
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; |
||||
import org.hyperledger.besu.plugin.data.TransactionType; |
||||
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class SigningPrivateMarkerTransactionFactory { |
||||
|
||||
protected Bytes signAndBuild( |
||||
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction, |
||||
final KeyPair signingKey) { |
||||
final Transaction transaction = |
||||
Transaction.builder() |
||||
.type(TransactionType.FRONTIER) |
||||
.nonce(unsignedPrivateMarkerTransaction.getNonce()) |
||||
.gasPrice( |
||||
unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null)) |
||||
.gasLimit(unsignedPrivateMarkerTransaction.getGasLimit()) |
||||
.to( |
||||
org.hyperledger.besu.ethereum.core.Address.fromPlugin( |
||||
unsignedPrivateMarkerTransaction.getTo().get())) |
||||
.value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue())) |
||||
.payload(unsignedPrivateMarkerTransaction.getPayload()) |
||||
.signAndBuild(signingKey); |
||||
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput(); |
||||
transaction.writeTo(out); |
||||
return out.encoded(); |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.plugin.data; |
||||
|
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public interface UnsignedPrivateMarkerTransaction { |
||||
|
||||
TransactionType getType(); |
||||
|
||||
long getNonce(); |
||||
|
||||
Optional<? extends Quantity> getGasPrice(); |
||||
|
||||
long getGasLimit(); |
||||
|
||||
Optional<? extends Address> getTo(); |
||||
|
||||
Quantity getValue(); |
||||
|
||||
Bytes getPayload(); |
||||
} |
@ -0,0 +1,31 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.plugin.services.privacy; |
||||
|
||||
import org.hyperledger.besu.plugin.data.Address; |
||||
import org.hyperledger.besu.plugin.data.PrivateTransaction; |
||||
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public interface PrivateMarkerTransactionFactory { |
||||
|
||||
Address getSender(PrivateTransaction privateTransaction, String privacyUserId); |
||||
|
||||
Bytes create( |
||||
UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction, |
||||
PrivateTransaction privateTransaction, |
||||
String privacyUserId); |
||||
} |
Loading…
Reference in new issue