diff --git a/src/NBitcoin/Crypto/ECKey.cs b/src/NBitcoin/Crypto/ECKey.cs
index 66e08884f0..aeb9d5e1cb 100644
--- a/src/NBitcoin/Crypto/ECKey.cs
+++ b/src/NBitcoin/Crypto/ECKey.cs
@@ -191,4 +191,12 @@ private static ECPoint DecompressKey(BigInteger xBN, bool yBit)
}
}
+
+ public static class ECKeyUtils
+ {
+ public static PubKey RecoverFromSignature(int recId, ECDSASignature sig, uint256 message, bool compressed)
+ {
+ return ECKey.RecoverFromSignature(recId, sig, message, compressed).GetPubKey(compressed);
+ }
+ }
}
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Stratis.Bitcoin.Features.SmartContracts.Tests.csproj b/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Stratis.Bitcoin.Features.SmartContracts.Tests.csproj
index 89393855db..10a5178455 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Stratis.Bitcoin.Features.SmartContracts.Tests.csproj
+++ b/src/Stratis.Bitcoin.Features.SmartContracts.Tests/Stratis.Bitcoin.Features.SmartContracts.Tests.csproj
@@ -17,8 +17,8 @@
+
-
all
runtime; build; native; contentfiles; analyzers
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs b/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
index 917471ab08..00ac769217 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
@@ -118,6 +118,7 @@ public static IFullNodeBuilder AddSmartContracts(this IFullNodeBuilder fullNodeB
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj b/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
index 29b239ca17..dbc320cce6 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
@@ -15,8 +15,8 @@
+
-
@@ -26,5 +26,4 @@
-
diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
index e972736eeb..068264bd80 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
@@ -99,8 +99,6 @@ private void AddInlineStats(StringBuilder log)
log.AppendLine("Wallet Height".PadRight(LoggingConfiguration.ColumnLength) + $": {this.walletManager.WalletTipHeight}".PadRight(10) + $"(Hash: {this.walletManager.WalletTipHash})");
else
log.AppendLine("Wallet Height".PadRight(LoggingConfiguration.ColumnLength) + ": No Wallet");
-
- log.AppendLine();
}
private void AddComponentStats(StringBuilder log)
diff --git a/src/Stratis.Bitcoin/Connection/ConnectionManager.cs b/src/Stratis.Bitcoin/Connection/ConnectionManager.cs
index 5ece69e57e..bc0d6021c3 100644
--- a/src/Stratis.Bitcoin/Connection/ConnectionManager.cs
+++ b/src/Stratis.Bitcoin/Connection/ConnectionManager.cs
@@ -316,6 +316,7 @@ void AddPeerInfo(StringBuilder peerBuilder, INetworkPeer peer)
int inbound = this.ConnectedPeers.Count(x => x.Inbound);
+ builder.AppendLine();
builder.AppendLine($">> Connections (In:{inbound}) (Out:{this.ConnectedPeers.Count() - inbound})");
builder.AppendLine("Data Transfer".PadRight(LoggingConfiguration.ColumnLength, ' ') + $": Received: {totalRead.BytesToMegaBytes()} MB Sent: {totalWritten.BytesToMegaBytes()} MB");
diff --git a/src/Stratis.SmartContracts.CLR.Tests/AuctionTests.cs b/src/Stratis.SmartContracts.CLR.Tests/AuctionTests.cs
index 36cfe45a97..2e851c27cc 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/AuctionTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/AuctionTests.cs
@@ -44,6 +44,7 @@ public AuctionTests()
null,
getBalance,
null,
+ null,
null
);
}
@@ -88,7 +89,8 @@ public TestSmartContractState(
IInternalTransactionExecutor transactionExecutor,
Func getBalance,
IInternalHashHelper hashHelper,
- IContractLogger contractLogger)
+ IContractLogger contractLogger,
+ IEcRecoverProvider ecRecoverProvider)
{
this.Block = block;
this.Message = message;
@@ -99,6 +101,7 @@ public TestSmartContractState(
this.GetBalance = getBalance;
this.InternalHashHelper = hashHelper;
this.ContractLogger = contractLogger;
+ this.EcRecoverProvider = ecRecoverProvider;
}
public IBlock Block { get; }
@@ -110,6 +113,7 @@ public TestSmartContractState(
public Func GetBalance { get; }
public IInternalHashHelper InternalHashHelper { get; }
public IContractLogger ContractLogger { get; }
+ public IEcRecoverProvider EcRecoverProvider { get; }
}
public class TestBlock : IBlock
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTestContext.cs b/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTestContext.cs
index fce7fe9b1c..85de0ef61d 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTestContext.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTestContext.cs
@@ -31,6 +31,7 @@ public class ContractExecutorTestContext
public IContractAssemblyCache ContractCache { get; }
public ReflectionVirtualMachine Vm { get; }
public ISmartContractStateFactory SmartContractStateFactory { get; }
+ public IEcRecoverProvider EcRecoverProvider { get; }
public StateProcessor StateProcessor { get; }
public Serializer Serializer { get; }
@@ -50,7 +51,8 @@ public ContractExecutorTestContext()
this.Vm = new ReflectionVirtualMachine(this.Validator, this.LoggerFactory, this.AssemblyLoader, this.ModuleDefinitionReader, this.ContractCache);
this.StateProcessor = new StateProcessor(this.Vm, this.AddressGenerator);
this.InternalTxExecutorFactory = new InternalExecutorFactory(this.LoggerFactory, this.StateProcessor);
- this.SmartContractStateFactory = new SmartContractStateFactory(this.ContractPrimitiveSerializer, this.InternalTxExecutorFactory, this.Serializer);
+ this.EcRecoverProvider = new EcRecoverProvider();
+ this.SmartContractStateFactory = new SmartContractStateFactory(this.ContractPrimitiveSerializer, this.InternalTxExecutorFactory, this.Serializer, this.EcRecoverProvider);
}
}
}
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTests.cs b/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTests.cs
index a17cb0059b..f4bf09a20a 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ContractExecutorTests.cs
@@ -41,6 +41,7 @@ public sealed class ContractExecutorTests
private readonly IStateProcessor stateProcessor;
private readonly ISmartContractStateFactory smartContractStateFactory;
private readonly ISerializer serializer;
+ private readonly IEcRecoverProvider ecRecoverProvider;
public ContractExecutorTests()
{
@@ -60,7 +61,8 @@ public ContractExecutorTests()
this.vm = new ReflectionVirtualMachine(this.validator, this.loggerFactory, this.assemblyLoader, this.moduleDefinitionReader, this.contractCache);
this.stateProcessor = new StateProcessor(this.vm, this.addressGenerator);
this.internalTxExecutorFactory = new InternalExecutorFactory(this.loggerFactory, this.stateProcessor);
- this.smartContractStateFactory = new SmartContractStateFactory(this.contractPrimitiveSerializer, this.internalTxExecutorFactory, this.serializer);
+ this.ecRecoverProvider = new EcRecoverProvider();
+ this.smartContractStateFactory = new SmartContractStateFactory(this.contractPrimitiveSerializer, this.internalTxExecutorFactory, this.serializer, this.ecRecoverProvider);
this.callDataSerializer = new CallDataSerializer(this.contractPrimitiveSerializer);
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ContractLogHolderTests.cs b/src/Stratis.SmartContracts.CLR.Tests/ContractLogHolderTests.cs
index a76d10c283..d4dfdd6af1 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ContractLogHolderTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ContractLogHolderTests.cs
@@ -29,11 +29,11 @@ public void Store_Structs_And_Get_Logs()
var contractAddress1 = new uint160(1);
var contractAddress2 = new uint160(2);
- var state1 = new TestSmartContractState(null, new TestMessage { ContractAddress = contractAddress1.ToAddress() }, null, null, null, null, null, null, null);
+ var state1 = new TestSmartContractState(null, new TestMessage { ContractAddress = contractAddress1.ToAddress() }, null, null, null, null, null, null, null, null);
var log1 = new Example1("Jordan", 12345);
var log2 = new Example1("John", 123);
- var state2 = new TestSmartContractState(null, new TestMessage { ContractAddress = contractAddress2.ToAddress() }, null, null, null, null, null, null, null);
+ var state2 = new TestSmartContractState(null, new TestMessage { ContractAddress = contractAddress2.ToAddress() }, null, null, null, null, null, null, null, null);
var log3 = new Example2("0x95D34980095380851902ccd9A1Fb4C813C2cb639".HexToAddress(), 16, "This is a test message.");
this.logHolder.Log(state1, log1);
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ObserverInstanceRewriterTests.cs b/src/Stratis.SmartContracts.CLR.Tests/ObserverInstanceRewriterTests.cs
index b43b4ccb6c..c62ae9aafc 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ObserverInstanceRewriterTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ObserverInstanceRewriterTests.cs
@@ -128,7 +128,8 @@ public ObserverInstanceRewriterTests()
new ContractLogHolder(),
Mock.Of(),
new InternalHashHelper(),
- () => 1000);
+ () => 1000,
+ Mock.Of());
this.rewriter = new ObserverInstanceRewriter();
}
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ObserverTests.cs b/src/Stratis.SmartContracts.CLR.Tests/ObserverTests.cs
index 9e4896992a..7b194e7b43 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ObserverTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ObserverTests.cs
@@ -127,7 +127,8 @@ public ObserverTests()
new ContractLogHolder(),
Mock.Of(),
new InternalHashHelper(),
- () => 1000);
+ () => 1000,
+ Mock.Of());
this.rewriter = new ObserverRewriter(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit)));
}
diff --git a/src/Stratis.SmartContracts.CLR.Tests/ReflectionVirtualMachineTests.cs b/src/Stratis.SmartContracts.CLR.Tests/ReflectionVirtualMachineTests.cs
index 5920e692e8..cfd83ba90b 100644
--- a/src/Stratis.SmartContracts.CLR.Tests/ReflectionVirtualMachineTests.cs
+++ b/src/Stratis.SmartContracts.CLR.Tests/ReflectionVirtualMachineTests.cs
@@ -45,7 +45,8 @@ public ReflectionVirtualMachineTests()
new ContractLogHolder(),
Mock.Of(),
new InternalHashHelper(),
- () => 1000);
+ () => 1000,
+ Mock.Of());
this.gasMeter = new GasMeter((RuntimeObserver.Gas)50_000);
}
diff --git a/src/Stratis.SmartContracts.CLR.Validation/Stratis.SmartContracts.CLR.Validation.csproj b/src/Stratis.SmartContracts.CLR.Validation/Stratis.SmartContracts.CLR.Validation.csproj
index a1640e41ac..f348678c6d 100644
--- a/src/Stratis.SmartContracts.CLR.Validation/Stratis.SmartContracts.CLR.Validation.csproj
+++ b/src/Stratis.SmartContracts.CLR.Validation/Stratis.SmartContracts.CLR.Validation.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Stratis.SmartContracts.CLR/EcRecoverProvider.cs b/src/Stratis.SmartContracts.CLR/EcRecoverProvider.cs
new file mode 100644
index 0000000000..61bad66b22
--- /dev/null
+++ b/src/Stratis.SmartContracts.CLR/EcRecoverProvider.cs
@@ -0,0 +1,48 @@
+using NBitcoin;
+using NBitcoin.Crypto;
+using Stratis.SmartContracts.Core.Hashing;
+
+namespace Stratis.SmartContracts.CLR
+{
+ ///
+ /// Holds logic for the equivalent of the ECRECOVER opcode.
+ ///
+ /// This is static for now but when we know more about how we are going to use it we will adjust as necessary.
+ ///
+ public class EcRecoverProvider : IEcRecoverProvider
+ {
+ private static uint256 GetUint256FromMessage(byte[] message)
+ {
+ return new uint256(HashHelper.Keccak256(message));
+ }
+
+ ///
+ /// Retrieves the base58 address of the signer of an ECDSA signature.
+ ///
+ ///
+ /// The ECDSA signature prepended with header information specifying the correct value of recId.
+ /// The base58 address for the signer of a signature.
+ public Address GetSigner(byte[] message, byte[] signature)
+ {
+ // TODO: Error handling for incorrect signature format etc.
+
+ uint256 hashedUint256 = GetUint256FromMessage(message);
+ PubKey pubKey = PubKey.RecoverCompact(hashedUint256, signature);
+
+ return pubKey.Hash.ToBytes().ToAddress();
+ }
+
+ ///
+ /// Signs a message, returning an ECDSA signature.
+ ///
+ /// The private key used to sign the message.
+ /// The complete message to be signed.
+ /// The ECDSA signature prepended with header information specifying the correct value of recId.
+ public static byte[] SignMessage(Key privateKey, byte[] message)
+ {
+ uint256 hashedUint256 = GetUint256FromMessage(message);
+
+ return privateKey.SignCompact(hashedUint256);
+ }
+ }
+}
diff --git a/src/Stratis.SmartContracts.CLR/SmartContractState.cs b/src/Stratis.SmartContracts.CLR/SmartContractState.cs
index 4770fd6792..dc1b35bc80 100644
--- a/src/Stratis.SmartContracts.CLR/SmartContractState.cs
+++ b/src/Stratis.SmartContracts.CLR/SmartContractState.cs
@@ -15,7 +15,8 @@ public SmartContractState(
IContractLogger contractLogger,
IInternalTransactionExecutor internalTransactionExecutor,
IInternalHashHelper internalHashHelper,
- Func getBalance)
+ Func getBalance,
+ IEcRecoverProvider ecRecoverProvider)
{
this.Block = block;
this.Message = message;
@@ -25,6 +26,7 @@ public SmartContractState(
this.InternalTransactionExecutor = internalTransactionExecutor;
this.InternalHashHelper = internalHashHelper;
this.GetBalance = getBalance;
+ this.EcRecoverProvider = ecRecoverProvider;
}
public IBlock Block { get; }
@@ -34,6 +36,7 @@ public SmartContractState(
public IPersistentState PersistentState { get; }
public ISerializer Serializer { get; }
+ public IEcRecoverProvider EcRecoverProvider { get; }
public IContractLogger ContractLogger { get; }
diff --git a/src/Stratis.SmartContracts.CLR/SmartContractStateFactory.cs b/src/Stratis.SmartContracts.CLR/SmartContractStateFactory.cs
index 59f6eb6de7..74d35eaa43 100644
--- a/src/Stratis.SmartContracts.CLR/SmartContractStateFactory.cs
+++ b/src/Stratis.SmartContracts.CLR/SmartContractStateFactory.cs
@@ -9,13 +9,17 @@ public class SmartContractStateFactory : ISmartContractStateFactory
{
private readonly ISerializer serializer;
+ private readonly IEcRecoverProvider ecRecoverProvider;
+
public SmartContractStateFactory(IContractPrimitiveSerializer primitiveSerializer,
IInternalExecutorFactory internalTransactionExecutorFactory,
- ISerializer serializer)
+ ISerializer serializer,
+ IEcRecoverProvider ecRecoverProvider)
{
this.serializer = serializer;
this.PrimitiveSerializer = primitiveSerializer;
this.InternalTransactionExecutorFactory = internalTransactionExecutorFactory;
+ this.ecRecoverProvider = ecRecoverProvider;
}
public IContractPrimitiveSerializer PrimitiveSerializer { get; }
@@ -44,7 +48,8 @@ public ISmartContractState Create(IState state, RuntimeObserver.IGasMeter gasMet
contractLogger,
this.InternalTransactionExecutorFactory.Create(gasMeter, state),
new InternalHashHelper(),
- () => state.GetBalance(address));
+ () => state.GetBalance(address),
+ this.ecRecoverProvider);
return contractState;
}
diff --git a/src/Stratis.SmartContracts.IntegrationTests/ECRecoverTests.cs b/src/Stratis.SmartContracts.IntegrationTests/ECRecoverTests.cs
new file mode 100644
index 0000000000..0a3dacfda4
--- /dev/null
+++ b/src/Stratis.SmartContracts.IntegrationTests/ECRecoverTests.cs
@@ -0,0 +1,145 @@
+using System.Threading.Tasks;
+using Stratis.Bitcoin.Features.SmartContracts.Models;
+using Stratis.SmartContracts.CLR;
+using Stratis.SmartContracts.CLR.Compilation;
+using Stratis.SmartContracts.CLR.Serialization;
+using Stratis.SmartContracts.Core;
+using Stratis.SmartContracts.Tests.Common.MockChain;
+using Xunit;
+using Key = NBitcoin.Key;
+
+namespace Stratis.SmartContracts.IntegrationTests
+{
+ public class ECRecoverTests
+ {
+ // 2 things to test:
+
+ // 1) That we have the ECDSA code and can make it available.
+
+ [Fact]
+ public void CanSignAndRetrieveSender()
+ {
+ using (PoWMockChain chain = new PoWMockChain(1))
+ {
+ var network = chain.Nodes[0].CoreNode.FullNode.Network;
+ var privateKey = new Key();
+ Address address = privateKey.PubKey.GetAddress(network).ToString().ToAddress(network);
+ byte[] message = new byte[] {0x69, 0x76, 0xAA};
+
+ // Sign a message
+ byte[] offChainSignature = EcRecoverProvider.SignMessage(privateKey, message);
+
+ var ecRecover = new EcRecoverProvider();
+ // Get the address out of the signature
+ Address recoveredAddress = ecRecover.GetSigner(message, offChainSignature);
+
+ // Check that the address matches that generated from the private key.
+ Assert.Equal(address, recoveredAddress);
+ }
+ }
+
+ [Fact]
+ public void CanCallEcRecoverContractWithValidSignatureAsync()
+ {
+ using (PoWMockChain chain = new PoWMockChain(2))
+ {
+ var node1 = chain.Nodes[0];
+
+ node1.MineBlocks(1);
+
+ var network = chain.Nodes[0].CoreNode.FullNode.Network;
+
+ var privateKey = new Key();
+ string address = privateKey.PubKey.GetAddress(network).ToString();
+ byte[] message = new byte[] { 0x69, 0x76, 0xAA };
+ byte[] signature = EcRecoverProvider.SignMessage(privateKey, message);
+
+ // TODO: If the incorrect parameters are passed to the constructor, the contract does not get properly created ('Method does not exist on contract'), but a success response is still returned?
+
+ byte[] contract = ContractCompiler.CompileFile("SmartContracts/EcRecoverContract.cs").Compilation;
+ string[] createParameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) };
+ BuildCreateContractTransactionResponse createResult = node1.SendCreateContractTransaction(contract, 1, createParameters);
+
+ Assert.NotNull(createResult);
+ Assert.True(createResult.Success);
+
+ node1.WaitMempoolCount(1);
+ node1.MineBlocks(1);
+
+ string[] callParameters = new string[]
+ {
+ string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, message.ToHexString()),
+ string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, signature.ToHexString())
+ };
+
+ BuildCallContractTransactionResponse response = node1.SendCallContractTransaction("CheckThirdPartySignature", createResult.NewContractAddress, 1, callParameters);
+ Assert.NotNull(response);
+ Assert.True(response.Success);
+
+ node1.WaitMempoolCount(1);
+ node1.MineBlocks(1);
+
+ ReceiptResponse receipt = node1.GetReceipt(response.TransactionId.ToString());
+
+ Assert.NotNull(receipt);
+ Assert.True(receipt.Success);
+ Assert.Equal("True", receipt.ReturnValue);
+ }
+ }
+
+ [Fact]
+ public void CanCallEcRecoverContractWithInvalidSignatureAsync()
+ {
+ using (PoWMockChain chain = new PoWMockChain(2))
+ {
+ var node1 = chain.Nodes[0];
+
+ node1.MineBlocks(1);
+
+ var network = chain.Nodes[0].CoreNode.FullNode.Network;
+
+ var privateKey = new Key();
+ string address = privateKey.PubKey.GetAddress(network).ToString();
+ byte[] message = new byte[] { 0x69, 0x76, 0xAA };
+
+ // Make the signature with a key unrelated to the third party signer for the contract.
+ byte[] signature = EcRecoverProvider.SignMessage(new Key(), message);
+
+ // TODO: If the incorrect parameters are passed to the constructor, the contract does not get properly created ('Method does not exist on contract'), but a success response is still returned?
+
+ byte[] contract = ContractCompiler.CompileFile("SmartContracts/EcRecoverContract.cs").Compilation;
+ string[] createParameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) };
+ BuildCreateContractTransactionResponse createResult = node1.SendCreateContractTransaction(contract, 1, createParameters);
+
+ Assert.NotNull(createResult);
+ Assert.True(createResult.Success);
+
+ node1.WaitMempoolCount(1);
+ node1.MineBlocks(1);
+
+ string[] callParameters = new string[]
+ {
+ string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, message.ToHexString()),
+ string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, signature.ToHexString())
+ };
+
+ BuildCallContractTransactionResponse response = node1.SendCallContractTransaction("CheckThirdPartySignature", createResult.NewContractAddress, 1, callParameters);
+ Assert.NotNull(response);
+ Assert.True(response.Success);
+
+ node1.WaitMempoolCount(1);
+ node1.MineBlocks(1);
+
+ ReceiptResponse receipt = node1.GetReceipt(response.TransactionId.ToString());
+
+ Assert.NotNull(receipt);
+ Assert.True(receipt.Success);
+ Assert.Equal("False", receipt.ReturnValue);
+ }
+ }
+
+ // 2) That we can enable the method in new contracts without affecting the older contracts
+
+ // TODO
+ }
+}
diff --git a/src/Stratis.SmartContracts.IntegrationTests/PoW/SmartContractMinerTests.cs b/src/Stratis.SmartContracts.IntegrationTests/PoW/SmartContractMinerTests.cs
index d379e7120d..fd6187ddee 100644
--- a/src/Stratis.SmartContracts.IntegrationTests/PoW/SmartContractMinerTests.cs
+++ b/src/Stratis.SmartContracts.IntegrationTests/PoW/SmartContractMinerTests.cs
@@ -180,6 +180,7 @@ public class TestContext
private StateProcessor stateProcessor;
private SmartContractStateFactory smartContractStateFactory;
public IBlockExecutionResultCache executionCache;
+ private IEcRecoverProvider ecRecoverProvider;
public SmartContractPowConsensusFactory ConsensusFactory { get; private set; }
#endregion
@@ -348,7 +349,8 @@ private void InitializeSmartContractComponents(string callingMethod)
this.internalTxExecutorFactory = new InternalExecutorFactory(this.loggerFactory, this.stateProcessor);
this.primitiveSerializer = new ContractPrimitiveSerializer(this.network);
this.serializer = new Serializer(this.primitiveSerializer);
- this.smartContractStateFactory = new SmartContractStateFactory(this.primitiveSerializer, this.internalTxExecutorFactory, this.serializer);
+ this.ecRecoverProvider = new EcRecoverProvider();
+ this.smartContractStateFactory = new SmartContractStateFactory(this.primitiveSerializer, this.internalTxExecutorFactory, this.serializer, this.ecRecoverProvider);
this.stateFactory = new StateFactory(this.smartContractStateFactory);
this.ExecutorFactory = new ReflectionExecutorFactory(this.loggerFactory, this.callDataSerializer, this.refundProcessor, this.transferProcessor, this.stateFactory, this.stateProcessor, this.primitiveSerializer);
}
diff --git a/src/Stratis.SmartContracts.IntegrationTests/SmartContracts/EcRecoverContract.cs b/src/Stratis.SmartContracts.IntegrationTests/SmartContracts/EcRecoverContract.cs
new file mode 100644
index 0000000000..ecde22a2b4
--- /dev/null
+++ b/src/Stratis.SmartContracts.IntegrationTests/SmartContracts/EcRecoverContract.cs
@@ -0,0 +1,28 @@
+
+using Stratis.SmartContracts;
+
+public class EcRecoverContract : SmartContract
+{
+ public Address ThirdPartySigner
+ {
+ get
+ {
+ return this.PersistentState.GetAddress(nameof(this.ThirdPartySigner));
+ }
+ set
+ {
+ this.PersistentState.SetAddress(nameof(this.ThirdPartySigner), value);
+ }
+ }
+
+ public EcRecoverContract(ISmartContractState state, Address thirdPartySigner) : base(state)
+ {
+ this.ThirdPartySigner = thirdPartySigner;
+ }
+
+ public bool CheckThirdPartySignature(byte[] message, byte[] signature)
+ {
+ Address signerOfMessage = this.EcRecover(message, signature);
+ return (signerOfMessage == this.ThirdPartySigner);
+ }
+}
diff --git a/src/Stratis.SmartContracts.IntegrationTests/Stratis.SmartContracts.IntegrationTests.csproj b/src/Stratis.SmartContracts.IntegrationTests/Stratis.SmartContracts.IntegrationTests.csproj
index 671aa63789..dd50563b98 100644
--- a/src/Stratis.SmartContracts.IntegrationTests/Stratis.SmartContracts.IntegrationTests.csproj
+++ b/src/Stratis.SmartContracts.IntegrationTests/Stratis.SmartContracts.IntegrationTests.csproj
@@ -90,6 +90,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest