gnolang / gno

Gno: An interpreted, stack-based Go virtual machine to build succinct and composable apps + Gno.land: a blockchain for timeless code and fair open-source
https://gno.land/
Other
842 stars 343 forks source link

Uninitialized accounts are unmarshalled with invalid data #661

Open zivkovicmilos opened 1 year ago

zivkovicmilos commented 1 year ago

Uninitialized accounts are returned with invalid data

Description

Executing a query to auth/accounts/<address> for a previously unseen address returns a nil response to an ABCI query result. This can lead to an invalid account (zero address) being returned (when unmarshalling this ABCI response on the client).

Your environment

Steps to reproduce

Expected behaviour

The account data should be returned (and filled correctly) even if the account is not found in the blockchain storage

Actual behaviour

If the account is not found, nil is returned, leading to an invalid unmarshal operation on ABCI clients.

Logs

./build/gnokey query --remote localhost:26657 --height 1 auth/accounts/g1zhrdmurv3yqwpct7s09rgk0l3yj6kgtyf7hd2f
height: 0
data: null

Proposed solution

Account fetches should never return nil, but rather initialize the account and return it.

zivkovicmilos commented 1 year ago

cc @moul

Initializing and saving unknown accounts on query requests can have real side-effects on storage, so I suggest we discuss how we want to go about solving a problem like this

moul commented 1 year ago

Hey, thank you.

@zivkovicmilos: what do you suggest?

Anyone: any feedback on how other chains handle this is a manner you prefer?

zivkovicmilos commented 1 year ago

Hey, thank you.

@zivkovicmilos: what do you suggest?

Anyone: any feedback on how other chains handle this is a manner you prefer?

Not exactly sure what should be the appropriate fix that doesn't have any unwanted side effects.

Ethereum handles these situations (querying of previously untouched accounts) in the following manner:

I honestly see no problem in doing the same on our Tendermint node, the only thing I'm worried about is the Account Number param for the BaseAccount. If I understood correctly, this is dependent on state, meaning the account needs to be initialized already (number secured, so no two accounts have the same one). Is this correct?

tbruyelle commented 1 year ago

I honestly see no problem in doing the same on our Tendermint node, the only thing I'm worried about is the Account Number param for the BaseAccount. If I understood correctly, this is dependent on state, meaning the account needs to be initialized already (number secured, so no two accounts have the same one). Is this correct?

I like the idea of returning a pre-initialized account if the passed address doesn't exist, unfortunately as you mentioned it's not possible due to the account number, which is a global counter incremented each time a new account is created.

The other way of dealing with non-existent account would be to return an error instead of nil, but not sure I prefer that...