Skip to content

Commit

Permalink
Add rpc: (NethermindEth#2046)
Browse files Browse the repository at this point in the history
parity_setEngineSigner
parity_setEngineSignerSecret
parity_clearEngineSigner
  • Loading branch information
LukaszRozmej authored Jun 23, 2020
1 parent b89c6c5 commit 8adf079
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.AuRa.Test/AuRaSealerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void Setup()
_auRaStepCalculator = Substitute.For<IAuRaStepCalculator>();
_validatorStore = Substitute.For<IValidatorStore>();
_validSealerStrategy = Substitute.For<IValidSealerStrategy>();
var signer = new Signer(ChainId.Mainnet, Build.A.PrivateKey.TestObject);
var signer = new Signer(ChainId.Mainnet, Build.A.PrivateKey.TestObject, LimboLogs.Instance);
_address = signer.Address;

_auRaSealer = new AuRaSealer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using Nethermind.Crypto;
using Nethermind.Evm;
using Nethermind.Evm.Tracing;
using Nethermind.Logging;
using Nethermind.State;
using NSubstitute;
using NUnit.Framework;
Expand Down Expand Up @@ -54,14 +55,14 @@ public void SetUp()
[Test]
public void constructor_throws_ArgumentNullException_on_null_encoder()
{
Action action = () => new ValidatorContract(_transactionProcessor, null, _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD));
Action action = () => new ValidatorContract(_transactionProcessor, null, _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD, LimboLogs.Instance));
action.Should().Throw<ArgumentNullException>();
}

[Test]
public void constructor_throws_ArgumentNullException_on_null_contractAddress()
{
Action action = () => new ValidatorContract(_transactionProcessor, new AbiEncoder(), null, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD));
Action action = () => new ValidatorContract(_transactionProcessor, new AbiEncoder(), null, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD, LimboLogs.Instance));
action.Should().Throw<ArgumentNullException>();
}

Expand All @@ -81,7 +82,7 @@ public void finalize_change_should_call_correct_transaction()
};
expectation.Hash = expectation.CalculateHash();

var contract = new ValidatorContract(_transactionProcessor, new AbiEncoder(), _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD));
var contract = new ValidatorContract(_transactionProcessor, new AbiEncoder(), _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD, LimboLogs.Instance));

contract.FinalizeChange(_block.Header);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void transaction_is_addable_to_block_after_fill()
var innerTxSource = Substitute.For<ITxSource>();
innerTxSource.GetTransactions(blockHeader, gasLimit).Returns(new[] {tx});

TxSealer txSealer = new TxSealer(new Signer(chainId, Build.A.PrivateKey.TestObject), timestamper);
TxSealer txSealer = new TxSealer(new Signer(chainId, Build.A.PrivateKey.TestObject, LimboLogs.Instance), timestamper);
var transactionFiller = new GeneratedTxSourceSealer(innerTxSource, txSealer, stateReader, LimboLogs.Instance);

var txResult= transactionFiller.GetTransactions(blockHeader, gasLimit).First();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public void SetUp()
.Encode(AbiEncodingStyle.IncludeSignature, Arg.Is<AbiSignature>(s => s.Name == "finalizeChange"), Arg.Any<object[]>())
.Returns(_finalizeChangeData.TransactionData);

_validatorContract = new ValidatorContract(_transactionProcessor, _abiEncoder, _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD));
_validatorContract = new ValidatorContract(_transactionProcessor, _abiEncoder, _contractAddress, _stateProvider, _readOnlyTransactionProcessorSource, new Signer(0, TestItem.PrivateKeyD, LimboLogs.Instance));
}

[Test]
Expand Down
11 changes: 11 additions & 0 deletions src/Nethermind/Nethermind.Cli/Modules/ParityCliModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

using Jint.Native;
using Nethermind.Core;

