Skip to content

Commit

Permalink
Use repositories instead of BlockChain in some parts
Browse files Browse the repository at this point in the history
  • Loading branch information
moreal committed Sep 5, 2024
1 parent fccbd83 commit 68bf45f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 109 deletions.
42 changes: 4 additions & 38 deletions NineChronicles.Headless/GraphTypes/NodeStatus.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using GraphQL;
using GraphQL.Types;
using Libplanet.Blockchain;
using Libplanet.Crypto;
using Libplanet.Types.Blocks;
using Libplanet.Explorer.GraphTypes;
Expand All @@ -10,6 +9,7 @@
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using NineChronicles.Headless.Repositories;

namespace NineChronicles.Headless.GraphTypes
{
Expand All @@ -28,7 +28,7 @@ public class NodeStatusType : ObjectGraphType<NodeStatusType>

public bool IsMining { get; set; }

public NodeStatusType(StandaloneContext context)
public NodeStatusType(StandaloneContext context, IBlockChainRepository blockChainRepository)
{
Field<NonNullGraphType<BooleanGraphType>>(
name: "bootstrapEnded",
Expand All @@ -43,9 +43,7 @@ public NodeStatusType(StandaloneContext context)
Field<NonNullGraphType<BlockHeaderType>>(
name: "tip",
description: "Block header of the tip block from the current canonical chain.",
resolve: _ => context.BlockChain is { } blockChain
? BlockHeaderType.FromBlock(blockChain.Tip)
: null
resolve: _ => BlockHeaderType.FromBlock(blockChainRepository.GetTip())
);
Field<NonNullGraphType<ListGraphType<BlockHeaderType>>>(
name: "topmostBlocks",
Expand All @@ -72,13 +70,8 @@ public NodeStatusType(StandaloneContext context)
description: "The topmost blocks from the current node.",
resolve: fieldContext =>
{
if (context.BlockChain is null)
{
throw new InvalidOperationException($"{nameof(context.BlockChain)} is null.");
}

IEnumerable<Block> blocks =
GetTopmostBlocks(context.BlockChain, fieldContext.GetArgument<int>("offset"));
blockChainRepository.IterateBlocksDescending(fieldContext.GetArgument<int>("offset"));
if (fieldContext.GetArgument<Address?>("miner") is { } miner)
{
blocks = blocks.Where(b => b.Miner.Equals(miner));
Expand Down Expand Up @@ -173,32 +166,5 @@ context.BlockChain is { } blockChain
resolve: _ => _informationalVersion
);
}

private IEnumerable<Block> GetTopmostBlocks(BlockChain blockChain, int offset)
{
Block block = blockChain.Tip;

while (offset > 0)
{
offset--;
if (block.PreviousHash is { } prev)
{
block = blockChain[prev];
}
}

while (true)
{
yield return block;
if (block.PreviousHash is { } prev)
{
block = blockChain[prev];
}
else
{
break;
}
}
}
}
}
103 changes: 32 additions & 71 deletions NineChronicles.Headless/GraphTypes/StandaloneQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System.Security.Cryptography;
using System.Text;
using Libplanet.Store.Trie;
using NineChronicles.Headless.Repositories;
using static NineChronicles.Headless.NCActionUtils;
using Transaction = Libplanet.Types.Tx.Transaction;

Expand All @@ -37,7 +38,7 @@ public class StandaloneQuery : ObjectGraphType
{
private static readonly ActivitySource ActivitySource = new ActivitySource("NineChronicles.Headless.GraphTypes.StandaloneQuery");

public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration configuration, ActionEvaluationPublisher publisher, StateMemoryCache stateMemoryCache)
public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration configuration, ActionEvaluationPublisher publisher, StateMemoryCache stateMemoryCache, IWorldStateRepository worldStateRepository, IBlockChainRepository blockChainRepository)
{
bool useSecretToken = configuration[GraphQLService.SecretTokenKey] is { };
if (Convert.ToBoolean(configuration.GetSection("Jwt")["EnableJwtAuthentication"]))
Expand All @@ -59,28 +60,18 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi
resolve: context =>
{
using var activity = ActivitySource.StartActivity("stateQuery");
BlockHash blockHash = (context.GetArgument<byte[]?>("hash"), context.GetArgument<long?>("index")) switch
Block block = (context.GetArgument<byte[]?>("hash"), context.GetArgument<long?>("index")) switch
{
({ } bytes, null) => new BlockHash(bytes),
(null, { } index) => standaloneContext.BlockChain[index].Hash,
({ } bytes, null) => blockChainRepository.GetBlock(new BlockHash(bytes)),
(null, { } index) => blockChainRepository.GetBlock(index),
(not null, not null) => throw new ArgumentException("Only one of 'hash' and 'index' must be given."),
(null, null) => standaloneContext.BlockChain.Tip.Hash,
(null, null) => blockChainRepository.GetTip(),
};
activity?.AddTag("BlockHash", blockHash.ToString());

if (!(standaloneContext.BlockChain is { } chain))
{
return null;
}

if (!(blockHash is { } hash))
{
return null;
}
activity?.AddTag("BlockHash", block.Hash.ToString());

return new StateContext(
chain.GetWorldState(blockHash),
chain[blockHash].Index,
worldStateRepository.GetWorldState(block.StateRootHash),
block.Index,
stateMemoryCache
);
}
Expand Down Expand Up @@ -108,13 +99,6 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi
resolve: context =>
{
using var activity = ActivitySource.StartActivity("diffs");
if (!(standaloneContext.BlockChain is BlockChain blockChain))
{
throw new ExecutionError(
$"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!"
);
}

var baseIndex = context.GetArgument<long>("baseIndex");
var changedIndex = context.GetArgument<long>("changedIndex");

Expand All @@ -126,8 +110,8 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi
);
}

var baseBlockStateRootHash = blockChain[baseIndex].StateRootHash.ToString();
var changedBlockStateRootHash = blockChain[changedIndex].StateRootHash.ToString();
var baseBlockStateRootHash = blockChainRepository.GetBlock(baseIndex).StateRootHash.ToString();
var changedBlockStateRootHash = blockChainRepository.GetBlock(changedIndex).StateRootHash.ToString();

var baseStateRootHash = HashDigest<SHA256>.FromString(baseBlockStateRootHash);
var targetStateRootHash = HashDigest<SHA256>.FromString(
Expand Down Expand Up @@ -201,13 +185,6 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi
resolve: context =>
{
using var activity = ActivitySource.StartActivity("accountDiffs");
if (!(standaloneContext.BlockChain is BlockChain blockChain))
{
throw new ExecutionError(
$"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!"
);
}

var baseIndex = context.GetArgument<long>("baseIndex");
var changedIndex = context.GetArgument<long>("changedIndex");
var accountAddress = context.GetArgument<Address>("accountAddress");
Expand All @@ -220,8 +197,8 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi
);
}

var baseBlockStateRootHash = blockChain[baseIndex].StateRootHash.ToString();
var changedBlockStateRootHash = blockChain[changedIndex].StateRootHash.ToString();
var baseBlockStateRootHash = blockChainRepository.GetBlock(baseIndex).StateRootHash.ToString();
var changedBlockStateRootHash = blockChainRepository.GetBlock(changedIndex).StateRootHash.ToString();

var baseStateRootHash = HashDigest<SHA256>.FromString(baseBlockStateRootHash);
var targetStateRootHash = HashDigest<SHA256>.FromString(
Expand Down Expand Up @@ -267,29 +244,22 @@ Binary GetAccountState(ITrie model, KeyBytes key)
resolve: context =>
{
using var activity = ActivitySource.StartActivity("state");
if (!(standaloneContext.BlockChain is BlockChain blockChain))
{
throw new ExecutionError(
$"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
}

var blockHash = (context.GetArgument<byte[]?>("hash"), context.GetArgument<long?>("index")) switch
var block = (context.GetArgument<byte[]?>("hash"), context.GetArgument<long?>("index")) switch
{
(not null, not null) => throw new ArgumentException(
"Only one of 'hash' and 'index' must be given."),
(null, { } index) => blockChain[index].Hash,
({ } bytes, null) => new BlockHash(bytes),
(null, null) => blockChain.Tip.Hash,
(null, { } index) => blockChainRepository.GetBlock(index),
({ } bytes, null) => blockChainRepository.GetBlock(new BlockHash(bytes)),
(null, null) => blockChainRepository.GetTip(),
};
var accountAddress = context.GetArgument<Address>("accountAddress");
var address = context.GetArgument<Address>("address");

activity?
.AddTag("BlockHash", blockHash.ToString())
.AddTag("BlockHash", block.Hash.ToString())
.AddTag("Address", address.ToString());

var state = blockChain
.GetWorldState(blockHash)
var state = worldStateRepository
.GetWorldState(block.StateRootHash)
.GetAccountState(accountAddress)
.GetState(address);

Expand Down Expand Up @@ -377,7 +347,7 @@ Binary GetAccountState(ITrie model, KeyBytes key)
resolve: _ =>
{
using var activity = ActivitySource.StartActivity("nodeStatus");
return new NodeStatusType(standaloneContext);
return new NodeStatusType(standaloneContext, blockChainRepository);
});

Field<NonNullGraphType<Libplanet.Explorer.Queries.ExplorerQuery>>(
Expand Down Expand Up @@ -412,26 +382,21 @@ Binary GetAccountState(ITrie model, KeyBytes key)
resolve: context =>
{
using var activity = ActivitySource.StartActivity("goldBalance");
if (!(standaloneContext.BlockChain is BlockChain blockChain))
{
throw new ExecutionError(
$"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
}

Address address = context.GetArgument<Address>("address");
byte[] blockHashByteArray = context.GetArgument<byte[]>("hash");
var blockHash = blockHashByteArray is null
? blockChain.Tip.Hash
: new BlockHash(blockHashByteArray);
var block = blockHashByteArray is null
? blockChainRepository.GetTip()
: blockChainRepository.GetBlock(new BlockHash(blockHashByteArray));
var worldState = worldStateRepository.GetWorldState(block.StateRootHash);
Currency currency = new GoldCurrencyState(
(Dictionary)blockChain.GetWorldState(blockHash).GetLegacyState(GoldCurrencyState.Address)
(Dictionary)worldState
.GetLegacyState(GoldCurrencyState.Address)
).Currency;

activity?
.AddTag("BlockHash", blockHash.ToString())
.AddTag("BlockHash", block.Hash.ToString())
.AddTag("Address", address.ToString());

return blockChain.GetWorldState(blockHash).GetBalance(
return worldState.GetBalance(
address,
currency
).GetQuantityString();
Expand Down Expand Up @@ -629,12 +594,6 @@ Binary GetAccountState(ITrie model, KeyBytes key)
),
resolve: context =>
{
if (!(standaloneContext.BlockChain is { } blockChain))
{
throw new ExecutionError(
$"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
}

ActivationKey activationKey;
try
{
Expand All @@ -646,7 +605,9 @@ Binary GetAccountState(ITrie model, KeyBytes key)
{
throw new ExecutionError("invitationCode format is invalid.");
}
if (blockChain.GetWorldState().GetLegacyState(activationKey.PendingAddress) is Dictionary dictionary)

var worldState = worldStateRepository.GetWorldState(blockChainRepository.GetTip().StateRootHash);
if (worldState.GetLegacyState(activationKey.PendingAddress) is Dictionary dictionary)
{
var pending = new PendingActivationState(dictionary);
return ByteUtil.Hex(pending.Nonce);
Expand Down

0 comments on commit 68bf45f

Please sign in to comment.