diff --git a/Libplanet.Action/State/IBlockChainStates.cs b/Libplanet.Action/State/IBlockChainStates.cs
index 716330dc652..09e1b257ce9 100644
--- a/Libplanet.Action/State/IBlockChainStates.cs
+++ b/Libplanet.Action/State/IBlockChainStates.cs
@@ -103,9 +103,7 @@ public interface IBlockChainStates
/// The of the to fetch
/// the state from.
/// The state associated to specified .
- /// An absent state is represented as . The returned value
- /// must be the same as the single element when retrieved via
- /// .
+ /// An absent state is represented as .
///
/// Thrown when is not
/// and one of the following is true.
@@ -119,10 +117,6 @@ public interface IBlockChainStates
///
///
///
- ///
- /// For performance reasons, it is generally recommended to use
- /// with a batch of es instead of iterating over this method.
- ///
IValue? GetState(Address address, Address accountAddress, BlockHash? offset);
///
@@ -142,52 +136,115 @@ public interface IBlockChainStates
///
/// The owner to query.
/// The currency type to query.
+ /// The account to query from.
/// The of the to fetch
/// the states from.
/// The 's balance for
- /// at . If absent, returns 0
+ /// at and .
+ /// If absent, returns 0
/// for .
///
/// Thrown when at
- /// cannot be created.
+ /// and cannot be created.
+ ///
FungibleAssetValue GetBalance(
Address address,
Currency currency,
+ Address accountAddress,
BlockHash? offset);
+ ///
+ /// Gets 's balance for given in the
+ /// at .
+ ///
+ /// The owner to query.
+ /// The currency type to query.
+ /// The state root hash of the to fetch
+ /// the balance from.
+ /// The 's balance for
+ /// at .
+ /// If absent, returns 0 for .
+ ///
+ /// Thrown when at
+ /// cannot be created.
+ FungibleAssetValue GetBalance(
+ Address address,
+ Currency currency,
+ HashDigest? stateRootHash);
+
///
/// Gets the total supply of a in the
/// at , and if not found, returns 0.
///
/// The currency type to query.
+ /// The account to query from.
/// The of the to fetch
/// the states from.
/// The total supply value of at
- /// in .
+ /// and
+ /// in .
/// If absent, returns 0
/// for .
/// Thrown when at
- /// cannot be created.
+ /// and cannot be created.
+ ///
/// Thrown when
/// given 's
/// is .
- ///
FungibleAssetValue GetTotalSupply(
Currency currency,
+ Address accountAddress,
BlockHash? offset);
+ ///
+ /// Gets the total supply of a in the
+ /// at , and if not found, returns 0.
+ ///
+ /// The currency type to query.
+ /// The state root hash of the to fetch
+ /// the total supply from.
+ /// The total supply value of at
+ /// in .
+ /// If absent, returns 0
+ /// for .
+ /// Thrown when at
+ /// cannot be created.
+ /// Thrown when
+ /// given 's
+ /// is .
+ FungibleAssetValue GetTotalSupply(
+ Currency currency,
+ HashDigest? stateRootHash);
+
///
/// Returns the validator set in the
/// at .
///
+ /// The account to query from.
/// The of the to fetch
/// the states from.
/// The validator set of type at
- /// .
+ /// and .
+ ///
+ /// Thrown when at
+ /// and cannot be created.
+ ///
+ ValidatorSet GetValidatorSet(
+ Address accountAddress,
+ BlockHash? offset);
+
+ ///
+ /// Returns the validator set in the
+ /// at .
+ ///
+ /// The state root hash of the to fetch
+ /// the validator set from.
+ /// The validator set of type at
+ /// .
///
/// Thrown when at
- /// cannot be created.
- ///
- ValidatorSet GetValidatorSet(BlockHash? offset);
+ /// cannot be created.
+ ValidatorSet GetValidatorSet(
+ HashDigest? stateRootHash);
}
}
diff --git a/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs b/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs
index 1f17ba483fe..a32ec751159 100644
--- a/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs
+++ b/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs
@@ -4,6 +4,7 @@
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.Loader;
+using Libplanet.Action.State;
using Libplanet.Action.Sys;
using Libplanet.Blockchain;
using Libplanet.Blockchain.Policies;
@@ -12,7 +13,6 @@
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
using Libplanet.Types.Tx;
-using Libplanet.Consensus;
using Libplanet.Store;
using Libplanet.Store.Trie;
@@ -189,7 +189,7 @@ private Transaction
{
var random = new System.Random(seed);
var addr = pk.ToAddress();
- var bal = (int)(Chain.GetBalance(addr, TestCurrency).MajorUnit & int.MaxValue);
+ var bal = (int)(Chain.GetBalance(addr, TestCurrency, ReservedAddresses.LegacyAccount).MajorUnit & int.MaxValue);
return Transaction.Create(
nonce,
pk,
diff --git a/Libplanet.Explorer.Tests/Queries/StateQueryTest.cs b/Libplanet.Explorer.Tests/Queries/StateQueryTest.cs
index 818c94ad3ce..c98d14cc01e 100644
--- a/Libplanet.Explorer.Tests/Queries/StateQueryTest.cs
+++ b/Libplanet.Explorer.Tests/Queries/StateQueryTest.cs
@@ -117,6 +117,7 @@ public async Task Balance()
balance(
owner: ""0x5003712B63baAB98094aD678EA2B24BcE445D076"",
currency: { ticker: ""ABC"", decimalPlaces: 2, totalSupplyTrackable: true },
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetBlockHash:
""01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b""
) {
@@ -159,6 +160,7 @@ public async Task TotalSupply()
{
totalSupply(
currency: { ticker: ""ABC"", decimalPlaces: 2, totalSupplyTrackable: true },
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetBlockHash:
""01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b""
) {
@@ -212,6 +214,7 @@ public async Task Validators()
ExecutionResult result = await ExecuteQueryAsync(@"
{
validators(
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetBlockHash:
""01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b""
) {
@@ -289,6 +292,7 @@ public async Task BalanceBySrh()
balance(
owner: ""0x5003712B63baAB98094aD678EA2B24BcE445D076"",
currency: { ticker: ""ABC"", decimalPlaces: 2, totalSupplyTrackable: true },
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetStateRootHash:
""c33b27773104f75ac9df5b0533854108bd498fab31e5236b6f1e1f6404d5ef64""
) {
@@ -331,6 +335,7 @@ public async Task TotalSupplyBySrh()
{
totalSupply(
currency: { ticker: ""ABC"", decimalPlaces: 2, totalSupplyTrackable: true },
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetStateRootHash:
""c33b27773104f75ac9df5b0533854108bd498fab31e5236b6f1e1f6404d5ef64""
) {
@@ -363,6 +368,7 @@ public async Task TotalSupplyBySrh()
{
totalSupply(
currency: { ticker: ""LEG"", decimalPlaces: 0, totalSupplyTrackable: false },
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetBlockHash:
""01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b""
) {
@@ -384,6 +390,7 @@ public async Task ValidatorsBySrh()
ExecutionResult result = await ExecuteQueryAsync(@"
{
validators(
+ accountAddress: ""0x1000000000000000000000000000000000000000"",
offsetStateRootHash:
""c33b27773104f75ac9df5b0533854108bd498fab31e5236b6f1e1f6404d5ef64""
) {
@@ -406,50 +413,42 @@ public async Task ValidatorsBySrh()
private class MockChainStates : IBlockChainStates
{
- public IReadOnlyList GetStates(
- IReadOnlyList addresses,
- HashDigest? stateRootHash) =>
- addresses.Select(addr => GetAccountState(stateRootHash).GetState(addr)).ToList().AsReadOnly();
-
- public FungibleAssetValue GetBalance(
- Address address, Currency currency, BlockHash? offset) =>
- new MockAccount().GetBalance(address, currency);
-
- public FungibleAssetValue GetTotalSupply(Currency currency, BlockHash? offset) =>
- new MockAccount().GetTotalSupply(currency);
-
- public ValidatorSet GetValidatorSet(BlockHash? offset) =>
- new MockAccount().GetValidatorSet();
-
-
- public IValue? GetState(Address address, Address accountAddress, BlockHash? offset)
- => new MockAccount().GetState(address);
+ public IWorldState GetWorldState(HashDigest? hash)
+ => new MockWorld();
public IWorldState GetWorldState(BlockHash? offset)
=> new MockWorld();
+ public IAccountState GetAccountState(HashDigest? hash)
+ => new MockAccount();
public IAccountState GetAccountState(Address address, BlockHash? blockHash)
=> new MockAccount();
- public ITrie GetBlockTrie(BlockHash? offset)
- {
- throw new System.NotImplementedException();
- }
+ public IValue? GetState(Address address, HashDigest? hash)
+ => new MockAccount().GetState(address);
- public ITrie GetTrie(HashDigest? hash)
- {
- throw new System.NotImplementedException();
- }
+ public IValue? GetState(Address address, Address accountAddress, BlockHash? offset)
+ => new MockAccount().GetState(address);
- public IWorldState GetWorldState(HashDigest? hash)
- => new MockWorld();
+ public FungibleAssetValue GetBalance(
+ Address address, Currency currency, HashDigest? hash) =>
+ new MockAccount().GetBalance(address, currency);
- public IAccountState GetAccountState(HashDigest? hash)
- => new MockAccount();
+ public FungibleAssetValue GetBalance(
+ Address address, Currency currency, Address accountAddress, BlockHash? offset) =>
+ new MockAccount().GetBalance(address, currency);
- public IValue? GetState(Address address, HashDigest? hash)
- => new MockAccount().GetState(address);
+ public FungibleAssetValue GetTotalSupply(Currency currency, HashDigest? hash) =>
+ new MockAccount().GetTotalSupply(currency);
+
+ public FungibleAssetValue GetTotalSupply(Currency currency, Address accountAddress, BlockHash? offset) =>
+ new MockAccount().GetTotalSupply(currency);
+ public ValidatorSet GetValidatorSet(HashDigest? hash) =>
+ new MockAccount().GetValidatorSet();
+
+ public ValidatorSet GetValidatorSet(Address accountAddress, BlockHash? offset) =>
+ new MockAccount().GetValidatorSet();
}
private class MockWorld : IWorld
diff --git a/Libplanet.Explorer/Queries/StateQuery.cs b/Libplanet.Explorer/Queries/StateQuery.cs
index 6fd072b6e29..9197d51ddda 100644
--- a/Libplanet.Explorer/Queries/StateQuery.cs
+++ b/Libplanet.Explorer/Queries/StateQuery.cs
@@ -40,7 +40,7 @@ public StateQuery()
"state",
arguments: new QueryArguments(
new QueryArgument> { Name = "address" },
- new QueryArgument> { Name = "accountAddress" },
+ new QueryArgument { Name = "accountAddress" },
new QueryArgument { Name = "offsetBlockHash" },
new QueryArgument { Name = "offsetStateRootHash" },
new QueryArgument { Name = "accountStateRootHash" }
@@ -52,8 +52,10 @@ public StateQuery()
arguments: new QueryArguments(
new QueryArgument> { Name = "owner" },
new QueryArgument> { Name = "currency" },
+ new QueryArgument { Name = "accountAddress" },
new QueryArgument { Name = "offsetBlockHash" },
- new QueryArgument { Name = "offsetStateRootHash" }
+ new QueryArgument { Name = "offsetStateRootHash" },
+ new QueryArgument { Name = "accountStateRootHash" }
),
resolve: ResolveBalance
);
@@ -61,16 +63,20 @@ public StateQuery()
"totalSupply",
arguments: new QueryArguments(
new QueryArgument> { Name = "currency" },
+ new QueryArgument { Name = "accountAddress" },
new QueryArgument { Name = "offsetBlockHash" },
- new QueryArgument { Name = "offsetStateRootHash" }
+ new QueryArgument { Name = "offsetStateRootHash" },
+ new QueryArgument { Name = "accountStateRootHash" }
),
resolve: ResolveTotalSupply
);
Field>>(
"validators",
arguments: new QueryArguments(
+ new QueryArgument { Name = "accountAddress" },
new QueryArgument { Name = "offsetBlockHash" },
- new QueryArgument { Name = "offsetStateRootHash" }
+ new QueryArgument { Name = "offsetStateRootHash" },
+ new QueryArgument { Name = "accountStateRootHash" }
),
resolve: ResolveValidatorSet
);
@@ -119,7 +125,7 @@ private static object ResolveWorldState(
private static object ResolveAccountState(
IResolveFieldContext<(IBlockChainStates ChainStates, IBlockPolicy Policy)> context)
{
- Address? accountAddress = context.GetArgument("accountAddress");
+ Address? accountAddress = context.GetArgument("accountAddress");
string? offsetBlockHash = context.GetArgument("offsetBlockHash");
HashDigest? offsetStateRootHash = context
.GetArgument?>("offsetStateRootHash");
@@ -193,7 +199,7 @@ private static object ResolveAccountState(
IResolveFieldContext<(IBlockChainStates ChainStates, IBlockPolicy Policy)> context)
{
Address address = context.GetArgument("address");
- Address? accountAddress = context.GetArgument("accountAddress");
+ Address? accountAddress = context.GetArgument("accountAddress");
string? offsetBlockHash = context.GetArgument("offsetBlockHash");
HashDigest? offsetStateRootHash = context
.GetArgument?>("offsetStateRootHash");
@@ -274,42 +280,79 @@ private static object ResolveBalance(
{
Address owner = context.GetArgument("owner");
Currency currency = context.GetArgument("currency");
+ Address? accountAddress = context.GetArgument("accountAddress");
string? offsetBlockHash = context.GetArgument("offsetBlockHash");
HashDigest? offsetStateRootHash = context
.GetArgument?>("offsetStateRootHash");
+ HashDigest? accountStateRootHash = context
+ .GetArgument?>("accountStateRootHash");
- switch (blockhash: offsetBlockHash, srh: offsetStateRootHash)
+ if (accountStateRootHash is { } accountSrh)
{
- case (blockhash: not null, srh: not null):
- throw new ExecutionError(
- "offsetBlockHash and offsetStateRootHash cannot be specified at the same time."
- );
- case (blockhash: null, srh: null):
+ if (accountAddress is not null
+ || offsetBlockHash is not null
+ || offsetStateRootHash is not null)
+ {
throw new ExecutionError(
- "Either offsetBlockHash or offsetStateRootHash must be specified."
+ "Neither accountAddress, offsetBlockHash nor offsetStateRootHash " +
+ "cannot be specified with the accountStateRootHash."
);
- case (blockhash: not null, _):
+ }
+
+ return context.Source.ChainStates
+ .GetAccountState(accountSrh)
+ .GetBalance(owner, currency);
+ }
+ else
+ {
+ if (accountAddress is { } accountAddr)
{
- BlockHash offset;
- try
- {
- offset = BlockHash.FromString(offsetBlockHash);
- }
- catch (Exception e)
+ switch (blockhash: offsetBlockHash, offsetSrh: offsetStateRootHash)
{
- throw new ExecutionError(
- "offsetBlockHash must consist of hexadecimal digits.\n" + e.Message,
- e
- );
- }
+ case (blockhash: not null, offsetSrh: not null):
+ throw new ExecutionError(
+ "offsetBlockHash and offsetStateRootHash " +
+ "cannot be specified at the same time."
+ );
+ case (blockhash: null, offsetSrh: null):
+ throw new ExecutionError(
+ "Either offsetBlockHash or offsetStateRootHash must be specified."
+ );
+ case (blockhash: not null, _):
+ {
+ BlockHash offset;
+ try
+ {
+ offset = BlockHash.FromString(offsetBlockHash);
+ }
+ catch (Exception e)
+ {
+ throw new ExecutionError(
+ "offsetBlockHash must consist of hexadecimal digits.\n"
+ + e.Message,
+ e
+ );
+ }
- return context.Source.ChainStates.GetBalance(owner, currency, offset);
- }
+ return context.Source.ChainStates
+ .GetWorldState(offset)
+ .GetAccount(accountAddr)
+ .GetBalance(owner, currency);
+ }
- case (_, srh: not null):
- return context.Source.ChainStates.GetWorldState(offsetStateRootHash)
- .GetAccount(ReservedAddresses.LegacyAccount)
- .GetBalance(owner, currency);
+ case (_, offsetSrh: not null):
+ return context.Source.ChainStates
+ .GetWorldState(offsetStateRootHash)
+ .GetAccount(accountAddr)
+ .GetBalance(owner, currency);
+ }
+ }
+ else
+ {
+ throw new ExecutionError(
+ "accountAddress have to be specified with offset."
+ );
+ }
}
}
@@ -317,9 +360,12 @@ private static object ResolveBalance(
IResolveFieldContext<(IBlockChainStates ChainStates, IBlockPolicy Policy)> context)
{
Currency currency = context.GetArgument("currency");
+ Address? accountAddress = context.GetArgument("accountAddress");
string? offsetBlockHash = context.GetArgument("offsetBlockHash");
HashDigest? offsetStateRootHash = context
.GetArgument?>("offsetStateRootHash");
+ HashDigest? accountStateRootHash = context
+ .GetArgument?>("accountStateRootHash");
if (!currency.TotalSupplyTrackable)
{
@@ -330,81 +376,151 @@ private static object ResolveBalance(
throw new ExecutionError(msg);
}
- switch (blockhash: offsetBlockHash, srh: offsetStateRootHash)
+ if (accountStateRootHash is { } accountSrh)
{
- case (blockhash: not null, srh: not null):
- throw new ExecutionError(
- "offsetBlockHash and offsetStateRootHash cannot be specified at the same time."
- );
- case (blockhash: null, srh: null):
+ if (accountAddress is not null
+ || offsetBlockHash is not null
+ || offsetStateRootHash is not null)
+ {
throw new ExecutionError(
- "Either offsetBlockHash or offsetStateRootHash must be specified."
+ "Neither accountAddress, offsetBlockHash nor offsetStateRootHash " +
+ "cannot be specified with the accountStateRootHash."
);
- case (blockhash: not null, _):
+ }
+
+ return context.Source.ChainStates
+ .GetAccountState(accountSrh)
+ .GetTotalSupply(currency);
+ }
+ else
+ {
+ if (accountAddress is { } accountAddr)
{
- BlockHash offset;
- try
- {
- offset = BlockHash.FromString(offsetBlockHash);
- }
- catch (Exception e)
+ switch (blockhash: offsetBlockHash, offsetSrh: offsetStateRootHash)
{
- throw new ExecutionError(
- "offsetBlockHash must consist of hexadecimal digits.\n" + e.Message,
- e
- );
- }
+ case (blockhash: not null, offsetSrh: not null):
+ throw new ExecutionError(
+ "offsetBlockHash and offsetStateRootHash " +
+ "cannot be specified at the same time."
+ );
+ case (blockhash: null, offsetSrh: null):
+ throw new ExecutionError(
+ "Either offsetBlockHash or offsetStateRootHash must be specified."
+ );
+ case (blockhash: not null, _):
+ {
+ BlockHash offset;
+ try
+ {
+ offset = BlockHash.FromString(offsetBlockHash);
+ }
+ catch (Exception e)
+ {
+ throw new ExecutionError(
+ "offsetBlockHash must consist of hexadecimal digits.\n"
+ + e.Message,
+ e
+ );
+ }
- return context.Source.ChainStates.GetTotalSupply(currency, offset);
- }
+ return context.Source.ChainStates
+ .GetWorldState(offset)
+ .GetAccount(accountAddr)
+ .GetTotalSupply(currency);
+ }
- case (_, srh: not null):
- return context.Source.ChainStates.GetWorldState(offsetStateRootHash)
- .GetAccount(ReservedAddresses.LegacyAccount)
- .GetTotalSupply(currency);
+ case (_, offsetSrh: not null):
+ return context.Source.ChainStates
+ .GetWorldState(offsetStateRootHash)
+ .GetAccount(accountAddr)
+ .GetTotalSupply(currency);
+ }
+ }
+ else
+ {
+ throw new ExecutionError(
+ "accountAddress have to be specified with offset."
+ );
+ }
}
}
private static object? ResolveValidatorSet(
IResolveFieldContext<(IBlockChainStates ChainStates, IBlockPolicy Policy)> context)
{
+ Address? accountAddress = context.GetArgument("accountAddress");
string? offsetBlockHash = context.GetArgument("offsetBlockHash");
HashDigest? offsetStateRootHash = context
.GetArgument?>("offsetStateRootHash");
+ HashDigest? accountStateRootHash = context
+ .GetArgument?>("accountStateRootHash");
- switch (blockhash: offsetBlockHash, srh: offsetStateRootHash)
+ if (accountStateRootHash is { } accountSrh)
{
- case (blockhash: not null, srh: not null):
- throw new ExecutionError(
- "offsetBlockHash and offsetStateRootHash cannot be specified at the same time."
- );
- case (blockhash: null, srh: null):
+ if (accountAddress is not null
+ || offsetBlockHash is not null
+ || offsetStateRootHash is not null)
+ {
throw new ExecutionError(
- "Either offsetBlockHash or offsetStateRootHash must be specified."
+ "Neither accountAddress, offsetBlockHash nor offsetStateRootHash " +
+ "cannot be specified with the accountStateRootHash."
);
- case (blockhash: not null, _):
+ }
+
+ return context.Source.ChainStates
+ .GetAccountState(accountSrh)
+ .GetValidatorSet().Validators;
+ }
+ else
+ {
+ if (accountAddress is { } accountAddr)
{
- BlockHash offset;
- try
- {
- offset = BlockHash.FromString(offsetBlockHash);
- }
- catch (Exception e)
+ switch (blockhash: offsetBlockHash, offsetSrh: offsetStateRootHash)
{
- throw new ExecutionError(
- "offsetBlockHash must consist of hexadecimal digits.\n" + e.Message,
- e
- );
- }
+ case (blockhash: not null, offsetSrh: not null):
+ throw new ExecutionError(
+ "offsetBlockHash and offsetStateRootHash " +
+ "cannot be specified at the same time."
+ );
+ case (blockhash: null, offsetSrh: null):
+ throw new ExecutionError(
+ "Either offsetBlockHash or offsetStateRootHash must be specified."
+ );
+ case (blockhash: not null, _):
+ {
+ BlockHash offset;
+ try
+ {
+ offset = BlockHash.FromString(offsetBlockHash);
+ }
+ catch (Exception e)
+ {
+ throw new ExecutionError(
+ "offsetBlockHash must consist of hexadecimal digits.\n"
+ + e.Message,
+ e
+ );
+ }
- return context.Source.ChainStates.GetValidatorSet(offset).Validators;
- }
+ return context.Source.ChainStates
+ .GetWorldState(offset)
+ .GetAccount(accountAddr)
+ .GetValidatorSet().Validators;
+ }
- case (_, srh: not null):
- return context.Source.ChainStates.GetWorldState(offsetStateRootHash)
- .GetAccount(ReservedAddresses.LegacyAccount)
- .GetValidatorSet()
- .Validators;
+ case (_, offsetSrh: not null):
+ return context.Source.ChainStates
+ .GetWorldState(offsetStateRootHash)
+ .GetAccount(accountAddr)
+ .GetValidatorSet().Validators;
+ }
+ }
+ else
+ {
+ throw new ExecutionError(
+ "accountAddress have to be specified with offset."
+ );
+ }
}
}
}
diff --git a/Libplanet.Tests/Action/AccountTest.cs b/Libplanet.Tests/Action/AccountTest.cs
index a808e1d10bc..c79bc25b0d3 100644
--- a/Libplanet.Tests/Action/AccountTest.cs
+++ b/Libplanet.Tests/Action/AccountTest.cs
@@ -238,11 +238,11 @@ public virtual BlockChain TransferAssetInBlock()
);
Assert.Equal(
DumbAction.DumbCurrency * 5,
- chain.GetBalance(_addr[0], DumbAction.DumbCurrency)
+ chain.GetBalance(_addr[0], DumbAction.DumbCurrency, ReservedAddresses.LegacyAccount)
);
Assert.Equal(
DumbAction.DumbCurrency * -5,
- chain.GetBalance(_addr[1], DumbAction.DumbCurrency)
+ chain.GetBalance(_addr[1], DumbAction.DumbCurrency, ReservedAddresses.LegacyAccount)
);
return chain;
diff --git a/Libplanet.Tests/Action/AccountV0Test.cs b/Libplanet.Tests/Action/AccountV0Test.cs
index d7f12211aee..02425711b55 100644
--- a/Libplanet.Tests/Action/AccountV0Test.cs
+++ b/Libplanet.Tests/Action/AccountV0Test.cs
@@ -81,7 +81,7 @@ public override BlockChain TransferAssetInBlock()
chain.Append(block, TestUtils.CreateBlockCommit(block));
Assert.Equal(
DumbAction.DumbCurrency * 6,
- chain.GetBalance(_addr[0], DumbAction.DumbCurrency)
+ chain.GetBalance(_addr[0], DumbAction.DumbCurrency, ReservedAddresses.LegacyAccount)
);
return chain;
diff --git a/Libplanet.Tests/Action/AccountV1Test.cs b/Libplanet.Tests/Action/AccountV1Test.cs
index 126e2ecc8ca..af2e6ac6b78 100644
--- a/Libplanet.Tests/Action/AccountV1Test.cs
+++ b/Libplanet.Tests/Action/AccountV1Test.cs
@@ -85,7 +85,7 @@ public override BlockChain TransferAssetInBlock()
);
Assert.Equal(
DumbAction.DumbCurrency * 5,
- chain.GetBalance(_addr[0], DumbAction.DumbCurrency)
+ chain.GetBalance(_addr[0], DumbAction.DumbCurrency, ReservedAddresses.LegacyAccount)
);
return chain;
diff --git a/Libplanet/Blockchain/BlockChain.cs b/Libplanet/Blockchain/BlockChain.cs
index b56b90a35a9..1d3d2172ecb 100644
--- a/Libplanet/Blockchain/BlockChain.cs
+++ b/Libplanet/Blockchain/BlockChain.cs
@@ -613,6 +613,10 @@ public IWorldState GetWorldState(BlockHash? offset)
/// The current world state.
public IWorldState GetWorldState() => GetWorldState(Tip.Hash);
+ ///
+ public IAccountState GetAccountState(HashDigest? stateRootHash) =>
+ new AccountBaseState(GetTrie(stateRootHash));
+
///
public IAccountState GetAccountState(Address address, BlockHash? offset) =>
GetWorldState(offset).GetAccount(address);
@@ -627,18 +631,14 @@ public IAccountState GetAccountState(Address address, BlockHash? offset) =>
public IAccountState GetAccountState(Address address) =>
GetWorldState().GetAccount(address);
- ///
- public IAccountState GetAccountState(HashDigest? stateRootHash) =>
- new AccountBaseState(GetTrie(stateRootHash));
+ ///
+ public IValue GetState(Address address, HashDigest? stateRootHash) =>
+ GetAccountState(stateRootHash).GetState(address);
///
public IValue GetState(Address address, Address accountAddress, BlockHash? offset) =>
GetAccountState(accountAddress, offset).GetState(address);
- ///
- public IValue GetState(Address address, HashDigest? stateRootHash) =>
- GetAccountState(stateRootHash).GetState(address);
-
///
/// Gets the current state of given and
/// in the .
@@ -652,47 +652,127 @@ public IValue GetState(Address address, HashDigest? stateRootHash) =>
public IValue GetState(Address address, Address accountAddress) =>
GetState(address, accountAddress, Tip.Hash);
+ ///
+ public FungibleAssetValue GetBalance(
+ Address address,
+ Currency currency,
+ HashDigest? stateRootHash)
+ => GetAccountState(stateRootHash)
+ .GetBalance(address, currency);
+
+ ///
+ public FungibleAssetValue GetBalance(
+ Address address,
+ Currency currency,
+ Address accountAddress,
+ BlockHash? offset)
+ => GetWorldState(offset)
+ .GetAccount(accountAddress)
+ .GetBalance(address, currency);
+
///
/// Queries 's current balance of the
/// in the .
///
/// The owner to query.
/// The currency type to query.
+ /// The account to query from.
/// The 's current balance.
///
+ /// Thrown when of
+ /// cannot be created.
+ ///
public FungibleAssetValue GetBalance(
Address address,
- Currency currency)
- => GetBalance(address, currency, Tip.Hash);
+ Currency currency,
+ Address accountAddress)
+ => GetBalance(address, currency, accountAddress, Tip.Hash);
- ///
- public FungibleAssetValue GetBalance(
- Address address,
+ ///
+ public FungibleAssetValue GetTotalSupply(
+ Currency currency,
+ HashDigest? stateRootHash)
+ => GetAccountState(stateRootHash)
+ .GetTotalSupply(currency);
+
+ ///
+ public FungibleAssetValue GetTotalSupply(
Currency currency,
+ Address accountAddress,
BlockHash? offset)
=> GetWorldState(offset)
- .GetAccount(ReservedAddresses.LegacyAccount).GetBalance(address, currency);
+ .GetAccount(accountAddress)
+ .GetTotalSupply(currency);
///
/// Gets the current total supply of a in the
/// .
///
/// The currency type to query.
+ /// The account to query from.
/// The total supply value of at
- /// in .
- public FungibleAssetValue GetTotalSupply(Currency currency)
- => GetTotalSupply(currency, Tip.Hash);
+ /// and
+ /// in .
+ /// Thrown when of
+ /// cannot be created.
+ ///
+ public FungibleAssetValue GetTotalSupply(Currency currency, Address accountAddress)
+ => GetTotalSupply(currency, accountAddress, Tip.Hash);
- ///
- public FungibleAssetValue GetTotalSupply(Currency currency, BlockHash? offset)
+ ///
+ public ValidatorSet GetValidatorSet(HashDigest? stateRootHash)
+ => GetAccountState(stateRootHash)
+ .GetValidatorSet();
+
+ ///
+ public ValidatorSet GetValidatorSet(Address accountAddress, BlockHash? offset)
=> GetWorldState(offset)
- .GetAccount(ReservedAddresses.LegacyAccount).GetTotalSupply(currency);
+ .GetAccount(accountAddress)
+ .GetValidatorSet();
- public ValidatorSet GetValidatorSet() => GetValidatorSet(Tip.Hash);
+ ///
+ /// Returns the current validator set in the .
+ ///
+ /// The account to query from.
+ /// The validator set of type at
+ /// and .
+ ///
+ /// Thrown when of
+ /// cannot be created.
+ ///
+ public ValidatorSet GetValidatorSet(Address accountAddress)
+ => GetValidatorSet(accountAddress, Tip.Hash);
- ///
+ ///
+ /// Returns the validator set in the
+ /// at and
+ /// .
+ ///
+ /// The of the to fetch
+ /// the states from.
+ /// The validator set of type at
+ /// and .
+ ///
+ /// Thrown when at
+ /// and
+ /// cannot be created.
+ ///
public ValidatorSet GetValidatorSet(BlockHash? offset)
- => GetWorldState(offset).GetAccount(ReservedAddresses.LegacyAccount).GetValidatorSet();
+ => GetValidatorSet(ReservedAddresses.LegacyAccount, offset);
+
+ ///
+ /// Returns the current validator set in the .
+ ///
+ /// The validator set of type at
+ /// and .
+ ///
+ /// Thrown when of
+ /// cannot be created.
+ ///
+ public ValidatorSet GetValidatorSet()
+ => GetValidatorSet(ReservedAddresses.LegacyAccount);
///
/// Queries the recorded for a successful or failed