diff --git a/docs/specification/new-spec/abci.md b/docs/specification/new-spec/abci.md index d942c800..75eed6b5 100644 --- a/docs/specification/new-spec/abci.md +++ b/docs/specification/new-spec/abci.md @@ -28,7 +28,7 @@ message Validator { The `pub_key` is the Amino encoded public key for the validator. For details on Amino encoded public keys, see the [section of the encoding spec](./encoding.md#public-key-cryptography). -For example, the 32-byte Ed25519 pubkey +For Ed25519 pubkeys, the Amino prefix is always "1624DE6220". For example, the 32-byte Ed25519 pubkey `76852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` would be Amino encoded as `1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` @@ -44,5 +44,23 @@ following rules: set with the given power - if the validator does already exist, its power will be adjusted to the given power - ## Query + +Query is a generic message type with lots of flexibility to enable diverse sets +of queries from applications. Tendermint has no requirements from the Query +message for normal operation - that is, the ABCI app developer need not implement Query functionality if they do not wish too. +That said, Tendermint makes a number of queries to support some optional +features. These are: + +### Peer Filtering + +When Tendermint connects to a peer, it sends two queries to the ABCI application +using the following paths, with no additional data: + + - `/p2p/filter/addr/`, where `` denote the IP address and + the port of the connection + - `p2p/filter/pubkey/`, where `` is the peer node ID (ie. the + pubkey.Address() for the peer's PubKey) + +If either of these queries return a non-zero ABCI code, Tendermint will refuse +to connect to the peer. diff --git a/docs/specification/new-spec/encoding.md b/docs/specification/new-spec/encoding.md index 83154c85..e15c370b 100644 --- a/docs/specification/new-spec/encoding.md +++ b/docs/specification/new-spec/encoding.md @@ -15,6 +15,9 @@ Notably, every object that satisfies an interface (eg. a particular kind of p2p or a particular kind of pubkey) is registered with a global name, the hash of which is included in the object's encoding as the so-called "prefix bytes". +We define the `func AminoEncode(obj interface{}) []byte` function to take an +arbitrary object and return the Amino encoded bytes. + ## Byte Arrays The encoding of a byte array is simply the raw-bytes prefixed with the length of @@ -48,6 +51,9 @@ Notice that when encoding byte-arrays, the length of the byte-array is appended to the PrefixBytes. Thus the encoding of a byte array becomes ` ` +(NOTE: the remainder of this section on Public Key Cryptography can be generated +from [this script](./scripts/crypto.go)) + ### PubKeyEd25519 ``` @@ -56,12 +62,21 @@ to the PrefixBytes. Thus the encoding of a byte array becomes ` // Length: 0x20 // Notes: raw 32-byte Ed25519 pubkey type PubKeyEd25519 [32]byte + +func (pubkey PubKeyEd25519) Address() []byte { + // NOTE: hash of the Amino encoded bytes! + return RIPEMD160(AminoEncode(pubkey)) +} ``` For example, the 32-byte Ed25519 pubkey -`76852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` would be +`CCACD52F9B29D04393F01CD9AF6535455668115641F3D8BAEFD2295F24BAF60E` would be encoded as -`1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` +`1624DE6220CCACD52F9B29D04393F01CD9AF6535455668115641F3D8BAEFD2295F24BAF60E`. + +The address would then be +`RIPEMD160(0x1624DE6220CCACD52F9B29D04393F01CD9AF6535455668115641F3D8BAEFD2295F24BAF60E)` +or `430FF75BAF1EC4B0D51BB3EEC2955479D0071605` ### SignatureEd25519 @@ -74,9 +89,9 @@ type SignatureEd25519 [64]byte ``` For example, the 64-byte Ed25519 signature -`005E76B3B0D790959B03F862A9EF8F6236457032B5F522C4CAB5AAD7C44A00A12669E1A2761798E70A0A923DA0CF981839558123CF6466553BCBFF25DADD630F` +`1B6034A8ED149D3C94FDA13EC03B26CC0FB264D9B0E47D3FA3DEF9FCDE658E49C80B35F9BE74949356401B15B18FB817D6E54495AD1C4A8401B248466CB0DB0B` would be encoded as -`3DA1DB2A40005E76B3B0D790959B03F862A9EF8F6236457032B5F522C4CAB5AAD7C44A00A12669E1A2761798E70A0A923DA0CF981839558123CF6466553BCBFF25DADD630F` +`3DA1DB2A401B6034A8ED149D3C94FDA13EC03B26CC0FB264D9B0E47D3FA3DEF9FCDE658E49C80B35F9BE74949356401B15B18FB817D6E54495AD1C4A8401B248466CB0DB0B` ### PrivKeyEd25519 @@ -85,6 +100,7 @@ would be encoded as // Notes: raw 32-byte priv key concatenated to raw 32-byte pub key type PrivKeyEd25519 [64]byte ``` + ### PubKeySecp256k1 ``` @@ -93,12 +109,22 @@ type PrivKeyEd25519 [64]byte // Length: 0x21 // Notes: OpenSSL compressed pubkey prefixed with 0x02 or 0x03 type PubKeySecp256k1 [33]byte + +func (pubkey PubKeySecp256k1) Address() []byte { + // NOTE: hash of the raw pubkey bytes (not Amino encoded!). + // Compatible with Bitcoin addresses. + return RIPEMD160(SHA256(pubkey[:])) +} ``` For example, the 33-byte Secp256k1 pubkey -`03573E0EC1F989DECC3913AC7D44D0509C1A992ECE700845594A1078DAF19A3380` would be +`020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9` would be encoded as -`EB5AE9822103573E0EC1F989DECC3913AC7D44D0509C1A992ECE700845594A1078DAF19A3380` +`EB5AE98221020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9` + +The address would then be +`RIPEMD160(SHA256(0x020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9))` +or `0AE5BEE929ABE51BAD345DB925EEA652680783FC` ### SignatureSecp256k1 @@ -112,9 +138,9 @@ type SignatureSecp256k1 []byte ``` For example, the Secp256k1 signature -`304402207447640A5C12A72BAA052D110B666FB6DF717A7B863361C092E751D016C6C08802205C20F9DEBF8915DED310B98BFA890105F43925FDB2B67B78510FE18EDA2B30DA` would -be encoded as -`16E1FEEA46304402202C10C874E413AF538D97EBEF2B01024719F8B7CC559CEEBDC7C380F9DCC4A6E002200EDE9B62F8531933F88DB2A62E73BA3D43ACEB1CBD23070C2F792AAA18717A4A` +`304402201CD4B8C764D2FD8AF23ECFE6666CA8A53886D47754D951295D2D311E1FEA33BF02201E0F906BB1CF2C30EAACFFB032A7129358AFF96B9F79B06ACFFB18AC90C2ADD7` +would be encoded as +`16E1FEEA46304402201CD4B8C764D2FD8AF23ECFE6666CA8A53886D47754D951295D2D311E1FEA33BF02201E0F906BB1CF2C30EAACFFB032A7129358AFF96B9F79B06ACFFB18AC90C2ADD7` ### PrivKeySecp256k1 @@ -124,8 +150,6 @@ be encoded as type PrivKeySecp256k1 [32]byte ``` - - ## Other Common Types ### BitArray diff --git a/docs/specification/new-spec/scripts/crypto.go b/docs/specification/new-spec/scripts/crypto.go index 704a21c3..e4dbd8a2 100644 --- a/docs/specification/new-spec/scripts/crypto.go +++ b/docs/specification/new-spec/scripts/crypto.go @@ -6,8 +6,11 @@ import ( crypto "github.com/tendermint/go-crypto" ) +// SECRET +var SECRET = []byte("some secret") + func printEd() { - priv := crypto.GenPrivKeyEd25519() + priv := crypto.GenPrivKeyEd25519FromSecret(SECRET) pub := priv.PubKey().(crypto.PubKeyEd25519) sig := priv.Sign([]byte("hello")).(crypto.SignatureEd25519) @@ -22,9 +25,15 @@ func printEd() { fmt.Printf("// Length: 0x%X \n", length) fmt.Println("// Notes: raw 32-byte Ed25519 pubkey") fmt.Println("type PubKeyEd25519 [32]byte") + fmt.Println("") + fmt.Println(`func (pubkey PubKeyEd25519) Address() []byte { + // NOTE: hash of the Amino encoded bytes! + return RIPEMD160(AminoEncode(pubkey)) +}`) fmt.Println("```") fmt.Println("") - fmt.Printf("For example, the 32-byte Ed25519 pubkey `%X` would be encoded as `%X`\n", pub[:], pub.Bytes()) + fmt.Printf("For example, the 32-byte Ed25519 pubkey `%X` would be encoded as `%X`.\n\n", pub[:], pub.Bytes()) + fmt.Printf("The address would then be `RIPEMD160(0x%X)` or `%X`\n", pub.Bytes(), pub.Address()) fmt.Println("") name = "tendermint/SignatureKeyEd25519" @@ -55,7 +64,7 @@ func printEd() { } func printSecp() { - priv := crypto.GenPrivKeySecp256k1() + priv := crypto.GenPrivKeySecp256k1FromSecret(SECRET) pub := priv.PubKey().(crypto.PubKeySecp256k1) sig := priv.Sign([]byte("hello")).(crypto.SignatureSecp256k1) @@ -70,9 +79,16 @@ func printSecp() { fmt.Printf("// Length: 0x%X \n", length) fmt.Println("// Notes: OpenSSL compressed pubkey prefixed with 0x02 or 0x03") fmt.Println("type PubKeySecp256k1 [33]byte") + fmt.Println("") + fmt.Println(`func (pubkey PubKeySecp256k1) Address() []byte { + // NOTE: hash of the raw pubkey bytes (not Amino encoded!). + // Compatible with Bitcoin addresses. + return RIPEMD160(SHA256(pubkey[:])) +}`) fmt.Println("```") fmt.Println("") - fmt.Printf("For example, the 33-byte Secp256k1 pubkey `%X` would be encoded as `%X`\n", pub[:], pub.Bytes()) + fmt.Printf("For example, the 33-byte Secp256k1 pubkey `%X` would be encoded as `%X`\n\n", pub[:], pub.Bytes()) + fmt.Printf("The address would then be `RIPEMD160(SHA256(0x%X))` or `%X`\n", pub[:], pub.Address()) fmt.Println("") name = "tendermint/SignatureKeySecp256k1" @@ -104,5 +120,6 @@ func printSecp() { func main() { printEd() + fmt.Println("") printSecp() }