cosmos tendermint irisnet 的amino編解碼解析
amino編解碼,加解密
amino編解碼
amino編解碼可以稱之為protobuf3的一次升級,再protobuf3的基礎上新增了對interface
的直接支援,也就說:可以直接把序列化好的資料unmarshal到一個介面物件中,但是這需要把定義的interface
和實現interface
的物件事前註冊到amino的編解碼物件中。具體例子如下:
cdc := amino.NewCodec()
cdc.RegisterInterface((*MyInterface1)(nil), nil)
cdc.RegisterInterface((*MyInterface2)(nil), nil)
cdc.RegisterConcrete(MyStruct1{}, "com.tendermint/MyStruct1", nil)
cdc.RegisterConcrete(MyStruct2{}, "com.tendermint/MyStruct2", nil)
cdc.RegisterConcrete(&MyStruct3{}, "anythingcangoinhereifitsunique", nil)
請注意,註冊介面時要註冊介面的指標,實現介面物件的註冊要注意的是實現方法的接受物件是指標還是物件本身。
註冊介面實現物件時需要提供一個名字。這個名字需要全域性唯一,為了防止大量註冊物件時的碰撞問題,會對這個名字進行一定的運算,從而計算出字首,字首一般是4個位元組,如果為了取得更好的防碰撞性,也可以在4個位元組的前面加上3個位元組的消岐位元組,字首位元組和消岐位元組都不能是0,具體的演算法如下: 對註冊時的名字進行sha256計算:
> hash := sha256("com.tendermint.consensus/MyConcreteName")
> hex.EncodeBytes(hash) // 0x{00 00 A8 FC 54 00 00 00 BB 9C 83 DD ...} (example)
去掉0
> rest = dropLeadingZeroBytes(hash) // 0x{A8 FC 54 00 00 00 BB 9C 83 DD ...}
> disamb = rest[0:3]
> rest = dropLeadingZeroBytes(rest[3:])
> prefix = rest[0:4]
結果如下:
> <0xA8 0xFC 0x54> [0xBB 0x9C 9x83 9xDD] // <Disamb Bytes> and [Prefix Bytes]
詳細標準請參考:amino spec
cosmos專案加解密
Ed25519,Secp256k1都稱之為橢圓加密演算法,只是他們採用的引數不一樣,比特幣和以太坊都是採用了Secp256k1演算法,而Cosmos專案同時採用了這兩種演算法,驗證者的consensus簽名採用的是Ed25519非對稱加密,使用者交易的簽名採用的是Secp256k1非對稱加密。
在cosmos專案中定義了兩個介面:
//tendermint/crypto/crypto.go
type PubKey interface {
Address() Address
Bytes() []byte
VerifyBytes(msg []byte, sig []byte) bool
Equals(PubKey) bool
}
type PrivKey interface {
Bytes() []byte
Sign(msg []byte) ([]byte, error)
PubKey() PubKey
Equals(PrivKey) bool
}
不管Ed25519還是Secp256k1的公私鑰都實現以上兩個介面,通過一下程式碼進行註冊,可以對公私鑰進行很方便的序列化。
//tendermint/crypto/encoding/amino/amino.go
// RegisterAmino registers all crypto related types in the given (amino) codec.
func RegisterAmino(cdc *amino.Codec) {
// These are all written here instead of
cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
cdc.RegisterConcrete(ed25519.PubKeyEd25519{},
"tendermint/PubKeyEd25519", nil)
cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{},
"tendermint/PubKeySecp256k1", nil)
cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
cdc.RegisterConcrete(ed25519.PrivKeyEd25519{},
"tendermint/PrivKeyEd25519", nil)
cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{},
"tendermint/PrivKeySecp256k1", nil)
}
按照amino的規範,對註冊名字進行sha256,並擷取[3:4]可以得到各個公私鑰的字首,也可以用以下快捷表進行換算。
Type | Name | Prefix | Length | Notes |
---|---|---|---|---|
PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | |
PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | |
PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | |
PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 |
例如:
經過amino編碼的33個位元組(21位元組16進位制)Secp256k1公鑰:
020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9
按照以上表格進行編碼得到:
EB5AE98721020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9
我們可以從字首輕易的看出到底是公鑰還是私鑰,也可以很輕易的辨認出是那種非對稱加密。
地址
-
Ed25519地址演算法
address = SHA256(pubkey)[:20]
- Secp256k1地址演算法
address = RIPEMD160(SHA256(pubkey))
和比特幣一樣。RIPEMD160
也是一種hash演算法。
bech32
為了增加地址的魯棒性,可以更好的進行正確性檢查,cosmos採用bech32格式來表示地址和公鑰,當然,程式內部很多地方還是使用16進位制編碼或者base64編碼來表示的。bech32的字首我們稱之為:human readable part(HRP),以下表格詳細解釋了HRP所表示的意思。
HRP | Definition |
---|---|
cosmos | Cosmos 賬戶地址,本地資料庫 |
cosmospub | Cosmos 賬戶公鑰,本地資料庫 |
cosmosvalcons | Cosmos 驗證者共識地址,也就是來自於priv_validator.json檔案 |
cosmosvalconspub | Cosmos 驗證者共識公鑰,也就是來自於priv_validator.json檔案 |
cosmosvaloper | Bond驗證者共識地址的賬戶地址 |
cosmosvaloperpub | Bond驗證者共識地址的賬戶公鑰 |
更多cosmos, tendermint筆記請訪問並關注我的github:https://github.com/elvin-du/cosmos-sdk-code-analysis
相關文章
- Go物件導向程式設計以及在Tendermint/Cosmos-SDK中的應用Go物件程式設計
- Go函數語言程式設計以及在Tendermint/Cosmos-SDK中的應用Go函數程式設計
- Tendermint的學習
- gookit/properties - Java Properties 格式內容的解析,編碼解碼庫GoJava
- Dubbo中編碼和解碼的解析
- Netty 中的訊息解析和編解碼器Netty
- Vue 原始碼解讀(8)—— 編譯器 之 解析(下)Vue原始碼編譯
- Vue 原始碼解讀(8)—— 編譯器 之 解析(上)Vue原始碼編譯
- LevelDB 原始碼解析之 Varint 編碼原始碼
- OpenLR 的編碼與解碼
- iOS socket通訊,編解碼,浮點型資料解析iOS
- Netty原始碼深度解析(九)-編碼Netty原始碼
- jdom解析中文編碼問題
- bencoding編碼解析器Encoding
- python中的編碼&解碼Python
- 螞蟻金服通訊框架SOFABolt解析|編解碼機制框架
- Android 中的編碼與解碼Android
- 解碼返回Unicode編碼的文字Unicode
- Java之Base64編碼解析Java
- 區塊鏈時代的拜占庭容錯:Tendermint(二)區塊鏈
- Javascript編碼解碼URLJavaScript
- Unicode編碼解碼Unicode
- NSCoding協議的編碼與解碼協議
- Unicode編碼解碼的全面介紹Unicode
- 共識演算法的比較:Casper vs Tendermint演算法
- 圖解Protobuf編碼圖解
- 深入解析字符集和字元編碼字元
- 字元編碼常識及問題解析字元
- URL編碼與解碼原理
- iOS Emoji表情編碼/解碼iOS
- springweb開發中編碼亂碼問題解析SpringWeb
- SDWebImage原始碼解析之SDWebImageManager的註解Web原始碼
- NIO框架之MINA原始碼解析(四):粘包與斷包處理及編碼與解碼框架原始碼
- Base24編碼以及解碼的實現
- tendermint區塊鏈五分鐘入門區塊鏈
- Go JSON編碼與解碼?GoJSON
- 3.3 編碼/解碼演算法演算法
- Base64 編碼解碼原理