public static async Task Start([PerperTrigger] object?input, IContext context, IHashResolver hashResolver, IPeerConnector peerConnector) { var(executorAgent, _) = await context.StartAgentAsync <object?>("Apocryph-Executor", null); await executorAgent.CallActionAsync("Register", (Hash.From("AgentOne"), context.Agent, "AgentOne")); await executorAgent.CallActionAsync("Register", (Hash.From("AgentTwo"), context.Agent, "AgentTwo")); var agentStates = new[] { new AgentState(0, ReferenceData.From(new AgentOne.AgentOneState()), Hash.From("AgentOne")), new AgentState(1, ReferenceData.From(new AgentTwo.AgentTwoState()), Hash.From("AgentTwo")) }; var agentStatesTree = await MerkleTreeBuilder.CreateRootFromValues(hashResolver, agentStates, 2); Chain chain; if (Environment.GetEnvironmentVariable("SAMPLE_AGENTS_CONSENSUS") == "Dummy") { chain = new Chain(new ChainState(agentStatesTree, agentStates.Length), "Apocryph-DummyConsensus", null, 1); } else { var snowballParameters = await hashResolver.StoreAsync <object>(new SnowballParameters(15, 0.8, 25)); chain = new Chain(new ChainState(agentStatesTree, agentStates.Length), "Apocryph-SnowballConsensus", snowballParameters, 60); } var chainId = await hashResolver.StoreAsync(chain); var(_, kothStates) = await context.StartAgentAsync <IAsyncEnumerable <(Hash <Chain>, Slot?[])> >("Apocryph-KoTH", null); var minerAgentTask = context.StartAgentAsync <object?>("Apocryph-KoTH-SimpleMiner", (kothStates, new Hash <Chain>[] { chainId }));
public static async Task <MerkleTreeLeafBuilder <T>[]> CreateFromValues <T>(IHashResolver resolver, IEnumerable <T> values, int maxChildren) { var result = new List <MerkleTreeLeafBuilder <T> >(); foreach (var value in values) { var leaf = new MerkleTreeLeaf <T>(value); var hash = await resolver.StoreAsync <IMerkleTree <T> >(leaf); var builder = new MerkleTreeLeafBuilder <T>(leaf, hash); result.Add(builder); } var currentLayer = new Queue <IMerkleTreeBuilder <T> >(result); while (currentLayer.Count > 1) { var previousLayer = currentLayer; currentLayer = new Queue <IMerkleTreeBuilder <T> >((previousLayer.Count - 1) / maxChildren + 1); while (previousLayer.Count > 0) { if (previousLayer.Count == 1) { currentLayer.Enqueue(previousLayer.Dequeue()); // Optimization; we never want single-element nodes break; } var children = new IMerkleTreeBuilder <T> [Math.Min(previousLayer.Count, maxChildren)]; var hashes = new Hash <IMerkleTree <T> > [children.Length]; for (var i = 0; i < children.Length; i++) { children[i] = previousLayer.Dequeue(); hashes[i] = children[i].Hash; } var node = new MerkleTreeNode <T>(hashes); var hash = await resolver.StoreAsync <IMerkleTree <T> >(node); var builder = new MerkleTreeNodeBuilder <T>(node, hash); for (var i = 0; i < children.Length; i++) { children[i].Parent = builder; children[i].IndexInParent = i; } currentLayer.Enqueue(builder); } } return(result.ToArray()); }