Browse Source

Merge pull request #325 from tendermint/sign_bytes

Sign bytes
pull/336/head
Ethan Buchman 8 years ago
committed by GitHub
parent
commit
f33cc3fb3b
7 changed files with 132 additions and 31 deletions
  1. +2
    -3
      types/block.go
  2. +77
    -0
      types/canonical_json.go
  3. +1
    -1
      types/part_set.go
  4. +11
    -14
      types/proposal.go
  5. +33
    -8
      types/proposal_test.go
  6. +4
    -4
      types/vote.go
  7. +4
    -1
      types/vote_set_test.go

+ 2
- 3
types/block.go View File

@ -409,10 +409,9 @@ func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
if blockID.IsZero() {
wire.WriteTo([]byte("null"), w, n, err)
} else {
wire.WriteTo([]byte(Fmt(`{"hash":"%X","parts":`, blockID.Hash)), w, n, err)
blockID.PartsHeader.WriteSignBytes(w, n, err)
wire.WriteTo([]byte("}"), w, n, err)
wire.WriteJSON(CanonicalBlockID(blockID), w, n, err)
}
}
func (blockID BlockID) String() string {


+ 77
- 0
types/canonical_json.go View File

@ -0,0 +1,77 @@
package types
// canonical json is go-wire's json for structs with fields in alphabetical order
type CanonicalJSONBlockID struct {
Hash []byte `json:"hash,omitempty"`
PartsHeader CanonicalJSONPartSetHeader `json:"parts,omitempty"`
}
type CanonicalJSONPartSetHeader struct {
Hash []byte `json:"hash"`
Total int `json:"total"`
}
type CanonicalJSONProposal struct {
BlockPartsHeader CanonicalJSONPartSetHeader `json:"block_parts_header"`
Height int `json:"height"`
POLBlockID CanonicalJSONBlockID `json:"pol_block_id"`
POLRound int `json:"pol_round"`
Round int `json:"round"`
}
type CanonicalJSONVote struct {
BlockID CanonicalJSONBlockID `json:"block_id"`
Height int `json:"height"`
Round int `json:"round"`
Type byte `json:"type"`
}
//------------------------------------
// Messages including a "chain id" can only be applied to one chain, hence "Once"
type CanonicalJSONOnceProposal struct {
ChainID string `json:"chain_id"`
Proposal CanonicalJSONProposal `json:"proposal"`
}
type CanonicalJSONOnceVote struct {
ChainID string `json:"chain_id"`
Vote CanonicalJSONVote `json:"vote"`
}
//-----------------------------------
// Canonicalize the structs
func CanonicalBlockID(blockID BlockID) CanonicalJSONBlockID {
return CanonicalJSONBlockID{
Hash: blockID.Hash,
PartsHeader: CanonicalPartSetHeader(blockID.PartsHeader),
}
}
func CanonicalPartSetHeader(psh PartSetHeader) CanonicalJSONPartSetHeader {
return CanonicalJSONPartSetHeader{
psh.Hash,
psh.Total,
}
}
func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
return CanonicalJSONProposal{
BlockPartsHeader: CanonicalPartSetHeader(proposal.BlockPartsHeader),
Height: proposal.Height,
POLBlockID: CanonicalBlockID(proposal.POLBlockID),
POLRound: proposal.POLRound,
Round: proposal.Round,
}
}
func CanonicalVote(vote *Vote) CanonicalJSONVote {
return CanonicalJSONVote{
CanonicalBlockID(vote.BlockID),
vote.Height,
vote.Round,
vote.Type,
}
}

+ 1
- 1
types/part_set.go View File

@ -74,7 +74,7 @@ func (psh PartSetHeader) Equals(other PartSetHeader) bool {
}
func (psh PartSetHeader) WriteSignBytes(w io.Writer, n *int, err *error) {
wire.WriteTo([]byte(Fmt(`{"hash":"%X","total":%v}`, psh.Hash, psh.Total)), w, n, err)
wire.WriteJSON(CanonicalPartSetHeader(psh), w, n, err)
}
//-------------------------------------


+ 11
- 14
types/proposal.go View File

