From e89aa1a435af71011fc043f291c998d03a55e4ef Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Wed, 6 Apr 2022 17:09:32 +0200 Subject: [PATCH 1/7] Fixes the issue #259: Expose foundation account address Adds the option of querying AccountInfo by using account index value. --- concordium-consensus/src/Concordium/External.hs | 11 +++++++---- .../src/Concordium/GlobalState/Basic/BlockState.hs | 4 ++++ .../src/Concordium/GlobalState/BlockState.hs | 5 +++++ .../src/Concordium/GlobalState/Paired.hs | 11 +++++++++++ .../Concordium/GlobalState/Persistent/BlockState.hs | 5 +++++ concordium-consensus/src/Concordium/Queries.hs | 8 +++++--- 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/concordium-consensus/src/Concordium/External.hs b/concordium-consensus/src/Concordium/External.hs index e8281246c6..cb03a4c425 100644 --- a/concordium-consensus/src/Concordium/External.hs +++ b/concordium-consensus/src/Concordium/External.hs @@ -891,14 +891,17 @@ decodeBlockHash blockcstr = readMaybe <$> peekCString blockcstr decodeAccountAddress :: CString -> IO (Either String AccountAddress) decodeAccountAddress acctstr = addressFromBytes <$> BS.packCString acctstr --- |Decode a null-terminated string as either an account address (base-58) or a +-- |Decode a null-terminated string as either an account address (base-58), account index (Int) or a -- credential registration ID (base-16). -decodeAccountAddressOrCredId :: CString -> IO (Maybe (Either CredentialRegistrationID AccountAddress)) +decodeAccountAddressOrCredId :: CString -> IO (Maybe AccountIdentifier) decodeAccountAddressOrCredId str = do bs <- BS.packCString str return $ case addressFromBytes bs of - Left _ -> Left <$> bsDeserializeBase16 bs - Right acc -> Just $ Right acc + Left _ -> Just $ + case bsDeserializeBase16 bs of + Nothing -> AI $ read (BS.unpack bs) + Just cid -> CID cid + Right acc -> Just $ AA acc -- |Decode an instance address from a null-terminated JSON-encoded string. decodeInstanceAddress :: CString -> IO (Maybe ContractAddress) diff --git a/concordium-consensus/src/Concordium/GlobalState/Basic/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/Basic/BlockState.hs index fda9973b83..0c2e16376d 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Basic/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Basic/BlockState.hs @@ -397,6 +397,10 @@ instance (IsProtocolVersion pv, Monad m) => BS.BlockStateQuery (PureBlockStateMo Nothing -> return Nothing Just ai -> return $ (ai, ) <$> bs ^? blockAccounts . Accounts.indexedAccount ai + {-# INLINE getAccountByIndex #-} + getAccountByIndex bs ai = + return $ (ai, ) <$> bs ^? blockAccounts . Accounts.indexedAccount ai + {-# INLINE getBakerAccount #-} getBakerAccount bs (BakerId ai) = return $ bs ^? blockAccounts . Accounts.indexedAccount ai diff --git a/concordium-consensus/src/Concordium/GlobalState/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/BlockState.hs index d497e5f852..f2492c2a04 100644 --- a/concordium-consensus/src/Concordium/GlobalState/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/BlockState.hs @@ -203,6 +203,9 @@ class AccountOperations m => BlockStateQuery m where -- |Query an account by the id of the credential that belonged to it. getAccountByCredId :: BlockState m -> CredentialRegistrationID -> m (Maybe (AccountIndex, Account m)) + -- |Query an account by the account index that belonged to it. + getAccountByIndex :: BlockState m -> AccountIndex -> m (Maybe (AccountIndex, Account m)) + -- |Get the contract state from the contract table of the state instance. getContractInstance :: BlockState m -> ContractAddress -> m (Maybe Instance) @@ -644,6 +647,7 @@ instance (Monad (t m), MonadTrans t, BlockStateQuery m) => BlockStateQuery (MGST getAccount s = lift . getAccount s accountExists s = lift . accountExists s getAccountByCredId s = lift . getAccountByCredId s + getAccountByIndex s = lift . getAccountByIndex s getBakerAccount s = lift . getBakerAccount s getContractInstance s = lift . getContractInstance s getModuleList = lift . getModuleList @@ -674,6 +678,7 @@ instance (Monad (t m), MonadTrans t, BlockStateQuery m) => BlockStateQuery (MGST {-# INLINE getAccount #-} {-# INLINE accountExists #-} {-# INLINE getAccountByCredId #-} + {-# INLINE getAccountByIndex #-} {-# INLINE getBakerAccount #-} {-# INLINE getContractInstance #-} {-# INLINE getModuleList #-} diff --git a/concordium-consensus/src/Concordium/GlobalState/Paired.hs b/concordium-consensus/src/Concordium/GlobalState/Paired.hs index f46a583e51..5db3ca89e0 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Paired.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Paired.hs @@ -209,6 +209,17 @@ instance (Monad m, C.HasGlobalStateContext (PairGSContext lc rc) r, BlockStateQu return Nothing (Nothing, _) -> error $ "Cannot get account with credid " ++ show cid ++ " in left implementation" (_, Nothing) -> error $ "Cannot get account with credid " ++ show cid ++ " in right implementation" + getAccountByIndex (ls, rs) idx = do + a1 <- coerceBSML (getAccountByIndex ls idx) + a2 <- coerceBSMR (getAccountByIndex rs idx) + case (a1, a2) of + (Just (ai1, a1'), Just (ai2, a2')) -> + assert ((getHash a1' :: H.Hash) == getHash a2' && ai1 == ai2) $ + return $ Just (ai1, (a1', a2')) + (Nothing, Nothing) -> + return Nothing + (Nothing, _) -> error $ "Cannot get account by index " ++ show idx ++ " in left implementation" + (_, Nothing) -> error $ "Cannot get account by index " ++ show idx ++ " in right implementation" getBakerAccount (ls, rs) bid = do a1 <- coerceBSML (getBakerAccount ls bid) a2 <- coerceBSMR (getBakerAccount rs bid) diff --git a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs index e864e9b837..f776e7870d 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs @@ -889,6 +889,10 @@ doGetAccountByCredId pbs cid = do bsp <- loadPBS pbs Accounts.getAccountByCredId cid (bspAccounts bsp) +doGetAccountByIndex :: (IsProtocolVersion pv, MonadBlobStore m) => PersistentBlockState pv -> AccountIndex -> m (Maybe (AccountIndex, PersistentAccount pv)) +doGetAccountByIndex pbs idx = do + bsp <- loadPBS pbs + fmap (idx, ) <$> Accounts.indexedAccount idx (bspAccounts bsp) doGetAccountIndex :: (IsProtocolVersion pv, MonadBlobStore m) => PersistentBlockState pv -> AccountAddress -> m (Maybe AccountIndex) doGetAccountIndex pbs addr = do @@ -1276,6 +1280,7 @@ instance (IsProtocolVersion pv, PersistentState r m) => BlockStateQuery (Persist getAccount = doGetAccount . hpbsPointers accountExists = doGetAccountExists . hpbsPointers getAccountByCredId = doGetAccountByCredId . hpbsPointers + getAccountByIndex = doGetAccountByIndex . hpbsPointers getContractInstance = doGetInstance . hpbsPointers getModuleList = doGetModuleList . hpbsPointers getAccountList = doAccountList . hpbsPointers diff --git a/concordium-consensus/src/Concordium/Queries.hs b/concordium-consensus/src/Concordium/Queries.hs index 795f84e67c..9afa885db1 100644 --- a/concordium-consensus/src/Concordium/Queries.hs +++ b/concordium-consensus/src/Concordium/Queries.hs @@ -459,19 +459,21 @@ getModuleList :: BlockHash -> MVR gsconf finconf (Maybe [ModuleRef]) getModuleList = liftSkovQueryBlock $ BS.getModuleList <=< blockState -- |Get the details of an account in the block state. --- The account can be given either via an address, or via a credential registration id. +-- The account can be given via an address, an account index or a credential registration id. -- In the latter case we lookup the account the credential is associated with, even if it was -- removed from the account. getAccountInfo :: BlockHash -> - Either CredentialRegistrationID AccountAddress -> + AccountIdentifier -> MVR gsconf finconf (Maybe AccountInfo) getAccountInfo blockHash acct = join <$> liftSkovQueryBlock ( \bp -> do bs <- blockState bp - macc <- either (BS.getAccountByCredId bs) (BS.getAccount bs) acct + macc <- case acct of AA addr -> BS.getAccount bs addr + AI idx -> BS.getAccountByIndex bs idx + CID crid -> BS.getAccountByCredId bs crid forM macc $ \(aiAccountIndex, acc) -> do aiAccountNonce <- BS.getAccountNonce acc aiAccountAmount <- BS.getAccountAmount acc From 1f54519b7768e35f7dfe79b64be13f3dde954dd7 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Thu, 7 Apr 2022 08:04:34 +0200 Subject: [PATCH 2/7] Update concordium-consensus/src/Concordium/Queries.hs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aleš Bizjak --- concordium-consensus/src/Concordium/Queries.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/concordium-consensus/src/Concordium/Queries.hs b/concordium-consensus/src/Concordium/Queries.hs index 9afa885db1..d9b80bfcb0 100644 --- a/concordium-consensus/src/Concordium/Queries.hs +++ b/concordium-consensus/src/Concordium/Queries.hs @@ -471,9 +471,10 @@ getAccountInfo blockHash acct = <$> liftSkovQueryBlock ( \bp -> do bs <- blockState bp - macc <- case acct of AA addr -> BS.getAccount bs addr - AI idx -> BS.getAccountByIndex bs idx - CID crid -> BS.getAccountByCredId bs crid + macc <- case acct of + AA addr -> BS.getAccount bs addr + AI idx -> BS.getAccountByIndex bs idx + CID crid -> BS.getAccountByCredId bs crid forM macc $ \(aiAccountIndex, acc) -> do aiAccountNonce <- BS.getAccountNonce acc aiAccountAmount <- BS.getAccountAmount acc From 397dcd31f31ddae342c712e14ce3737966cc7e49 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Thu, 7 Apr 2022 08:18:01 +0200 Subject: [PATCH 3/7] Fixes after review comments. --- concordium-consensus/src/Concordium/External.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/concordium-consensus/src/Concordium/External.hs b/concordium-consensus/src/Concordium/External.hs index cb03a4c425..44af30e5eb 100644 --- a/concordium-consensus/src/Concordium/External.hs +++ b/concordium-consensus/src/Concordium/External.hs @@ -891,16 +891,16 @@ decodeBlockHash blockcstr = readMaybe <$> peekCString blockcstr decodeAccountAddress :: CString -> IO (Either String AccountAddress) decodeAccountAddress acctstr = addressFromBytes <$> BS.packCString acctstr --- |Decode a null-terminated string as either an account address (base-58), account index (Int) or a +-- |Decode a null-terminated string as either an account address (base-58), account index (AccountIndex) or a -- credential registration ID (base-16). decodeAccountAddressOrCredId :: CString -> IO (Maybe AccountIdentifier) decodeAccountAddressOrCredId str = do bs <- BS.packCString str return $ case addressFromBytes bs of - Left _ -> Just $ + Left _ -> case bsDeserializeBase16 bs of - Nothing -> AI $ read (BS.unpack bs) - Just cid -> CID cid + Nothing -> AI <$> readMaybe (BS.unpack bs) + Just cid -> Just $ CID cid Right acc -> Just $ AA acc -- |Decode an instance address from a null-terminated JSON-encoded string. From f82d40ba97855518b88211e39bbd02090251f2e1 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Thu, 7 Apr 2022 09:14:48 +0200 Subject: [PATCH 4/7] Updates the `concordium-base` reference. This is to include `AccountIdentifier` type from `concordium-base`. --- concordium-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concordium-base b/concordium-base index 39b313c79f..62922b9e78 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit 39b313c79fa55da9a9f861735321e55877f757ac +Subproject commit 62922b9e7829a97eb85aa92571e7a1a4dc2aa9f7 From a9cc3869ded9a2308be09714553d77f9bee09058 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Thu, 7 Apr 2022 09:20:23 +0200 Subject: [PATCH 5/7] Updates changelog. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc12297111..f98c837027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ which they returned previously. - Fix issue #244: Collector to keep querying. Remove the parameter for maximum allowed times a gRPC call can fail and keeps `node-collector` querying forever. +- Fix the issue #259: Expose foundation account address. The account information now can + be queried by using an account index as well. ## concordium-node 3.0.1 From df847a77868741735bc51fa1bbc651473ae55a9c Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Fri, 8 Apr 2022 07:42:49 +0200 Subject: [PATCH 6/7] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aleš Bizjak --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f98c837027..dad4cc99f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,7 @@ which they returned previously. - Fix issue #244: Collector to keep querying. Remove the parameter for maximum allowed times a gRPC call can fail and keeps `node-collector` querying forever. -- Fix the issue #259: Expose foundation account address. The account information now can - be queried by using an account index as well. +- `GetAccountInfo` endpoint supports querying the account via the account index. ## concordium-node 3.0.1 From 4d6ab9eec83e0576ac037ebc74ba83edb238e004 Mon Sep 17 00:00:00 2001 From: Cem Eliguzel Date: Fri, 8 Apr 2022 07:47:30 +0200 Subject: [PATCH 7/7] Moves decodeAccountAddressOrCredId to concordium-base and renames to decodeAccountIdentifier --- concordium-base | 2 +- .../src/Concordium/External.hs | 18 +++--------------- concordium-consensus/src/Concordium/Queries.hs | 6 +++--- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/concordium-base b/concordium-base index 62922b9e78..764e519b66 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit 62922b9e7829a97eb85aa92571e7a1a4dc2aa9f7 +Subproject commit 764e519b669236e8aa0e8967c8aaec0913cc89dd diff --git a/concordium-consensus/src/Concordium/External.hs b/concordium-consensus/src/Concordium/External.hs index 44af30e5eb..6b50505a3e 100644 --- a/concordium-consensus/src/Concordium/External.hs +++ b/concordium-consensus/src/Concordium/External.hs @@ -29,7 +29,6 @@ import qualified Data.FixedByteString as FBS import Concordium.Afgjort.Finalize.Types (FinalizationInstance (FinalizationInstance)) import Concordium.Birk.Bake import Concordium.Constants.Time (defaultEarlyBlockThreshold, defaultMaxBakingDelay) -import Concordium.Crypto.ByteStringHelpers import Concordium.GlobalState import Concordium.GlobalState.Persistent.LMDB (addDatabaseVersion) import Concordium.GlobalState.Persistent.TreeState (InitException (..)) @@ -891,18 +890,6 @@ decodeBlockHash blockcstr = readMaybe <$> peekCString blockcstr decodeAccountAddress :: CString -> IO (Either String AccountAddress) decodeAccountAddress acctstr = addressFromBytes <$> BS.packCString acctstr --- |Decode a null-terminated string as either an account address (base-58), account index (AccountIndex) or a --- credential registration ID (base-16). -decodeAccountAddressOrCredId :: CString -> IO (Maybe AccountIdentifier) -decodeAccountAddressOrCredId str = do - bs <- BS.packCString str - return $ case addressFromBytes bs of - Left _ -> - case bsDeserializeBase16 bs of - Nothing -> AI <$> readMaybe (BS.unpack bs) - Just cid -> Just $ CID cid - Right acc -> Just $ AA acc - -- |Decode an instance address from a null-terminated JSON-encoded string. decodeInstanceAddress :: CString -> IO (Maybe ContractAddress) decodeInstanceAddress inststr = AE.decodeStrict <$> BS.packCString inststr @@ -1074,8 +1061,9 @@ getModuleList cptr blockcstr = do getAccountInfo :: StablePtr ConsensusRunner -> CString -> CString -> IO CString getAccountInfo cptr blockcstr acctcstr = do mblock <- decodeBlockHash blockcstr - maccount <- decodeAccountAddressOrCredId acctcstr - case (mblock, maccount) of + acctbs <- BS.packCString acctcstr + let account = decodeAccountIdentifier acctbs + case (mblock, account) of (Just bh, Just acct) -> jsonQuery cptr (Q.getAccountInfo bh acct) _ -> jsonCString AE.Null diff --git a/concordium-consensus/src/Concordium/Queries.hs b/concordium-consensus/src/Concordium/Queries.hs index d9b80bfcb0..7fd719cdea 100644 --- a/concordium-consensus/src/Concordium/Queries.hs +++ b/concordium-consensus/src/Concordium/Queries.hs @@ -472,9 +472,9 @@ getAccountInfo blockHash acct = ( \bp -> do bs <- blockState bp macc <- case acct of - AA addr -> BS.getAccount bs addr - AI idx -> BS.getAccountByIndex bs idx - CID crid -> BS.getAccountByCredId bs crid + AccAddress addr -> BS.getAccount bs addr + AccIndex idx -> BS.getAccountByIndex bs idx + CredRegID crid -> BS.getAccountByCredId bs crid forM macc $ \(aiAccountIndex, acc) -> do aiAccountNonce <- BS.getAccountNonce acc aiAccountAmount <- BS.getAccountAmount acc