Skip to content

Commit ba52f5e

Browse files
committed
* Option to specify the address that RPC server listens on (rather than only loopback).
* Support specifying account mnemonic in unit test template app.config & global setup.
1 parent ebd9f75 commit ba52f5e

File tree

7 files changed

+45
-16
lines changed

7 files changed

+45
-16
lines changed

src/Meadow.Cli/Commands/StartTestServerCommand.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected override void EndProcessing()
1818

1919
var config = this.ReadConfig();
2020

21-
var testNodeServer = new TestNodeServer((int)config.NetworkPort, new AccountConfiguration
21+
var testNodeServer = new TestNodeServer(port: (int)config.NetworkPort, accountConfig: new AccountConfiguration
2222
{
2323
AccountGenerationCount = config.AccountCount,
2424
DefaultAccountEtherBalance = config.AccountBalance

src/Meadow.JsonRpc.Server.Proxy/RpcServerProxy.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Net;
45
using System.Text;
56
using System.Threading.Tasks;
67
using Meadow.Core.EthTypes;
@@ -21,10 +22,10 @@ public class RpcServerProxy : IRpcController, IDisposable
2122

2223
public IWebHost WebHost => _httpServer.WebHost;
2324

24-
public RpcServerProxy(Uri targetHost, int? proxyServerPort = null)
25+
public RpcServerProxy(Uri targetHost, int? proxyServerPort = null, IPAddress address = null)
2526
{
2627
_proxyClient = JsonRpcClient.Create(targetHost, ArbitraryDefaults.DEFAULT_GAS_LIMIT, ArbitraryDefaults.DEFAULT_GAS_PRICE);
27-
_httpServer = new JsonRpcHttpServer(_proxyClient, ConfigureWebHost, proxyServerPort);
28+
_httpServer = new JsonRpcHttpServer(_proxyClient, ConfigureWebHost, proxyServerPort, address);
2829

2930
//var undefinedRpcMethods = this.GetUndefinedRpcMethods();
3031
//Console.WriteLine("Warning: following RPC methods are not defined: \n" + string.Join(", ", undefinedRpcMethods.Select(r => r.Value())));

src/Meadow.JsonRpc.Server/JsonRpcHttpServer.cs

+10-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class JsonRpcHttpServer : IDisposable
3636
public string[] ServerAddresses => _serverAddressFeature().Addresses.ToArray();
3737

3838
public int ServerPort => GetServerPort();
39+
public Uri ServerAddress => GetServerHostAddress();
3940

4041
Func<IServerAddressesFeature> _serverAddressFeature;
4142
IRpcController _serverHandler;
@@ -55,7 +56,7 @@ public RpcRequestItem(JObject requestMessage)
5556

5657

5758
/// <param name="port">If null or unspecified the http server binds to a random port.</param>
58-
public JsonRpcHttpServer(IRpcController serverHandler, Func<IWebHostBuilder, IWebHostBuilder> configure = null, int? port = null)
59+
public JsonRpcHttpServer(IRpcController serverHandler, Func<IWebHostBuilder, IWebHostBuilder> configure = null, int? port = null, IPAddress address = null)
5960
{
6061
_serverHandler = serverHandler;
6162
var webHostBuilder = new WebHostBuilder()
@@ -68,7 +69,7 @@ public JsonRpcHttpServer(IRpcController serverHandler, Func<IWebHostBuilder, IWe
6869
.UseSockets()
6970
.UseKestrel(options =>
7071
{
71-
options.Listen(IPAddress.Loopback, port ?? 0);
72+
options.Listen(address ?? IPAddress.Loopback, port ?? 0);
7273
//options.Listen(port ?? 0);
7374
});
7475

@@ -99,8 +100,7 @@ public JsonRpcHttpServer(IRpcController serverHandler, Func<IWebHostBuilder, IWe
99100

100101
public void Stop() => WebHost.StopAsync().GetAwaiter().GetResult();
101102

102-
103-
int GetServerPort()
103+
Uri GetServerHostAddress()
104104
{
105105
var addrs = ServerAddresses;
106106
if (addrs.Length == 0)
@@ -109,9 +109,12 @@ int GetServerPort()
109109
}
110110

111111
var httpAddr = addrs.FirstOrDefault(addr => addr.StartsWith("http://", StringComparison.OrdinalIgnoreCase));
112-
var addrParts = httpAddr.Split(':')[2];
113-
var port = int.Parse(addrParts, CultureInfo.InvariantCulture);
114-
return port;
112+
return new Uri(httpAddr);
113+
}
114+
115+
int GetServerPort()
116+
{
117+
return GetServerHostAddress().Port;
115118
}
116119

117120
async Task Handle(HttpContext context, Func<Task> next)

src/Meadow.TestNode/AccountConfiguration.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ public class AccountConfiguration
1919
/// <summary>
2020
/// The specification/format to use for generating accounts from the seed.
2121
/// Defaults to <see cref="Bip44AccountDerivation"/>
22-
/// TODO: Currently defaults to the C# rng with fixed seed until bip44 is implemented.
2322
/// </summary>
24-
public IAccountDerivation AccountDerivationMethod { get; set; } = new SystemRandomAccountDerivation(1234);
23+
public IAccountDerivation AccountDerivationMethod { get; set; }
2524

2625
}
2726
}

src/Meadow.TestNode/TestNodeServer.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
using Meadow.Core.Cryptography.Ecdsa;
2626
using Meadow.Core.Cryptography;
2727
using Meadow.Core.RlpEncoding;
28+
using System.Net;
29+
using Meadow.Core.AccountDerivation;
2830

2931
namespace Meadow.TestNode
3032
{
@@ -54,10 +56,10 @@ static TestNodeServer()
5456
#region Constructor
5557
/// <param name="port">If null or unspecified the http server binds to a random port.</param>
5658
/// <param name="accountConfig">Configure number of accounts to generate, ether balance, wallet derivation method.</param>
57-
public TestNodeServer(int? port = null, AccountConfiguration accountConfig = null)
59+
public TestNodeServer(int? port = null, IPAddress address = null, AccountConfiguration accountConfig = null)
5860
{
5961
// Initialize our basic components.
60-
RpcServer = new JsonRpcHttpServer(this, ConfigureWebHost, port);
62+
RpcServer = new JsonRpcHttpServer(this, ConfigureWebHost, port, address);
6163
AccountKeys = new List<Address>();
6264
AccountDictionary = new Dictionary<Address, EthereumEcdsa>();
6365
Snapshots = new Dictionary<ulong, (StateSnapshot snapshot, TimeSpan timeStampOffset)>();
@@ -70,8 +72,10 @@ public TestNodeServer(int? port = null, AccountConfiguration accountConfig = nul
7072
accountConfig = (accountConfig ?? new AccountConfiguration());
7173
BigInteger initialAccountBalance = new BigInteger(1e18M * accountConfig.DefaultAccountEtherBalance);
7274

75+
var accountDerivation = accountConfig.AccountDerivationMethod ?? HDAccountDerivation.Create();
76+
7377
// Generate a keypairs
74-
foreach (var keypair in EthereumEcdsa.Generate(accountConfig.AccountGenerationCount, accountConfig.AccountDerivationMethod))
78+
foreach (var keypair in EthereumEcdsa.Generate(accountConfig.AccountGenerationCount, accountDerivation))
7579
{
7680
// Get an account from the public key hash.
7781
Meadow.EVM.Data_Types.Addressing.Address account = new Meadow.EVM.Data_Types.Addressing.Address(keypair.GetPublicKeyHash());

src/Meadow.UnitTestTemplate/Global.cs

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Meadow.Contract;
2+
using Meadow.Core.AccountDerivation;
23
using Meadow.Core.Utils;
34
using Meadow.CoverageReport;
45
using Meadow.CoverageReport.Debugging;
@@ -73,6 +74,14 @@ public static class Global
7374
[System.ComponentModel.Description("TODO")]
7475
public static long? AccountBalance { get; set; }
7576

77+
/// <summary>
78+
/// Initially populated by app.config (if set).
79+
/// Defaults to a randomly generated mnemonic if not set.
80+
/// </summary>
81+
[DefaultValue(null), DisplayName("AccountMnemonic")]
82+
[System.ComponentModel.Description("TODO")]
83+
public static string AccountMnemonic { get; set; }
84+
7685
/// <summary>
7786
/// Initially populated by app.config (if set). Describes the endpoint of an external node
7887
/// to connect to and tests against.
@@ -201,6 +210,11 @@ static void ParseAppConfigSettings(Assembly callingAssembly)
201210
() => AccountBalance,
202211
str => int.Parse(str, NumberStyles.AllowThousands, CultureInfo.InvariantCulture));
203212

213+
SetupConfigValue(
214+
configValueList,
215+
() => AccountMnemonic,
216+
str => str);
217+
204218
SetupConfigValue(
205219
configValueList,
206220
() => SolcVersion,
@@ -319,11 +333,18 @@ static bool TryGetAppConfigValue(string key, out string value)
319333

320334
public static async Task<TestServices> CreateTestServicesInstance()
321335
{
336+
// Setup account derivation / keys.
337+
var mnemonic = AccountMnemonic ?? AttributeHelper.GetDefault(() => AccountMnemonic);
338+
var accountDerivation = string.IsNullOrWhiteSpace(mnemonic)
339+
? HDAccountDerivation.Create()
340+
: new HDAccountDerivation(mnemonic);
341+
322342
// Create our local test node.
323343
var accountConfig = new AccountConfiguration
324344
{
325345
AccountGenerationCount = AccountCount ?? AttributeHelper.GetDefault(() => AccountCount),
326-
DefaultAccountEtherBalance = AccountBalance ?? AttributeHelper.GetDefault(() => AccountBalance)
346+
DefaultAccountEtherBalance = AccountBalance ?? AttributeHelper.GetDefault(() => AccountBalance),
347+
AccountDerivationMethod = accountDerivation
327348
};
328349

329350
var testNodeServer = new TestNodeServer(accountConfig: accountConfig);

src/Meadow.UnitTestTemplate/MeadowTestMethodAttribute.cs

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public static TestResult[] Execute(ITestMethod testMethod)
6262
}
6363

6464
}
65+
6566
// Test only has description, use in display name
6667
else if (desc != null)
6768
{

0 commit comments

Comments
 (0)