namespace Nethermind.Cli.Modules
{
Expand All @@ -33,5 +34,15 @@ public ParityCliModule(ICliEngine engine, INodeManager nodeManager) : base(engin

[CliProperty("parity", "enode", Description = "Returns the node enode URI.")]
public string Enode() => NodeManager.Post<string>("parity_enode").Result;

[CliFunction("parity", "clearEngineSigner", Description = "Clears an authority account for signing consensus messages. Blocks will not be sealed.")]
public bool ClearSigner() => NodeManager.Post<bool>("parity_clearEngineSigner").Result;

[CliFunction("parity", "setEngineSigner", Description = "Sets an authority account for signing consensus messages.")]
public bool SetSigner(Address address, string password) => NodeManager.Post<bool>("parity_setEngineSigner", address, password).Result;

[CliFunction("parity", "setEngineSignerSecret", Description = "Sets an authority account for signing consensus messages.")]
public bool SetEngineSignerSecret(string privateKey) => NodeManager.Post<bool>("parity_setEngineSignerSecret", privateKey).Result;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = f

SnapshotManager snapshotManager = new SnapshotManager(_cliqueConfig, blocksDb, blockTree, _ethereumEcdsa, nodeLogManager);
_snapshotManager[privateKey] = snapshotManager;
CliqueSealer cliqueSealer = new CliqueSealer(new Signer(ChainId.Goerli, privateKey), _cliqueConfig, snapshotManager, nodeLogManager);
CliqueSealer cliqueSealer = new CliqueSealer(new Signer(ChainId.Goerli, privateKey, LimboLogs.Instance), _cliqueConfig, snapshotManager, nodeLogManager);



Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Clique.Test/CliqueBridgeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void Sets_clique_block_producer_properly()
{
CliqueConfig cliqueConfig = new CliqueConfig();
IBlockTree blockTree = Substitute.For<IBlockTree>();
Signer signer = new Signer(ChainId.Ropsten, TestItem.PrivateKeyA);
Signer signer = new Signer(ChainId.Ropsten, TestItem.PrivateKeyA, LimboLogs.Instance);
CliqueBlockProducer producer = new CliqueBlockProducer(
Substitute.For<ITxSource>(),
Substitute.For<IBlockchainProcessor>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void Setup_chain()
_currentSigner = _signers[currentSignerIndex];
_snapshotManager = new SnapshotManager(config, db, _blockTree, ecdsa, LimboLogs.Instance);
_sealValidator = new CliqueSealValidator(config, _snapshotManager, LimboLogs.Instance);
_clique = new CliqueSealer(new Signer(ChainId.Rinkeby, _currentSigner), config, _snapshotManager, LimboLogs.Instance);
_clique = new CliqueSealer(new Signer(ChainId.Rinkeby, _currentSigner, LimboLogs.Instance), config, _snapshotManager, LimboLogs.Instance);
}

[Test]
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Clique.Test/CliqueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void Setup_chain()

_ecdsa = new EthereumEcdsa(ChainId.Rinkeby, LimboLogs.Instance);
_snapshotManager = new SnapshotManager(config, db, _blockTree, _ecdsa, LimboLogs.Instance);
_clique = new CliqueSealer(new Signer(ChainId.Rinkeby, key), config, _snapshotManager, LimboLogs.Instance);
_clique = new CliqueSealer(new Signer(ChainId.Rinkeby, key, LimboLogs.Instance), config, _snapshotManager, LimboLogs.Instance);
_sealValidator = new CliqueSealValidator(config, _snapshotManager, LimboLogs.Instance);
}

Expand Down
2 changes: 0 additions & 2 deletions src/Nethermind/Nethermind.Consensus/ISignerStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,5 @@ public interface ISignerStore
{
void SetSigner(PrivateKey key);
void SetSigner(ProtectedPrivateKey key);
void LockSign();
void UnlockSign();
}
}
27 changes: 11 additions & 16 deletions src/Nethermind/Nethermind.Consensus/Signer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Logging;
using Nethermind.Secp256k1;
using Nethermind.Serialization.Rlp;

Expand All @@ -28,30 +29,33 @@ public class Signer : ISigner, ISignerStore
{
private readonly int _chainId;
private ProtectedPrivateKey _key;
private bool _canSign = true;
private ILogger _logger;

public Address Address => _key.Address;
public Address Address => _key?.Address ?? Address.Zero;

public bool CanSign
{
get => _canSign && _key != null;
get => _key != null;
}

public Signer(int chainId, PrivateKey key)
public Signer(int chainId, PrivateKey key, ILogManager logManager)
{
_chainId = chainId;
_logger = logManager?.GetClassLogger<Signer>() ?? throw new ArgumentNullException(nameof(logManager));
SetSigner(key);
}

public Signer(int chainId, ProtectedPrivateKey key)
public Signer(int chainId, ProtectedPrivateKey key, ILogManager logManager)
{
_chainId = chainId;
_logger = logManager?.GetClassLogger<Signer>() ?? throw new ArgumentNullException(nameof(logManager));
SetSigner(key);
}

public Signature Sign(Keccak message)
{
if (_key == null) throw new NotSupportedException("Cannot sign without provided key.");
if (!CanSign) throw new NotSupportedException("Cannot sign without provided key.");

using var key = _key.Unprotect();
var rs = Proxy.SignCompact(message.Bytes, key.KeyBytes, out int v);
return new Signature(rs, v);
Expand All @@ -72,16 +76,7 @@ public void SetSigner(PrivateKey key)
public void SetSigner(ProtectedPrivateKey key)
{
_key = key;
}

public void LockSign()
{
_canSign = false;
}

public void UnlockSign()
{
_canSign = true;
if (_logger.IsInfo) _logger.Info(_key != null ? $"Address {Address} is configured for signing blocks." : "No address is configured for signing blocks.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.

using System.Net;
using FluentAssertions;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Receipts;
using Nethermind.Config;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Specs;
Expand All @@ -30,6 +32,7 @@
using Nethermind.State;
using Nethermind.State.Repositories;
using Nethermind.Db.Blooms;
using Nethermind.KeyStore;
using Nethermind.TxPool;
using Nethermind.TxPool.Storages;
using NUnit.Framework;
Expand All @@ -42,6 +45,7 @@ namespace Nethermind.JsonRpc.Test.Modules
public class ParityModuleTests
{
private IParityModule _parityModule;
private Signer _signerStore;

[SetUp]
public void Initialize()
Expand All @@ -59,7 +63,11 @@ public void Initialize()
IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, txPool, NullBloomStorage.Instance, LimboLogs.Instance);

IReceiptStorage receiptStorage = new InMemoryReceiptStorage();
_parityModule = new ParityModule(ethereumEcdsa, txPool, blockTree, receiptStorage, new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545), logger);

_signerStore = new Signer(specProvider.ChainId, TestItem.PrivateKeyB, logger);
_parityModule = new ParityModule(ethereumEcdsa, txPool, blockTree, receiptStorage, new Enode(TestItem.PublicKeyA, IPAddress.Loopback, 8545),
_signerStore, new MemKeyStore(new[] {TestItem.PrivateKeyA}), logger);

var blockNumber = 2;
var pendingTransaction = Build.A.Transaction.Signed(ethereumEcdsa, TestItem.PrivateKeyD, false)
.WithSenderAddress(Address.FromNumber((UInt256)blockNumber)).TestObject;
Expand Down Expand Up @@ -131,5 +139,35 @@ public void parity_enode()
var expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"enode://a49ac7010c2e0a444dfeeabadbafa4856ba4a2d732acb86d20c577b3b365fdaeb0a70ce47f890cf2f9fca562a7ed784f76eb870a2c75c0f2ab476a70ccb67e92@127.0.0.1:8545\",\"id\":67}";
Assert.AreEqual(expectedResult, serialized);
}

[Test]
public void parity_setEngineSigner()
{
string serialized = RpcTest.TestSerializedRequest(_parityModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password");
var expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}";
Assert.AreEqual(expectedResult, serialized);
_signerStore.Address.Should().Be(TestItem.AddressA);
_signerStore.CanSign.Should().BeTrue();
}

[Test]
public void parity_setEngineSignerSecret()
{
string serialized = RpcTest.TestSerializedRequest(_parityModule, "parity_setEngineSignerSecret", TestItem.PrivateKeyA.ToString());
var expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}";
Assert.AreEqual(expectedResult, serialized);
_signerStore.Address.Should().Be(TestItem.AddressA);
_signerStore.CanSign.Should().BeTrue();
}

[Test]
public void parity_clearEngineSigner()
{
RpcTest.TestSerializedRequest(_parityModule, "parity_setEngineSigner", TestItem.AddressA.ToString(), "password");
string serialized = RpcTest.TestSerializedRequest(_parityModule, "parity_clearEngineSigner");
var expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}";
_signerStore.Address.Should().Be(Address.Zero);
_signerStore.CanSign.Should().BeFalse();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using Nethermind.Blockchain;
using Nethermind.Blockchain.Find;
using Nethermind.Core;
using Nethermind.JsonRpc.Data;

namespace Nethermind.JsonRpc.Modules.Parity
Expand All @@ -26,5 +27,8 @@ public interface IParityModule : IModule
ResultWrapper<ParityTransaction[]> parity_pendingTransactions();
ResultWrapper<ReceiptForRpc[]> parity_getBlockReceipts(BlockParameter blockParameter);
ResultWrapper<string> parity_enode();
ResultWrapper<bool> parity_setEngineSigner(Address address, string password);
ResultWrapper<bool> parity_setEngineSignerSecret(string privateKey);
ResultWrapper<bool> parity_clearEngineSigner();
}
}
45 changes: 43 additions & 2 deletions src/Nethermind/Nethermind.JsonRpc/Modules/Parity/ParityModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Receipts;
using Nethermind.Config;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Crypto;
using Nethermind.JsonRpc.Data;
using Nethermind.KeyStore;
using Nethermind.Logging;
using Nethermind.Serialization.Rlp;
using Nethermind.TxPool;
Expand All @@ -37,14 +39,26 @@ public class ParityModule : IParityModule
private readonly IBlockFinder _blockFinder;
private readonly IReceiptFinder _receiptFinder;
private readonly IEnode _enode;
private readonly ISignerStore _signerStore;
private readonly IKeyStore _keyStore;

public ParityModule(IEcdsa ecdsa, ITxPool txPool, IBlockFinder blockFinder, IReceiptFinder receiptFinder, IEnode enode, ILogManager logManager)
public ParityModule(
IEcdsa ecdsa,
ITxPool txPool,
IBlockFinder blockFinder,
IReceiptFinder receiptFinder,
IEnode enode,
ISignerStore signerStore,
IKeyStore keyStore,
ILogManager logManager)
{
_ecdsa = ecdsa ?? throw new ArgumentNullException(nameof(ecdsa));
_txPool = txPool ?? throw new ArgumentNullException(nameof(txPool));
_blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder));
_receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder));
_enode = enode;
_enode = enode ?? throw new ArgumentNullException(nameof(enode));
_signerStore = signerStore ?? throw new ArgumentNullException(nameof(signerStore));
_keyStore = keyStore ?? throw new ArgumentNullException(nameof(keyStore));
}

public ResultWrapper<ParityTransaction[]> parity_pendingTransactions()
Expand All @@ -66,6 +80,33 @@ public ResultWrapper<ReceiptForRpc[]> parity_getBlockReceipts(BlockParameter blo
return ResultWrapper<ReceiptForRpc[]>.Success(result.ToArray());
}

public ResultWrapper<bool> parity_setEngineSigner(Address address, string password)
{
(ProtectedPrivateKey privateKey, Result result) = _keyStore.GetProtectedKey(address, password.Secure());
if (result == Result.Success)
{
_signerStore.SetSigner(privateKey);
return ResultWrapper<bool>.Success(true);
}
else
{
return ResultWrapper<bool>.Success(false);
}
}

public ResultWrapper<bool> parity_setEngineSignerSecret(string privateKey)
{
var key = new PrivateKey(privateKey);
_signerStore.SetSigner(key);
return ResultWrapper<bool>.Success(true);
}

public ResultWrapper<bool> parity_clearEngineSigner()
{
_signerStore.SetSigner((ProtectedPrivateKey) null);
return ResultWrapper<bool>.Success(true);
}

public ResultWrapper<string> parity_enode() => ResultWrapper<string>.Success(_enode.ToString());
}
}
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.KeyStore/MemKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ public MemKeyStore(PrivateKey[] privateKeys)

public (PrivateKey PrivateKey, Result Result) GetKey(Address address, SecureString password)
{
return (_privateKeys[address], Result.Success);
return _privateKeys.ContainsKey(address) ? (_privateKeys[address], Result.Success) : (null, Result.Fail("Can't unlock key."));
}

public (ProtectedPrivateKey PrivateKey, Result Result) GetProtectedKey(Address address, SecureString password)
{
return (new ProtectedPrivateKey(_privateKeys[address]), Result.Success);
return _privateKeys.ContainsKey(address) ? (new ProtectedPrivateKey(_privateKeys[address]), Result.Success) : (null, Result.Fail("Can't unlock key."));
}

public (KeyStoreItem KeyData, Result Result) GetKeyData(Address address)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private Task InitBlockchain()

Account.AccountStartNonce = _context.ChainSpec.Parameters.AccountStartNonce;

_context.Signer = new Signer(_context.SpecProvider.ChainId, _context.OriginalSignerKey);
_context.Signer = new Signer(_context.SpecProvider.ChainId, _context.OriginalSignerKey, _context.LogManager);

_context.StateProvider = new StateProvider(
_context.DbProvider.StateDb,
Expand Down
Loading

0 comments on commit 8adf079

Please sign in to comment.