tendermint / go-amino

Protobuf3 with Interface support - Designed for blockchains (deterministic, upgradeable, fast, and compact)
Other
260 stars 84 forks source link

How does slice decoding is done? #309

Closed salahzsh closed 4 years ago

salahzsh commented 4 years ago

https://github.com/tendermint/go-amino/blob/dc14acf9ef15f85828bfbc561ed9dd9d2a284885/binary-decode.go#L547

Hi, I'm trying to decode an StdTx obtained from a node using the go-sdk for the Binance Chain. The StdTx is encoded so using codec.UnmarshalBinaryLengthPrefixed I'm able to decode it to an str json (following this example: https://github.com/binance-chain/node-binary/issues/53). Now I'm trying to code my own function to decode the tx (to read the outputs of a transaction on a system where I can't use UnmarshalBinaryLengthPrefixed or any library). The Output struct looks like this:

type AccAddress []byte

// Coin def
type Coin struct {
    Denom  string `json:"denom"`
    Amount int64  `json:"amount"`
}

// Coins def
type Coins []Coin

// Transaction Output
type Output struct {
    Address AccAddress `json:"address"`
    Coins   Coins      `json:"coins"`
}

I have managed to decode the Amount (int64) and the Denom (string) but I have difficulty understanding how the Address ([]byte) is decoded.

Looking into the function that is called to decode it I can see the following steps: Initially I have:

bz -> [20 210 70 25 113 160 90 159 247 12 180 104 194 51 29 152 47 90 15 172 236 18 10 10 3 66 78 66 16 128 225 235 23] (encoded value)
rv -> bnb1wr3j9g (I think is the default value, but I'm not sure)

Then is called DecodeByteSlice(bz) and returns:

byteslice -> [210 70 25 113 160 90 159 247 12 180 104 194 51 29 152 47 90 15 172 236]
_n -> 21

Then is called rv.Set(reflect.ValueOf(byteslice)) and I got in rv the Address decoded:

reflect.ValueOf(byteslice) returns -> [210 70 25 113 160 90 159 247 12 180 104 194 51 29 152 47 90 15 172 236] //the same value as byteslice
rv -> bnb16frpjudqt20lwr95drprx8vc9adqlt8vzpmukw

I don't understand how from byteslice I can obtain the final value of rv.

Can someone help me or guide me? I appreciate any response. Thanks in advance

jaekwon commented 4 years ago

Looks like you're printing the .String() value of rv.Elem()? How are you printing rv -> ...? What is rv.Type? See if there is a .String() method implemented there. This is using bech32 to encode the 20 bytes starting with [210, 70, ...] using the bech32 prefix of "bnb". Good luck, sorry for the late reply.

salahzsh commented 4 years ago

This was the key

This is using bech32 to encode the 20 bytes

Could solve it, thanks for replying anyway!