public static async Task Run([PerperStreamTrigger] PerperStreamContext context, [Perper("self")] ValidatorKey self, [PerperStream("inputStream")] IAsyncEnumerable <IHashed <AgentInput> > inputStream, [PerperStream("outputStream")] IAsyncCollector <AgentOutput> outputStream, CancellationToken cancellationToken, ILogger logger) { await inputStream.ForEachAsync(async input => { try { var agentContext = await context.CallWorkerAsync <AgentContext <object> >(nameof(RuntimeWorker), new { state = input.Value.State, sender = new AgentCapability(input.Value.Sender), message = input.Value.Message }, cancellationToken); await outputStream.AddAsync(new AgentOutput { Previous = input.Hash, State = agentContext.State, Commands = agentContext.Commands }, cancellationToken); } catch (Exception e) { logger.LogError(e.ToString()); } }, cancellationToken); }
public static async Task Run([PerperStreamTrigger] PerperStreamContext context, [Perper("self")] ValidatorKey self, [PerperStream("stepsStream")] IAsyncEnumerable <IHashed <IAgentStep> > stepsStream, [PerperStream("currentProposerStream")] IAsyncEnumerable <ValidatorKey> currentProposerStream, [PerperStream("outputStream")] IAsyncCollector <IHashed <IAgentStep> > outputStream) { var state = await context.FetchStateAsync <State>() ?? new State(); async Task processPending() { if (state.LastProposer != null && state.LastProposer.Equals(self) && state.LastCommit != null) { await outputStream.AddAsync(state.LastCommit); state.LastCommit = null; // Do not produce the same commit twice state.LastProposer = null; // Do not produce the next commit before the proposer is updated } }; await Task.WhenAll( currentProposerStream.ForEachAsync(async currentProposer => { state.LastProposer = currentProposer; await processPending(); await context.UpdateStateAsync(state); }, CancellationToken.None), stepsStream.ForEachAsync(async commit => { state.LastCommit = commit; await processPending(); await context.UpdateStateAsync(state); }, CancellationToken.None)); }
public virtual Validator <T> NewValidator <T>(ValidatorOptions options) { var key = new ValidatorKey() { validatorType = typeof(T), validatorOptions = options }; Validator <T> retval; if (!ValidatorCacheContainer <T> .validators.TryGetValue(key, out retval)) { retval = DoNewValidator <T>(options); var newValidators = new Dictionary <ValidatorKey, Validator <T> >(); foreach (var keyValue in ValidatorCacheContainer <T> .validators) { newValidators[keyValue.Key] = keyValue.Value; } newValidators[key] = retval; ValidatorCacheContainer <T> .validators = newValidators; } return(retval); }
public static async Task Run([PerperStreamTrigger] PerperStreamContext context, [Perper("self")] ValidatorKey self, [Perper("privateKey")] ECParameters privateKey, [PerperStream("dataStream")] IAsyncEnumerable <object> dataStream, [PerperStream("outputStream")] IAsyncCollector <ISigned <object> > outputStream) { await dataStream.ForEachAsync(async item => { var bytes = IpfsJsonSettings.ObjectToBytes(item); var signature = ValidatorKey.GenerateSignature(privateKey, bytes); await outputStream.AddAsync(Signed.Create(item, self, signature)); }, CancellationToken.None); }
public static async Task Run([PerperStreamTrigger] PerperStreamContext context, CancellationToken cancellationToken) { ECParameters privateKey; ValidatorKey self; using (var dsa = ECDsa.Create()) { privateKey = dsa.ExportParameters(true); self = new ValidatorKey { Key = dsa.ExportParameters(false) }; } var ipfsGateway = "http://127.0.0.1:5001"; await using var agentZeroStream = await context.StreamFunctionAsync(nameof (IpfsInput), new { ipfsGateway, topic = "apocryph-agent-0" }); await using var _inputVerifierStream = await context.StreamFunctionAsync(nameof (StepSignatureVerifier), new { stepsStream = agentZeroStream, }); await using var inputVerifierStream = await context.StreamFunctionAsync(nameof (IpfsLoader), new { ipfsGateway, hashStream = _inputVerifierStream }); await using var validatorSetsStream = await context.StreamFunctionAsync(nameof (ValidatorSets), new { inputVerifierStream }); await using var validatorSchedulerStream = await context.StreamActionAsync(nameof (ValidatorScheduler), new { validatorSetsStream, ipfsGateway, privateKey, self }); await context.BindOutput(cancellationToken); }
public static async Task Run([PerperStreamTrigger(RunOnStartup = true)] PerperStreamContext context, CancellationToken cancellationToken) { var keys = new List <(ECParameters, ValidatorKey)>(); var validatorSet = new ValidatorSet(); for (var i = 0; i < 1; i++) { using var dsa = ECDsa.Create(ECCurve.NamedCurves.nistP521); var privateKey = dsa.ExportParameters(true); var publicKey = new ValidatorKey { Key = dsa.ExportParameters(false) }; keys.Add((privateKey, publicKey)); validatorSet.Weights.Add(publicKey, 10); } var ipfsGateway = "http://127.0.0.1:5001"; await using var _validatorSetsStream = await context.StreamFunctionAsync("TestDataGenerator", new { delay = TimeSpan.FromSeconds(20), data = validatorSet }); await using var validatorSetsStream = await context.StreamFunctionAsync(nameof (IpfsSaver), new { ipfsGateway, dataStream = _validatorSetsStream }); await using var validatorLauncherStreams = new AsyncDisposableList(); foreach (var(privateKey, self) in keys) { validatorLauncherStreams.Add( await context.StreamActionAsync(nameof(ValidatorLauncher), new { agentId = "0", services = new [] { "Sample", "IpfsInput" }, validatorSetsStream, ipfsGateway, privateKey, self })); } await context.BindOutput(cancellationToken); }
public static async Task Run([PerperStreamTrigger] PerperStreamContext context, [PerperStream("validatorSetsStream")] IAsyncEnumerable <Dictionary <string, ValidatorSet> > validatorSetsStream, [Perper("ipfsGateway")] string ipfsGateway, [Perper("privateKey")] ECParameters privateKey, [Perper("self")] ValidatorKey self) { var runningStreams = new Dictionary <KeyValuePair <string, ValidatorSet>, IAsyncDisposable>(); await validatorSetsStream.ForEachAsync(async validatorSets => { // FIXME: Instead of restarting when validator set changes, send validator sets as a seperate stream var filteredValidatorSets = validatorSets .Where(kv => kv.Value.Weights.ContainsKey(self)); var toStop = new HashSet <KeyValuePair <string, ValidatorSet> >(runningStreams.Keys); foreach (var kv in filteredValidatorSets) { toStop.Remove(kv); if (!runningStreams.ContainsKey(kv)) { var agentId = kv.Key; var validatorSet = kv.Value; runningStreams[kv] = await context.StreamActionAsync(nameof(ValidatorLauncher), new { ipfsGateway, agentId = agentId, validatorSet = validatorSet, privateKey, self }); } } foreach (var kv in toStop) { await runningStreams[kv].DisposeAsync(); runningStreams.Remove(kv); } }, CancellationToken.None); }
public static async Task Run([PerperStreamTrigger] PerperStreamContext context, [Perper("agentId")] string agentId, [Perper("services")] string[] services, [Perper("validatorSetsStream")] object[] validatorSetsStream, [Perper("ipfsGateway")] string ipfsGateway, [Perper("privateKey")] ECParameters privateKey, [Perper("self")] ValidatorKey self, CancellationToken cancellationToken) { var genesisMessage = ("", (object)new InitMessage()); await using var validatorSchedulerStream = await context.StreamActionAsync(nameof (PBFTConsensus), new { agentId, services, validatorSetsStream, genesisMessage, ipfsGateway, privateKey, self }); await context.BindOutput(cancellationToken); }
public static void SubscribeUserInput(this IAgentContext context, ValidatorKey key) { context.SendServiceMessage("IpfsInput", key); }