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