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函數程式設計
- Netty 中的訊息解析和編解碼器Netty
- Tendermint的學習
- gookit/properties - Java Properties 格式內容的解析,編碼解碼庫GoJava
- Vue 原始碼解讀(8)—— 編譯器 之 解析(上)Vue原始碼編譯
- Vue 原始碼解讀(8)—— 編譯器 之 解析(下)Vue原始碼編譯
- OpenLR 的編碼與解碼
- python中的編碼&解碼Python
- Netty原始碼深度解析(九)-編碼Netty原始碼
- LevelDB 原始碼解析之 Varint 編碼原始碼
- 解碼返回Unicode編碼的文字Unicode
- Unicode編碼解碼Unicode
- Cosmos 是什麼? 一文了解Cosmos的來龍去脈
- 螞蟻金服通訊框架SOFABolt解析|編解碼機制框架
- Unicode編碼解碼的全面介紹Unicode
- Java之Base64編碼解析Java
- Javascript編碼解碼URLJavaScript
- NCF 的Azure Cosmos DB 演示案例
- 【Netty】編解碼器Netty
- 音視訊編解碼 -- 編碼引數 CRFCRF
- Go JSON編碼與解碼?GoJSON
- URL編碼與解碼原理
- SDWebImage原始碼解析之SDWebImageManager的註解Web原始碼
- 共識演算法的比較:Casper vs Tendermint演算法
- 區塊鏈時代的拜占庭容錯:Tendermint(二)區塊鏈
- 3.3 編碼/解碼演算法演算法
- Glide原始碼解析四(解碼和轉碼)IDE原始碼
- Rust中字串的base64編碼與解碼Rust字串
- 編解碼器軟體支援 WMP,因為它使用 Directshow 編解碼器
- 基於Base64編/解碼演算法的Spring Boot檔案上傳技術解析演算法Spring Boot
- 深入解析 H.265 編碼模式,帶你瞭解Apple全面推進H.265的原因模式APP
- 深入瞭解SpringMVC原始碼解析SpringMVC原始碼
- 詳解HashMap原始碼解析(下)HashMap原始碼
- 詳解HashMap原始碼解析(上)HashMap原始碼
- 關於使用Markdown解析器Parsedown應該注意的編碼...
- JSP 的本質原理解析:"編寫的時候是JSP,心裡想解讀的是 java 原始碼"JSJava原始碼
- Spring MVC 中文編碼亂碼解決SpringMVC