@ -5,7 +5,7 @@ import (
"fmt"
"io"
. "github.com/tendermint/go-common"
//. "github.com/tendermint/go-common"
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
)
@ -16,12 +16,12 @@ var (
)
type Proposal struct {
Height int `json:"height"`
Round int `json:"round"`
BlockPartsHeader PartSetHeader `json:"block_parts_header"`
POLRound int `json:"pol_round"` // -1 if null.
POLBlockID BlockID `json:"pol_block_id"` // zero if null.
Signature crypto.SignatureEd25519 `json:"signature"`
Height int `json:"height"`
Round int `json:"round"`
BlockPartsHeader PartSetHeader `json:"block_parts_header"`
POLRound int `json:"pol_round"` // -1 if null.
POLBlockID BlockID `json:"pol_block_id"` // zero if null.
Signature crypto.Signature `json:"signature"`
}
// polRound: -1 if no polRound.
@ -41,11 +41,8 @@ func (p *Proposal) String() string {
}
func (p *Proposal) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
wire.WriteTo([]byte(Fmt(`{"chain_id":"%s"`, chainID)), w, n, err)
wire.WriteTo([]byte(`,"proposal":{"block_parts_header":`), w, n, err)
p.BlockPartsHeader.WriteSignBytes(w, n, err)
wire.WriteTo([]byte(Fmt(`,"height":%v,"pol_block_id":`, p.Height)), w, n, err)
p.POLBlockID.WriteSignBytes(w, n, err)
wire.WriteTo([]byte(Fmt(`,"pol_round":%v`, p.POLRound)), w, n, err)
wire.WriteTo([]byte(Fmt(`,"round":%v}}`, p.Round)), w, n, err)
wire.WriteJSON(CanonicalJSONOnceProposal{
ChainID: chainID,
Proposal: CanonicalProposal(p),
}, w, n, err)
}

+ 33
- 8
types/proposal_test.go View File

@ -4,18 +4,43 @@ import (
"testing"
)
var testProposal = &Proposal{
Height: 12345,
Round: 23456,
BlockPartsHeader: PartSetHeader{111, []byte("blockparts")},
POLRound: -1,
}
func TestProposalSignable(t *testing.T) {
proposal := &Proposal{
Height: 12345,
Round: 23456,
BlockPartsHeader: PartSetHeader{111, []byte("blockparts")},
POLRound: -1,
}
signBytes := SignBytes("test_chain_id", proposal)
signBytes := SignBytes("test_chain_id", testProposal)
signStr := string(signBytes)
expected := `{"chain_id":"test_chain_id","proposal":{"block_parts_header":{"hash":"626C6F636B7061727473","total":111},"height":12345,"pol_block_id":null,"pol_round":-1,"round":23456}}`
expected := `{"chain_id":"test_chain_id","proposal":{"block_parts_header":{"hash":"626C6F636B7061727473","total":111},"height":12345,"pol_block_id":{},"pol_round":-1,"round":23456}}`
if signStr != expected {
t.Errorf("Got unexpected sign string for Proposal. Expected:\n%v\nGot:\n%v", expected, signStr)
}
}
func BenchmarkProposalWriteSignBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
SignBytes("test_chain_id", testProposal)
}
}
func BenchmarkProposalSign(b *testing.B) {
privVal := GenPrivValidator()
for i := 0; i < b.N; i++ {
privVal.Sign(SignBytes("test_chain_id", testProposal))
}
}
func BenchmarkProposalVerifySignature(b *testing.B) {
signBytes := SignBytes("test_chain_id", testProposal)
privVal := GenPrivValidator()
signature := privVal.Sign(signBytes)
pubKey := privVal.PubKey
for i := 0; i < b.N; i++ {
pubKey.VerifyBytes(SignBytes("test_chain_id", testProposal), signature)
}
}

+ 4
- 4
types/vote.go View File

@ -57,10 +57,10 @@ type Vote struct {
}
func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
wire.WriteTo([]byte(Fmt(`{"chain_id":"%s"`, chainID)), w, n, err)
wire.WriteTo([]byte(`,"vote":{"block_id":`), w, n, err)
vote.BlockID.WriteSignBytes(w, n, err)
wire.WriteTo([]byte(Fmt(`,"height":%v,"round":%v,"type":%v}}`, vote.Height, vote.Round, vote.Type)), w, n, err)
wire.WriteJSON(CanonicalJSONOnceVote{
chainID,
CanonicalVote(vote),
}, w, n, err)
}
func (vote *Vote) Copy() *Vote {


+ 4
- 1
types/vote_set_test.go View File

@ -92,7 +92,10 @@ func TestAddVote(t *testing.T) {
Type: VoteTypePrevote,
BlockID: BlockID{nil, PartSetHeader{}},
}
signAddVote(val0, vote, voteSet)
_, err := signAddVote(val0, vote, voteSet)
if err != nil {
t.Error(err)
}
if voteSet.GetByAddress(val0.Address) == nil {
t.Errorf("Expected GetByAddress(val0.Address) to be present")


Loading…
Cancel
Save