From 89665e7d6734476b9fbcb662f7c2c31e13cbbdd7 Mon Sep 17 00:00:00 2001 From: Stevan Ognjanovic Date: Tue, 9 Jun 2020 17:15:32 +0200 Subject: [PATCH 01/12] types: Remove duplicated validation in VerifyCommit (#4991) --- types/validator_set.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/types/validator_set.go b/types/validator_set.go index 3591b9207..cf04df6dd 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -671,13 +671,6 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", blockID, commit.BlockID) } - if height != commit.Height { - return NewErrInvalidCommitHeight(height, commit.Height) - } - if !blockID.Equals(commit.BlockID) { - return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", - blockID, commit.BlockID) - } talliedVotingPower := int64(0) votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 From 660e72a12f977a9b52659e263d096406b181b2ba Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Tue, 9 Jun 2020 18:09:51 +0200 Subject: [PATCH 02/12] p2p/conn: migrate to Protobuf (#4990) Migrates the p2p connections to Protobuf. Supersedes #4800. gogoproto's `NewDelimitedReader()` uses an internal buffer, which makes it unsuitable for reading individual messages from a shared reader (since any remaining data in the buffer will be discarded). We therefore add a new `protoio` package with an unbuffered `NewDelimitedReader()`. Additionally, the `NewDelimitedWriter()` returns the number of bytes written, and we've added `MarshalDelimited()` and `UnmarshalDelimited()`, to ease migration of existing code. --- libs/protoio/io.go | 96 ++++++++ libs/protoio/io_test.go | 157 ++++++++++++++ libs/protoio/reader.go | 88 ++++++++ libs/protoio/writer.go | 100 +++++++++ p2p/conn/codec.go | 14 -- p2p/conn/connection.go | 147 +++++++------ p2p/conn/connection_test.go | 145 +++++++------ p2p/conn/evil_secret_connection_test.go | 27 ++- p2p/conn/secret_connection.go | 52 +++-- p2p/conn/secret_connection_test.go | 32 +-- proto/p2p/conn_msgs.pb.go | 277 ++++++++++++++++++++++-- proto/p2p/conn_msgs.proto | 6 + 12 files changed, 925 insertions(+), 216 deletions(-) create mode 100644 libs/protoio/io.go create mode 100644 libs/protoio/io_test.go create mode 100644 libs/protoio/reader.go create mode 100644 libs/protoio/writer.go delete mode 100644 p2p/conn/codec.go diff --git a/libs/protoio/io.go b/libs/protoio/io.go new file mode 100644 index 000000000..91acbb71b --- /dev/null +++ b/libs/protoio/io.go @@ -0,0 +1,96 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Modified to return number of bytes written by Writer.WriteMsg(), and added byteReader. + +package protoio + +import ( + "io" + + "github.com/gogo/protobuf/proto" +) + +type Writer interface { + WriteMsg(proto.Message) (int, error) +} + +type WriteCloser interface { + Writer + io.Closer +} + +type Reader interface { + ReadMsg(msg proto.Message) error +} + +type ReadCloser interface { + Reader + io.Closer +} + +type marshaler interface { + MarshalTo(data []byte) (n int, err error) +} + +func getSize(v interface{}) (int, bool) { + if sz, ok := v.(interface { + Size() (n int) + }); ok { + return sz.Size(), true + } else if sz, ok := v.(interface { + ProtoSize() (n int) + }); ok { + return sz.ProtoSize(), true + } else { + return 0, false + } +} + +// byteReader wraps an io.Reader and implements io.ByteReader. Reading one byte at a +// time is extremely slow, but this is what Amino did already, and the caller can +// wrap the reader in bufio.Reader if appropriate. +type byteReader struct { + io.Reader + bytes []byte +} + +func newByteReader(r io.Reader) *byteReader { + return &byteReader{ + Reader: r, + bytes: make([]byte, 1), + } +} + +func (r *byteReader) ReadByte() (byte, error) { + _, err := r.Read(r.bytes) + if err != nil { + return 0, err + } + return r.bytes[0], nil +} diff --git a/libs/protoio/io_test.go b/libs/protoio/io_test.go new file mode 100644 index 000000000..5ec5627d2 --- /dev/null +++ b/libs/protoio/io_test.go @@ -0,0 +1,157 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package protoio_test + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "math/rand" + "testing" + "time" + + "github.com/gogo/protobuf/proto" + "github.com/gogo/protobuf/test" + + "github.com/tendermint/tendermint/libs/protoio" +) + +func iotest(writer protoio.WriteCloser, reader protoio.ReadCloser) error { + varint := make([]byte, binary.MaxVarintLen64) + size := 1000 + msgs := make([]*test.NinOptNative, size) + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for i := range msgs { + msgs[i] = test.NewPopulatedNinOptNative(r, true) + //issue 31 + if i == 5 { + msgs[i] = &test.NinOptNative{} + } + //issue 31 + if i == 999 { + msgs[i] = &test.NinOptNative{} + } + // FIXME Check size + bz, err := proto.Marshal(msgs[i]) + if err != nil { + return err + } + visize := binary.PutUvarint(varint, uint64(len(bz))) + n, err := writer.WriteMsg(msgs[i]) + if err != nil { + return err + } + if n != len(bz)+visize { + return fmt.Errorf("WriteMsg() wrote %v bytes, expected %v", n, len(bz)+visize) // nolint + } + } + if err := writer.Close(); err != nil { + return err + } + i := 0 + for { + msg := &test.NinOptNative{} + if err := reader.ReadMsg(msg); err != nil { + if err == io.EOF { + break + } + return err + } + if err := msg.VerboseEqual(msgs[i]); err != nil { + return err + } + i++ + } + if i != size { + panic("not enough messages read") + } + if err := reader.Close(); err != nil { + return err + } + return nil +} + +type buffer struct { + *bytes.Buffer + closed bool +} + +func (b *buffer) Close() error { + b.closed = true + return nil +} + +func newBuffer() *buffer { + return &buffer{bytes.NewBuffer(nil), false} +} + +func TestVarintNormal(t *testing.T) { + buf := newBuffer() + writer := protoio.NewDelimitedWriter(buf) + reader := protoio.NewDelimitedReader(buf, 1024*1024) + if err := iotest(writer, reader); err != nil { + t.Error(err) + } + if !buf.closed { + t.Fatalf("did not close buffer") + } +} + +func TestVarintNoClose(t *testing.T) { + buf := bytes.NewBuffer(nil) + writer := protoio.NewDelimitedWriter(buf) + reader := protoio.NewDelimitedReader(buf, 1024*1024) + if err := iotest(writer, reader); err != nil { + t.Error(err) + } +} + +//issue 32 +func TestVarintMaxSize(t *testing.T) { + buf := newBuffer() + writer := protoio.NewDelimitedWriter(buf) + reader := protoio.NewDelimitedReader(buf, 20) + if err := iotest(writer, reader); err == nil { + t.Error(err) + } else { + t.Logf("%s", err) + } +} + +func TestVarintError(t *testing.T) { + buf := newBuffer() + buf.Write([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}) + reader := protoio.NewDelimitedReader(buf, 1024*1024) + msg := &test.NinOptNative{} + err := reader.ReadMsg(msg) + if err == nil { + t.Fatalf("Expected error") + } +} diff --git a/libs/protoio/reader.go b/libs/protoio/reader.go new file mode 100644 index 000000000..15a84899f --- /dev/null +++ b/libs/protoio/reader.go @@ -0,0 +1,88 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Modified from original GoGo Protobuf to not buffer the reader. + +package protoio + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + + "github.com/gogo/protobuf/proto" +) + +// NewDelimitedReader reads varint-delimited Protobuf messages from a reader. Unlike the gogoproto +// NewDelimitedReader, this does not buffer the reader, which may cause poor performance but is +// necessary when only reading single messages (e.g. in the p2p package). +func NewDelimitedReader(r io.Reader, maxSize int) ReadCloser { + var closer io.Closer + if c, ok := r.(io.Closer); ok { + closer = c + } + return &varintReader{newByteReader(r), nil, maxSize, closer} +} + +type varintReader struct { + r *byteReader + buf []byte + maxSize int + closer io.Closer +} + +func (r *varintReader) ReadMsg(msg proto.Message) error { + length64, err := binary.ReadUvarint(newByteReader(r.r)) + if err != nil { + return err + } + length := int(length64) + if length < 0 || length > r.maxSize { + return fmt.Errorf("message exceeds max size (%v > %v)", length, r.maxSize) + } + if len(r.buf) < length { + r.buf = make([]byte, length) + } + buf := r.buf[:length] + if _, err := io.ReadFull(r.r, buf); err != nil { + return err + } + return proto.Unmarshal(buf, msg) +} + +func (r *varintReader) Close() error { + if r.closer != nil { + return r.closer.Close() + } + return nil +} + +func UnmarshalDelimited(data []byte, msg proto.Message) error { + return NewDelimitedReader(bytes.NewReader(data), len(data)).ReadMsg(msg) +} diff --git a/libs/protoio/writer.go b/libs/protoio/writer.go new file mode 100644 index 000000000..d4c66798f --- /dev/null +++ b/libs/protoio/writer.go @@ -0,0 +1,100 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Modified from original GoGo Protobuf to return number of bytes written. + +package protoio + +import ( + "bytes" + "encoding/binary" + "io" + + "github.com/gogo/protobuf/proto" +) + +// NewDelimitedWriter writes a varint-delimited Protobuf message to a writer. It is +// equivalent to the gogoproto NewDelimitedWriter, except WriteMsg() also returns the +// number of bytes written, which is necessary in the p2p package. +func NewDelimitedWriter(w io.Writer) WriteCloser { + return &varintWriter{w, make([]byte, binary.MaxVarintLen64), nil} +} + +type varintWriter struct { + w io.Writer + lenBuf []byte + buffer []byte +} + +func (w *varintWriter) WriteMsg(msg proto.Message) (int, error) { + if m, ok := msg.(marshaler); ok { + n, ok := getSize(m) + if ok { + if n+binary.MaxVarintLen64 >= len(w.buffer) { + w.buffer = make([]byte, n+binary.MaxVarintLen64) + } + lenOff := binary.PutUvarint(w.buffer, uint64(n)) + _, err := m.MarshalTo(w.buffer[lenOff:]) + if err != nil { + return 0, err + } + _, err = w.w.Write(w.buffer[:lenOff+n]) + return lenOff + n, err + } + } + + // fallback + data, err := proto.Marshal(msg) + if err != nil { + return 0, err + } + length := uint64(len(data)) + n := binary.PutUvarint(w.lenBuf, length) + _, err = w.w.Write(w.lenBuf[:n]) + if err != nil { + return 0, err + } + _, err = w.w.Write(data) + return len(data) + n, err +} + +func (w *varintWriter) Close() error { + if closer, ok := w.w.(io.Closer); ok { + return closer.Close() + } + return nil +} + +func MarshalDelimited(msg proto.Message) ([]byte, error) { + var buf bytes.Buffer + _, err := NewDelimitedWriter(&buf).WriteMsg(msg) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/p2p/conn/codec.go b/p2p/conn/codec.go deleted file mode 100644 index 0625c7a38..000000000 --- a/p2p/conn/codec.go +++ /dev/null @@ -1,14 +0,0 @@ -package conn - -import ( - amino "github.com/tendermint/go-amino" - - cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino" -) - -var cdc *amino.Codec = amino.NewCodec() - -func init() { - cryptoamino.RegisterAmino(cdc) - RegisterPacket(cdc) -} diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index f2e02fbc9..dc53bcd95 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -2,25 +2,26 @@ package conn import ( "bufio" - "runtime/debug" - "errors" "fmt" "io" "math" "net" "reflect" + "runtime/debug" "sync" "sync/atomic" "time" - amino "github.com/tendermint/go-amino" + "github.com/gogo/protobuf/proto" flow "github.com/tendermint/tendermint/libs/flowrate" "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" + "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/libs/service" "github.com/tendermint/tendermint/libs/timer" + tmp2p "github.com/tendermint/tendermint/proto/p2p" ) const ( @@ -66,7 +67,7 @@ There are two methods for sending messages: `Send(chID, msgBytes)` is a blocking call that waits until `msg` is successfully queued for the channel with the given id byte `chID`, or until the -request times out. The message `msg` is serialized using Go-Amino. +request times out. The message `msg` is serialized using Protobuf. `TrySend(chID, msgBytes)` is a nonblocking call that returns false if the channel's queue is full. @@ -418,9 +419,11 @@ func (c *MConnection) CanSend(chID byte) bool { func (c *MConnection) sendRoutine() { defer c._recover() + protoWriter := protoio.NewDelimitedWriter(c.bufConnWriter) + FOR_LOOP: for { - var _n int64 + var _n int var err error SELECTION: select { @@ -434,11 +437,12 @@ FOR_LOOP: } case <-c.pingTimer.C: c.Logger.Debug("Send Ping") - _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPing{}) + _n, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPing{})) if err != nil { + c.Logger.Error("Failed to send PacketPing", "err", err) break SELECTION } - c.sendMonitor.Update(int(_n)) + c.sendMonitor.Update(_n) c.Logger.Debug("Starting pong timer", "dur", c.config.PongTimeout) c.pongTimer = time.AfterFunc(c.config.PongTimeout, func() { select { @@ -456,11 +460,12 @@ FOR_LOOP: } case <-c.pong: c.Logger.Debug("Send Pong") - _n, err = cdc.MarshalBinaryLengthPrefixedWriter(c.bufConnWriter, PacketPong{}) + _n, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) if err != nil { + c.Logger.Error("Failed to send PacketPong", "err", err) break SELECTION } - c.sendMonitor.Update(int(_n)) + c.sendMonitor.Update(_n) c.flush() case <-c.quitSendRoutine: break FOR_LOOP @@ -540,7 +545,7 @@ func (c *MConnection) sendPacketMsg() bool { c.stopForError(err) return true } - c.sendMonitor.Update(int(_n)) + c.sendMonitor.Update(_n) c.flushTimer.Set() return false } @@ -552,6 +557,8 @@ func (c *MConnection) sendPacketMsg() bool { func (c *MConnection) recvRoutine() { defer c._recover() + protoReader := protoio.NewDelimitedReader(c.bufConnReader, c._maxPacketMsgSize) + FOR_LOOP: for { // Block until .recvMonitor says we can read. @@ -572,12 +579,9 @@ FOR_LOOP: */ // Read packet type - var packet Packet - var _n int64 - var err error - _n, err = cdc.UnmarshalBinaryLengthPrefixedReader(c.bufConnReader, &packet, int64(c._maxPacketMsgSize)) - c.recvMonitor.Update(int(_n)) + var packet tmp2p.Packet + err := protoReader.ReadMsg(&packet) if err != nil { // stopServices was invoked and we are shutting down // receiving is excpected to fail since we will close the connection @@ -599,8 +603,8 @@ FOR_LOOP: } // Read more depending on packet type. - switch pkt := packet.(type) { - case PacketPing: + switch pkt := packet.Sum.(type) { + case *tmp2p.Packet_PacketPing: // TODO: prevent abuse, as they cause flush()'s. // https://github.com/tendermint/tendermint/issues/1190 c.Logger.Debug("Receive Ping") @@ -609,23 +613,23 @@ FOR_LOOP: default: // never block } - case PacketPong: + case *tmp2p.Packet_PacketPong: c.Logger.Debug("Receive Pong") select { case c.pongTimeoutCh <- false: default: // never block } - case PacketMsg: - channel, ok := c.channelsIdx[pkt.ChannelID] + case *tmp2p.Packet_PacketMsg: + channel, ok := c.channelsIdx[byte(pkt.PacketMsg.ChannelID)] if !ok || channel == nil { - err := fmt.Errorf("unknown channel %X", pkt.ChannelID) + err := fmt.Errorf("unknown channel %X", pkt.PacketMsg.ChannelID) c.Logger.Error("Connection failed @ recvRoutine", "conn", c, "err", err) c.stopForError(err) break FOR_LOOP } - msgBytes, err := channel.recvPacketMsg(pkt) + msgBytes, err := channel.recvPacketMsg(*pkt.PacketMsg) if err != nil { if c.IsRunning() { c.Logger.Error("Connection failed @ recvRoutine", "conn", c, "err", err) @@ -634,9 +638,9 @@ FOR_LOOP: break FOR_LOOP } if msgBytes != nil { - c.Logger.Debug("Received bytes", "chID", pkt.ChannelID, "msgBytes", fmt.Sprintf("%X", msgBytes)) + c.Logger.Debug("Received bytes", "chID", pkt.PacketMsg.ChannelID, "msgBytes", fmt.Sprintf("%X", msgBytes)) // NOTE: This means the reactor.Receive runs in the same thread as the p2p recv routine - c.onReceive(pkt.ChannelID, msgBytes) + c.onReceive(byte(pkt.PacketMsg.ChannelID), msgBytes) } default: err := fmt.Errorf("unknown message type %v", reflect.TypeOf(packet)) @@ -661,14 +665,17 @@ func (c *MConnection) stopPongTimer() { } } -// maxPacketMsgSize returns a maximum size of PacketMsg, including the overhead -// of amino encoding. +// maxPacketMsgSize returns a maximum size of PacketMsg func (c *MConnection) maxPacketMsgSize() int { - return len(cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{ + bz, err := proto.Marshal(mustWrapPacket(&tmp2p.PacketMsg{ ChannelID: 0x01, EOF: 1, - Bytes: make([]byte, c.config.MaxPacketMsgPayloadSize), - })) + 10 // leave room for changes in amino + Data: make([]byte, c.config.MaxPacketMsgPayloadSize), + })) + if err != nil { + panic(err) + } + return len(bz) } type ConnectionStatus struct { @@ -814,17 +821,16 @@ func (ch *Channel) isSendPending() bool { // Creates a new PacketMsg to send. // Not goroutine-safe -func (ch *Channel) nextPacketMsg() PacketMsg { - packet := PacketMsg{} - packet.ChannelID = ch.desc.ID +func (ch *Channel) nextPacketMsg() tmp2p.PacketMsg { + packet := tmp2p.PacketMsg{ChannelID: int32(ch.desc.ID)} maxSize := ch.maxPacketMsgPayloadSize - packet.Bytes = ch.sending[:tmmath.MinInt(maxSize, len(ch.sending))] + packet.Data = ch.sending[:tmmath.MinInt(maxSize, len(ch.sending))] if len(ch.sending) <= maxSize { - packet.EOF = byte(0x01) + packet.EOF = 0x01 ch.sending = nil atomic.AddInt32(&ch.sendQueueSize, -1) // decrement sendQueueSize } else { - packet.EOF = byte(0x00) + packet.EOF = 0x00 ch.sending = ch.sending[tmmath.MinInt(maxSize, len(ch.sending)):] } return packet @@ -832,24 +838,24 @@ func (ch *Channel) nextPacketMsg() PacketMsg { // Writes next PacketMsg to w and updates c.recentlySent. // Not goroutine-safe -func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) { - var packet = ch.nextPacketMsg() - n, err = cdc.MarshalBinaryLengthPrefixedWriter(w, packet) - atomic.AddInt64(&ch.recentlySent, n) +func (ch *Channel) writePacketMsgTo(w io.Writer) (n int, err error) { + packet := ch.nextPacketMsg() + n, err = protoio.NewDelimitedWriter(w).WriteMsg(mustWrapPacket(&packet)) + atomic.AddInt64(&ch.recentlySent, int64(n)) return } // Handles incoming PacketMsgs. It returns a message bytes if message is // complete. NOTE message bytes may change on next call to recvPacketMsg. // Not goroutine-safe -func (ch *Channel) recvPacketMsg(packet PacketMsg) ([]byte, error) { +func (ch *Channel) recvPacketMsg(packet tmp2p.PacketMsg) ([]byte, error) { ch.Logger.Debug("Read PacketMsg", "conn", ch.conn, "packet", packet) - var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Bytes) + var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Data) if recvCap < recvReceived { return nil, fmt.Errorf("received message exceeds available capacity: %v < %v", recvCap, recvReceived) } - ch.recving = append(ch.recving, packet.Bytes...) - if packet.EOF == byte(0x01) { + ch.recving = append(ch.recving, packet.Data...) + if packet.EOF == 0x01 { msgBytes := ch.recving // clear the slice without re-allocating. @@ -873,33 +879,34 @@ func (ch *Channel) updateStats() { //---------------------------------------- // Packet -type Packet interface { - AssertIsPacket() -} +// mustWrapPacket takes a packet kind (oneof) and wraps it in a tmp2p.Packet message. +func mustWrapPacket(pb proto.Message) *tmp2p.Packet { + var msg tmp2p.Packet -func RegisterPacket(cdc *amino.Codec) { - cdc.RegisterInterface((*Packet)(nil), nil) - cdc.RegisterConcrete(PacketPing{}, "tendermint/p2p/PacketPing", nil) - cdc.RegisterConcrete(PacketPong{}, "tendermint/p2p/PacketPong", nil) - cdc.RegisterConcrete(PacketMsg{}, "tendermint/p2p/PacketMsg", nil) -} + switch pb := pb.(type) { + case *tmp2p.Packet: // already a packet + msg = *pb + case *tmp2p.PacketPing: + msg = tmp2p.Packet{ + Sum: &tmp2p.Packet_PacketPing{ + PacketPing: pb, + }, + } + case *tmp2p.PacketPong: + msg = tmp2p.Packet{ + Sum: &tmp2p.Packet_PacketPong{ + PacketPong: pb, + }, + } + case *tmp2p.PacketMsg: + msg = tmp2p.Packet{ + Sum: &tmp2p.Packet_PacketMsg{ + PacketMsg: pb, + }, + } + default: + panic(fmt.Errorf("unknown packet type %T", pb)) + } -func (PacketPing) AssertIsPacket() {} -func (PacketPong) AssertIsPacket() {} -func (PacketMsg) AssertIsPacket() {} - -type PacketPing struct { -} - -type PacketPong struct { -} - -type PacketMsg struct { - ChannelID byte - EOF byte // 1 means message ends here. - Bytes []byte -} - -func (mp PacketMsg) String() string { - return fmt.Sprintf("PacketMsg{%X:%X T:%X}", mp.ChannelID, mp.Bytes, mp.EOF) + return &msg } diff --git a/p2p/conn/connection_test.go b/p2p/conn/connection_test.go index 29d29fc6e..f5fe45bde 100644 --- a/p2p/conn/connection_test.go +++ b/p2p/conn/connection_test.go @@ -1,7 +1,6 @@ package conn import ( - "bytes" "net" "testing" "time" @@ -10,9 +9,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - amino "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/protoio" + tmp2p "github.com/tendermint/tendermint/proto/p2p" + "github.com/tendermint/tendermint/proto/types" ) const maxPingPongPacketSize = 1024 // bytes @@ -54,12 +54,12 @@ func TestMConnectionSendFlushStop(t *testing.T) { msg := []byte("abc") assert.True(t, clientConn.Send(0x01, msg)) - aminoMsgLength := 14 + msgLength := 14 // start the reader in a new routine, so we can flush errCh := make(chan error) go func() { - msgB := make([]byte, aminoMsgLength) + msgB := make([]byte, msgLength) _, err := server.Read(msgB) if err != nil { t.Error(err) @@ -182,9 +182,9 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { serverGotPing := make(chan struct{}) go func() { // read ping - var pkt PacketPing - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - assert.Nil(t, err) + var pkt tmp2p.Packet + err := protoio.NewDelimitedReader(server, maxPingPongPacketSize).ReadMsg(&pkt) + require.NoError(t, err) serverGotPing <- struct{}{} }() <-serverGotPing @@ -219,26 +219,28 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { defer mconn.Stop() // sending 3 pongs in a row (abuse) - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) + protoWriter := protoio.NewDelimitedWriter(server) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) serverGotPing := make(chan struct{}) go func() { // read ping (one byte) - var ( - packet Packet - err error - ) - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &packet, maxPingPongPacketSize) - require.Nil(t, err) + var packet tmp2p.Packet + err := protoio.NewDelimitedReader(server, maxPingPongPacketSize).ReadMsg(&packet) + require.NoError(t, err) serverGotPing <- struct{}{} + // respond with pong - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) }() <-serverGotPing @@ -273,19 +275,27 @@ func TestMConnectionMultiplePings(t *testing.T) { // sending 3 pings in a row (abuse) // see https://github.com/tendermint/tendermint/issues/1190 - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) - require.Nil(t, err) - var pkt PacketPong - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) - require.Nil(t, err) - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - require.Nil(t, err) - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{})) - require.Nil(t, err) - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - require.Nil(t, err) + protoReader := protoio.NewDelimitedReader(server, maxPingPongPacketSize) + protoWriter := protoio.NewDelimitedWriter(server) + var pkt tmp2p.Packet + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPing{})) + require.NoError(t, err) + + err = protoReader.ReadMsg(&pkt) + require.NoError(t, err) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPing{})) + require.NoError(t, err) + + err = protoReader.ReadMsg(&pkt) + require.NoError(t, err) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPing{})) + require.NoError(t, err) + + err = protoReader.ReadMsg(&pkt) + require.NoError(t, err) assert.True(t, mconn.IsRunning()) } @@ -314,25 +324,32 @@ func TestMConnectionPingPongs(t *testing.T) { serverGotPing := make(chan struct{}) go func() { + protoReader := protoio.NewDelimitedReader(server, maxPingPongPacketSize) + protoWriter := protoio.NewDelimitedWriter(server) + var pkt tmp2p.PacketPing + // read ping - var pkt PacketPing - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - require.Nil(t, err) + err = protoReader.ReadMsg(&pkt) + require.NoError(t, err) serverGotPing <- struct{}{} + // respond with pong - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) time.Sleep(mconn.config.PingInterval) // read ping - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize) - require.Nil(t, err) + err = protoReader.ReadMsg(&pkt) + require.NoError(t, err) + serverGotPing <- struct{}{} + // respond with pong - _, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{})) - require.Nil(t, err) + _, err = protoWriter.WriteMsg(mustWrapPacket(&tmp2p.PacketPong{})) + require.NoError(t, err) }() <-serverGotPing + <-serverGotPing pongTimerExpired := (mconn.config.PongTimeout + 20*time.Millisecond) * 2 select { @@ -425,13 +442,9 @@ func TestMConnectionReadErrorBadEncoding(t *testing.T) { client := mconnClient.conn - // send badly encoded msgPacket - bz := cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{}) - bz[4] += 0x01 // Invalid prefix bytes. - // Write it. - _, err := client.Write(bz) - assert.Nil(t, err) + _, err := client.Write([]byte{1, 2, 3, 4, 5}) + require.NoError(t, err) assert.True(t, expectSend(chOnErr), "badly encoded msgPacket") } @@ -465,32 +478,28 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { } client := mconnClient.conn + protoWriter := protoio.NewDelimitedWriter(client) // send msg thats just right - var err error - var buf = new(bytes.Buffer) - var packet = PacketMsg{ + var packet = tmp2p.PacketMsg{ ChannelID: 0x01, EOF: 1, - Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize), + Data: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize), } - _, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet) - assert.Nil(t, err) - _, err = client.Write(buf.Bytes()) - assert.Nil(t, err) + + _, err := protoWriter.WriteMsg(mustWrapPacket(&packet)) + require.NoError(t, err) assert.True(t, expectSend(chOnRcv), "msg just right") // send msg thats too long - buf = new(bytes.Buffer) - packet = PacketMsg{ + packet = tmp2p.PacketMsg{ ChannelID: 0x01, EOF: 1, - Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+100), + Data: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+100), } - _, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet) - assert.Nil(t, err) - _, err = client.Write(buf.Bytes()) - assert.NotNil(t, err) + + _, err = protoWriter.WriteMsg(mustWrapPacket(&packet)) + require.Error(t, err) assert.True(t, expectSend(chOnErr), "msg too long") } @@ -501,10 +510,8 @@ func TestMConnectionReadErrorUnknownMsgType(t *testing.T) { defer mconnServer.Stop() // send msg with unknown msg type - err := amino.EncodeUvarint(mconnClient.conn, 4) - assert.Nil(t, err) - _, err = mconnClient.conn.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF}) - assert.Nil(t, err) + _, err := protoio.NewDelimitedWriter(mconnClient.conn).WriteMsg(&types.Header{ChainID: "x"}) + require.NoError(t, err) assert.True(t, expectSend(chOnErr), "unknown msg type") } diff --git a/p2p/conn/evil_secret_connection_test.go b/p2p/conn/evil_secret_connection_test.go index 1f662ee2a..993b07f5a 100644 --- a/p2p/conn/evil_secret_connection_test.go +++ b/p2p/conn/evil_secret_connection_test.go @@ -6,12 +6,16 @@ import ( "io" "testing" + gogotypes "github.com/gogo/protobuf/types" "github.com/gtank/merlin" "github.com/stretchr/testify/assert" "golang.org/x/crypto/chacha20poly1305" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" + "github.com/tendermint/tendermint/libs/protoio" + tmp2p "github.com/tendermint/tendermint/proto/p2p" ) type buffer struct { @@ -80,14 +84,15 @@ func (c *evilConn) Read(data []byte) (n int, err error) { switch c.readStep { case 0: if !c.badEphKey { - bz, err := cdc.MarshalBinaryLengthPrefixed(c.locEphPub) + lc := *c.locEphPub + bz, err := protoio.MarshalDelimited(&gogotypes.BytesValue{Value: lc[:]}) if err != nil { panic(err) } copy(data, bz[c.readOffset:]) n = len(data) } else { - bz, err := cdc.MarshalBinaryLengthPrefixed([]byte("drop users;")) + bz, err := protoio.MarshalDelimited(&gogotypes.BytesValue{Value: []byte("drop users;")}) if err != nil { panic(err) } @@ -108,7 +113,11 @@ func (c *evilConn) Read(data []byte) (n int, err error) { case 1: signature := c.signChallenge() if !c.badAuthSignature { - bz, err := cdc.MarshalBinaryLengthPrefixed(authSigMessage{c.privKey.PubKey(), signature}) + pkpb, err := cryptoenc.PubKeyToProto(c.privKey.PubKey()) + if err != nil { + panic(err) + } + bz, err := protoio.MarshalDelimited(&tmp2p.AuthSigMessage{PubKey: pkpb, Sig: signature}) if err != nil { panic(err) } @@ -121,7 +130,7 @@ func (c *evilConn) Read(data []byte) (n int, err error) { } copy(data, c.buffer.Bytes()[c.readOffset:]) } else { - bz, err := cdc.MarshalBinaryLengthPrefixed([]byte("select * from users;")) + bz, err := protoio.MarshalDelimited(&gogotypes.BytesValue{Value: []byte("select * from users;")}) if err != nil { panic(err) } @@ -144,10 +153,16 @@ func (c *evilConn) Read(data []byte) (n int, err error) { func (c *evilConn) Write(data []byte) (n int, err error) { switch c.writeStep { case 0: - err := cdc.UnmarshalBinaryLengthPrefixed(data, c.remEphPub) + var ( + bytes gogotypes.BytesValue + remEphPub [32]byte + ) + err := protoio.UnmarshalDelimited(data, &bytes) if err != nil { panic(err) } + copy(remEphPub[:], bytes.Value) + c.remEphPub = &remEphPub c.writeStep = 1 if !c.shareAuthSignature { c.writeStep = 2 @@ -235,7 +250,7 @@ func TestMakeSecretConnection(t *testing.T) { errMsg string }{ {"refuse to share ethimeral key", newEvilConn(false, false, false, false), "EOF"}, - {"share bad ethimeral key", newEvilConn(true, true, false, false), "Insufficient bytes to decode"}, + {"share bad ethimeral key", newEvilConn(true, true, false, false), "wrong wireType"}, {"refuse to share auth signature", newEvilConn(true, false, false, false), "EOF"}, {"share bad auth signature", newEvilConn(true, false, true, true), "failed to decrypt SecretConnection"}, {"all good", newEvilConn(true, false, true, false), ""}, diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 5d48fa1c6..4d3ea3491 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -14,6 +14,7 @@ import ( "sync" "time" + gogotypes "github.com/gogo/protobuf/types" "github.com/gtank/merlin" pool "github.com/libp2p/go-buffer-pool" "golang.org/x/crypto/chacha20poly1305" @@ -23,7 +24,10 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/async" + "github.com/tendermint/tendermint/libs/protoio" + tmp2p "github.com/tendermint/tendermint/proto/p2p" ) // 4 + 1024 == 1028 total frame size @@ -250,7 +254,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) { defer pool.Put(frame) _, err = sc.recvAead.Open(frame[:0], sc.recvNonce[:], sealedFrame, nil) if err != nil { - return n, errors.New("failed to decrypt SecretConnection") + return n, fmt.Errorf("failed to decrypt SecretConnection: %w", err) } incrNonce(sc.recvNonce) // end decryption @@ -300,18 +304,22 @@ func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byt // Send our pubkey and receive theirs in tandem. var trs, _ = async.Parallel( func(_ int) (val interface{}, abort bool, err error) { - var _, err1 = cdc.MarshalBinaryLengthPrefixedWriter(conn, locEphPub) - if err1 != nil { - return nil, true, err1 // abort + lc := *locEphPub + _, err = protoio.NewDelimitedWriter(conn).WriteMsg(&gogotypes.BytesValue{Value: lc[:]}) + if err != nil { + return nil, true, err // abort } return nil, false, nil }, func(_ int) (val interface{}, abort bool, err error) { - var _remEphPub [32]byte - var _, err2 = cdc.UnmarshalBinaryLengthPrefixedReader(conn, &_remEphPub, 1024*1024) // TODO - if err2 != nil { - return nil, true, err2 // abort + var bytes gogotypes.BytesValue + err = protoio.NewDelimitedReader(conn, 1024*1024).ReadMsg(&bytes) + if err != nil { + return nil, true, err // abort } + + var _remEphPub [32]byte + copy(_remEphPub[:], bytes.Value) return _remEphPub, false, nil }, ) @@ -399,17 +407,31 @@ func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature []byte // Send our info and receive theirs in tandem. var trs, _ = async.Parallel( func(_ int) (val interface{}, abort bool, err error) { - var _, err1 = cdc.MarshalBinaryLengthPrefixedWriter(sc, authSigMessage{pubKey, signature}) - if err1 != nil { - return nil, true, err1 // abort + pbpk, err := cryptoenc.PubKeyToProto(pubKey) + if err != nil { + return nil, true, err + } + _, err = protoio.NewDelimitedWriter(sc).WriteMsg(&tmp2p.AuthSigMessage{PubKey: pbpk, Sig: signature}) + if err != nil { + return nil, true, err // abort } return nil, false, nil }, func(_ int) (val interface{}, abort bool, err error) { - var _recvMsg authSigMessage - var _, err2 = cdc.UnmarshalBinaryLengthPrefixedReader(sc, &_recvMsg, 1024*1024) // TODO - if err2 != nil { - return nil, true, err2 // abort + var pba tmp2p.AuthSigMessage + err = protoio.NewDelimitedReader(sc, 1024*1024).ReadMsg(&pba) + if err != nil { + return nil, true, err // abort + } + + pk, err := cryptoenc.PubKeyFromProto(pba.PubKey) + if err != nil { + return nil, true, err // abort + } + + _recvMsg := authSigMessage{ + Key: pk, + Sig: pba.Sig, } return _recvMsg, false, nil }, diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 0edf2e243..9ded86a15 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -257,38 +257,30 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) { func TestNilPubkey(t *testing.T) { var fooConn, barConn = makeKVStoreConnPair() + defer fooConn.Close() + defer barConn.Close() var fooPrvKey = ed25519.GenPrivKey() var barPrvKey = privKeyWithNilPubKey{ed25519.GenPrivKey()} - go func() { - _, err := MakeSecretConnection(barConn, barPrvKey) - assert.NoError(t, err) - }() + go MakeSecretConnection(fooConn, fooPrvKey) - assert.NotPanics(t, func() { - _, err := MakeSecretConnection(fooConn, fooPrvKey) - if assert.Error(t, err) { - assert.Equal(t, "expected ed25519 pubkey, got ", err.Error()) - } - }) + _, err := MakeSecretConnection(barConn, barPrvKey) + require.Error(t, err) + assert.Equal(t, "toproto: key type is not supported", err.Error()) } func TestNonEd25519Pubkey(t *testing.T) { var fooConn, barConn = makeKVStoreConnPair() + defer fooConn.Close() + defer barConn.Close() var fooPrvKey = ed25519.GenPrivKey() var barPrvKey = secp256k1.GenPrivKey() - go func() { - _, err := MakeSecretConnection(barConn, barPrvKey) - assert.NoError(t, err) - }() + go MakeSecretConnection(fooConn, fooPrvKey) - assert.NotPanics(t, func() { - _, err := MakeSecretConnection(fooConn, fooPrvKey) - if assert.Error(t, err) { - assert.Equal(t, "expected ed25519 pubkey, got secp256k1.PubKey", err.Error()) - } - }) + _, err := MakeSecretConnection(barConn, barPrvKey) + require.Error(t, err) + assert.Contains(t, err.Error(), "is not supported") } func writeLots(t *testing.T, wg *sync.WaitGroup, conn io.Writer, txt string, n int) { diff --git a/proto/p2p/conn_msgs.pb.go b/proto/p2p/conn_msgs.pb.go index bd0ab6358..86afe9dc7 100644 --- a/proto/p2p/conn_msgs.pb.go +++ b/proto/p2p/conn_msgs.pb.go @@ -7,6 +7,7 @@ import ( fmt "fmt" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" + keys "github.com/tendermint/tendermint/proto/crypto/keys" io "io" math "math" math_bits "math/bits" @@ -253,38 +254,96 @@ func (*Packet) XXX_OneofWrappers() []interface{} { } } +type AuthSigMessage struct { + PubKey keys.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Sig []byte `protobuf:"bytes,2,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (m *AuthSigMessage) Reset() { *m = AuthSigMessage{} } +func (m *AuthSigMessage) String() string { return proto.CompactTextString(m) } +func (*AuthSigMessage) ProtoMessage() {} +func (*AuthSigMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_8c680f0b24d73fe7, []int{4} +} +func (m *AuthSigMessage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AuthSigMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AuthSigMessage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AuthSigMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_AuthSigMessage.Merge(m, src) +} +func (m *AuthSigMessage) XXX_Size() int { + return m.Size() +} +func (m *AuthSigMessage) XXX_DiscardUnknown() { + xxx_messageInfo_AuthSigMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_AuthSigMessage proto.InternalMessageInfo + +func (m *AuthSigMessage) GetPubKey() keys.PublicKey { + if m != nil { + return m.PubKey + } + return keys.PublicKey{} +} + +func (m *AuthSigMessage) GetSig() []byte { + if m != nil { + return m.Sig + } + return nil +} + func init() { proto.RegisterType((*PacketPing)(nil), "tendermint.proto.p2p.PacketPing") proto.RegisterType((*PacketPong)(nil), "tendermint.proto.p2p.PacketPong") proto.RegisterType((*PacketMsg)(nil), "tendermint.proto.p2p.PacketMsg") proto.RegisterType((*Packet)(nil), "tendermint.proto.p2p.Packet") + proto.RegisterType((*AuthSigMessage)(nil), "tendermint.proto.p2p.AuthSigMessage") } func init() { proto.RegisterFile("proto/p2p/conn_msgs.proto", fileDescriptor_8c680f0b24d73fe7) } var fileDescriptor_8c680f0b24d73fe7 = []byte{ - // 324 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0x41, 0x4b, 0xfb, 0x30, - 0x18, 0xc6, 0x9b, 0x7f, 0xff, 0x9b, 0xf4, 0xdd, 0xbc, 0x04, 0x0f, 0x9b, 0x87, 0x6c, 0xec, 0x20, - 0x43, 0xa4, 0x85, 0xfa, 0x05, 0x64, 0x9b, 0xe2, 0x0e, 0xc3, 0xd1, 0xa3, 0x97, 0xd2, 0xb5, 0x35, - 0x0d, 0xda, 0x24, 0xb4, 0xd9, 0xc1, 0x6f, 0xe1, 0xc7, 0xf2, 0xb8, 0xa3, 0x20, 0x0c, 0xe9, 0xbe, - 0x88, 0x2c, 0x99, 0x5b, 0x05, 0xd1, 0xdb, 0xf3, 0x3c, 0xbc, 0xf9, 0xbd, 0x4f, 0x12, 0xe8, 0xca, - 0x42, 0x28, 0xe1, 0x49, 0x5f, 0x7a, 0xb1, 0xe0, 0x3c, 0xcc, 0x4b, 0x5a, 0xba, 0x3a, 0xc3, 0x27, - 0x2a, 0xe5, 0x49, 0x5a, 0xe4, 0x8c, 0x2b, 0x93, 0xb8, 0xd2, 0x97, 0xa7, 0x67, 0x2a, 0x63, 0x45, - 0x12, 0xca, 0xa8, 0x50, 0xcf, 0x9e, 0x39, 0x4c, 0x05, 0x15, 0x07, 0x65, 0x66, 0x07, 0x6d, 0x80, - 0x79, 0x14, 0x3f, 0xa6, 0x6a, 0xce, 0x38, 0xad, 0x39, 0xc1, 0xe9, 0x20, 0x03, 0xc7, 0xb8, 0x59, - 0x49, 0xf1, 0x05, 0x40, 0x9c, 0x45, 0x9c, 0xa7, 0x4f, 0x21, 0x4b, 0x3a, 0xa8, 0x8f, 0x86, 0x8d, - 0xd1, 0x71, 0xb5, 0xee, 0x39, 0x63, 0x93, 0x4e, 0x27, 0x81, 0xb3, 0x1b, 0x98, 0x26, 0xb8, 0x0b, - 0x76, 0x2a, 0x1e, 0x3a, 0xff, 0xf4, 0xd8, 0x51, 0xb5, 0xee, 0xd9, 0xd7, 0x77, 0x37, 0xc1, 0x36, - 0xc3, 0x18, 0xfe, 0x27, 0x91, 0x8a, 0x3a, 0x76, 0x1f, 0x0d, 0xdb, 0x81, 0xd6, 0x83, 0x77, 0x04, - 0x4d, 0xb3, 0x0a, 0x8f, 0xa1, 0x25, 0xb5, 0x0a, 0x25, 0xe3, 0x54, 0x2f, 0x6a, 0xf9, 0x7d, 0xf7, - 0xa7, 0x4b, 0xba, 0x87, 0xe6, 0xb7, 0x56, 0x00, 0x72, 0xef, 0xea, 0x10, 0xc1, 0xa9, 0xae, 0xf1, - 0x17, 0x44, 0x7c, 0x83, 0x08, 0x4e, 0xf1, 0x15, 0xec, 0xdc, 0xf6, 0xb5, 0x75, 0xdd, 0x96, 0xdf, - 0xfb, 0x8d, 0x31, 0x2b, 0xb7, 0x08, 0x47, 0x7e, 0x99, 0x51, 0x03, 0xec, 0x72, 0x99, 0x8f, 0x26, - 0xaf, 0x15, 0x41, 0xab, 0x8a, 0xa0, 0x8f, 0x8a, 0xa0, 0x97, 0x0d, 0xb1, 0x56, 0x1b, 0x62, 0xbd, - 0x6d, 0x88, 0x75, 0x7f, 0x4e, 0x99, 0xca, 0x96, 0x0b, 0x37, 0x16, 0xb9, 0x77, 0x00, 0xd7, 0xe5, - 0xfe, 0xdf, 0x17, 0x4d, 0x2d, 0x2f, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xad, 0x8c, 0xf9, 0x97, - 0x0b, 0x02, 0x00, 0x00, + // 409 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xdf, 0x6a, 0xd4, 0x40, + 0x14, 0xc6, 0x13, 0xd3, 0x6e, 0xd9, 0xb3, 0xab, 0xc8, 0xe0, 0xc5, 0xb6, 0x60, 0x76, 0xc9, 0x85, + 0x16, 0x91, 0x04, 0xe2, 0x0b, 0x68, 0x5a, 0x8b, 0xa5, 0x2c, 0x2e, 0xf1, 0xce, 0x9b, 0x90, 0x3f, + 0xe3, 0x64, 0xdc, 0x66, 0x66, 0xc8, 0x4c, 0x2e, 0xf2, 0x16, 0x3e, 0x56, 0x2f, 0x7b, 0x29, 0x08, + 0x8b, 0x64, 0x5f, 0x44, 0x32, 0x13, 0x77, 0x57, 0x14, 0x7b, 0xf7, 0x7d, 0x1f, 0x27, 0xbf, 0x73, + 0x4e, 0xce, 0xc0, 0xa9, 0xa8, 0xb9, 0xe2, 0x81, 0x08, 0x45, 0x90, 0x73, 0xc6, 0x92, 0x4a, 0x12, + 0xe9, 0xeb, 0x0c, 0x3d, 0x53, 0x98, 0x15, 0xb8, 0xae, 0x28, 0x53, 0x26, 0xf1, 0x45, 0x28, 0xce, + 0x5e, 0xa8, 0x92, 0xd6, 0x45, 0x22, 0xd2, 0x5a, 0xb5, 0x81, 0xf9, 0x98, 0x70, 0xc2, 0xf7, 0xca, + 0xd4, 0x9e, 0x3d, 0x37, 0x49, 0x5e, 0xb7, 0x42, 0xf1, 0x60, 0x8d, 0x5b, 0x19, 0xa8, 0x56, 0xe0, + 0x01, 0xee, 0x4d, 0x01, 0x56, 0x69, 0xbe, 0xc6, 0x6a, 0x45, 0x19, 0x39, 0x70, 0x9c, 0x11, 0xaf, + 0x84, 0xb1, 0x71, 0x4b, 0x49, 0xd0, 0x6b, 0x80, 0xbc, 0x4c, 0x19, 0xc3, 0xb7, 0x09, 0x2d, 0x66, + 0xf6, 0xc2, 0x3e, 0x3f, 0x8e, 0x1e, 0x77, 0x9b, 0xf9, 0xf8, 0xc2, 0xa4, 0xd7, 0x97, 0xf1, 0x78, + 0x28, 0xb8, 0x2e, 0xd0, 0x29, 0x38, 0x98, 0x7f, 0x99, 0x3d, 0xd2, 0x65, 0x27, 0xdd, 0x66, 0xee, + 0xbc, 0xff, 0x78, 0x15, 0xf7, 0x19, 0x42, 0x70, 0x54, 0xa4, 0x2a, 0x9d, 0x39, 0x0b, 0xfb, 0x7c, + 0x1a, 0x6b, 0xed, 0xfd, 0xb0, 0x61, 0x64, 0x5a, 0xa1, 0x0b, 0x98, 0x08, 0xad, 0x12, 0x41, 0x19, + 0xd1, 0x8d, 0x26, 0xe1, 0xc2, 0xff, 0xd7, 0x3f, 0xf0, 0xf7, 0x93, 0x7f, 0xb0, 0x62, 0x10, 0x3b, + 0x77, 0x08, 0xe1, 0x8c, 0xe8, 0x31, 0x1e, 0x82, 0xf0, 0x3f, 0x20, 0x9c, 0x11, 0xf4, 0x16, 0x06, + 0xd7, 0x1f, 0x43, 0x8f, 0x3b, 0x09, 0xe7, 0xff, 0x63, 0x2c, 0x65, 0x8f, 0x18, 0x8b, 0xdf, 0x26, + 0x3a, 0x06, 0x47, 0x36, 0x95, 0xf7, 0x15, 0x9e, 0xbc, 0x6b, 0x54, 0xf9, 0x89, 0x92, 0x25, 0x96, + 0x32, 0x25, 0x18, 0x5d, 0xc1, 0x89, 0x68, 0xb2, 0x64, 0x8d, 0xdb, 0x61, 0xc1, 0x97, 0x7f, 0x73, + 0xcd, 0xc5, 0xfc, 0xfe, 0x62, 0xfe, 0xaa, 0xc9, 0x6e, 0x69, 0x7e, 0x83, 0xdb, 0xe8, 0xe8, 0x6e, + 0x33, 0xb7, 0xe2, 0x91, 0x68, 0xb2, 0x1b, 0xdc, 0xa2, 0xa7, 0xe0, 0x48, 0x6a, 0xf6, 0x9b, 0xc6, + 0xbd, 0x8c, 0x2e, 0xef, 0x3a, 0xd7, 0xbe, 0xef, 0x5c, 0xfb, 0x67, 0xe7, 0xda, 0xdf, 0xb6, 0xae, + 0x75, 0xbf, 0x75, 0xad, 0xef, 0x5b, 0xd7, 0xfa, 0xfc, 0x8a, 0x50, 0x55, 0x36, 0x99, 0x9f, 0xf3, + 0x2a, 0xd8, 0x37, 0x3b, 0x94, 0xbb, 0x27, 0x98, 0x8d, 0xb4, 0x7c, 0xf3, 0x2b, 0x00, 0x00, 0xff, + 0xff, 0xd2, 0xaa, 0xb3, 0xc0, 0x96, 0x02, 0x00, 0x00, } func (m *PacketPing) Marshal() (dAtA []byte, err error) { @@ -468,6 +527,46 @@ func (m *Packet_PacketMsg) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *AuthSigMessage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AuthSigMessage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AuthSigMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Sig) > 0 { + i -= len(m.Sig) + copy(dAtA[i:], m.Sig) + i = encodeVarintConnMsgs(dAtA, i, uint64(len(m.Sig))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintConnMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintConnMsgs(dAtA []byte, offset int, v uint64) int { offset -= sovConnMsgs(v) base := offset @@ -564,6 +663,20 @@ func (m *Packet_PacketMsg) Size() (n int) { } return n } +func (m *AuthSigMessage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PubKey.Size() + n += 1 + l + sovConnMsgs(uint64(l)) + l = len(m.Sig) + if l > 0 { + n += 1 + l + sovConnMsgs(uint64(l)) + } + return n +} func sovConnMsgs(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -960,6 +1073,126 @@ func (m *Packet) Unmarshal(dAtA []byte) error { } return nil } +func (m *AuthSigMessage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AuthSigMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AuthSigMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthConnMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthConnMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sig", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConnMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthConnMsgs + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthConnMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sig = append(m.Sig[:0], dAtA[iNdEx:postIndex]...) + if m.Sig == nil { + m.Sig = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipConnMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthConnMsgs + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthConnMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipConnMsgs(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/proto/p2p/conn_msgs.proto b/proto/p2p/conn_msgs.proto index 6c362d7ad..c501ca4f0 100644 --- a/proto/p2p/conn_msgs.proto +++ b/proto/p2p/conn_msgs.proto @@ -4,6 +4,7 @@ package tendermint.proto.p2p; option go_package = "github.com/tendermint/tendermint/proto/p2p"; import "third_party/proto/gogoproto/gogo.proto"; +import "proto/crypto/keys/types.proto"; message PacketPing {} @@ -22,3 +23,8 @@ message Packet { PacketMsg packet_msg = 3; } } + +message AuthSigMessage { + tendermint.proto.crypto.keys.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + bytes sig = 2; +} From 65909a13d59896acbaa4f773f94ff84e4354b106 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 10 Jun 2020 11:13:38 +0400 Subject: [PATCH 03/12] consensus: stricter on LastCommitRound check (#4970) LastCommitRound should always be >= 0 for heights > 1. In State.updateToState, last precommit is computed only when round greater than -1 and has votes. But "LastCommit" is always updated regardless of the condition. If there's no last precommit, "LastCommit" is set to (*types.VoteSet)(nil). That's why "LastCommit" can be -1 for heights > 1. To fix it, only update State.RoundState.LastCommit when there is last precommit. Fixes #2737 Co-authored-by: Cuong Manh Le --- CHANGELOG_PENDING.md | 1 + consensus/reactor.go | 13 +++++++++---- consensus/reactor_test.go | 12 ++++++------ consensus/state.go | 33 ++++++++++++++++++++++++--------- consensus/types/round_state.go | 2 +- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index de693aa06..c1b3faa28 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -94,4 +94,5 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi ### BUG FIXES: - [consensus] [\#4895](https://github.com/tendermint/tendermint/pull/4895) Cache the address of the validator to reduce querying a remote KMS (@joe-bowman) +- [consensus] \#4970 Stricter on `LastCommitRound` check (@cuonglm) - [blockchain/v2] Correctly set block store base in status responses (@erikgrinaker) diff --git a/consensus/reactor.go b/consensus/reactor.go index 9faea561f..b427dcec6 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -101,9 +101,14 @@ func (conR *Reactor) OnStop() { // It resets the state, turns off fast_sync, and starts the consensus state-machine func (conR *Reactor) SwitchToConsensus(state sm.State, skipWAL bool) { conR.Logger.Info("SwitchToConsensus") - conR.conS.reconstructLastCommit(state) - // NOTE: The line below causes broadcastNewRoundStepRoutine() to - // broadcast a NewRoundStepMessage. + + // We have no votes, so reconstruct LastCommit from SeenCommit. + if state.LastBlockHeight > 0 { + conR.conS.reconstructLastCommit(state) + } + + // NOTE: The line below causes broadcastNewRoundStepRoutine() to broadcast a + // NewRoundStepMessage. conR.conS.updateToState(state) conR.mtx.Lock() @@ -1438,7 +1443,7 @@ func (m *NewRoundStepMessage) ValidateBasic() error { // NOTE: SecondsSinceStartTime may be negative if (m.Height == 1 && m.LastCommitRound != -1) || - (m.Height > 1 && m.LastCommitRound < -1) { // TODO: #2737 LastCommitRound should always be >= 0 for heights > 1 + (m.Height > 1 && m.LastCommitRound < 0) { return errors.New("invalid LastCommitRound (for 1st block: -1, for others: >= 0)") } return nil diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index c57a6184c..adfdf4d8e 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -699,12 +699,12 @@ func TestNewRoundStepMessageValidateBasic(t *testing.T) { testName string messageStep cstypes.RoundStepType }{ - {false, 0, 0, 0, "Valid Message", 0x01}, - {true, -1, 0, 0, "Invalid Message", 0x01}, - {true, 0, 0, -1, "Invalid Message", 0x01}, - {true, 0, 0, 1, "Invalid Message", 0x00}, - {true, 0, 0, 1, "Invalid Message", 0x00}, - {true, 0, -2, 2, "Invalid Message", 0x01}, + {false, 0, 0, 0, "Valid Message", cstypes.RoundStepNewHeight}, + {true, -1, 0, 0, "Negative round", cstypes.RoundStepNewHeight}, + {true, 0, 0, -1, "Negative height", cstypes.RoundStepNewHeight}, + {true, 0, 0, 0, "Invalid Step", cstypes.RoundStepCommit + 1}, + {true, 0, 0, 1, "H == 1 but LCR != -1 ", cstypes.RoundStepNewHeight}, + {true, 0, -1, 2, "H > 1 but LCR < 0", cstypes.RoundStepNewHeight}, } for _, tc := range testCases { diff --git a/consensus/state.go b/consensus/state.go index 924ffbefa..7e8ce5d40 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -175,11 +175,16 @@ func NewState( cs.doPrevote = cs.defaultDoPrevote cs.setProposal = cs.defaultSetProposal + // We have no votes, so reconstruct LastCommit from SeenCommit. + if state.LastBlockHeight > 0 { + cs.reconstructLastCommit(state) + } + cs.updateToState(state) // Don't call scheduleRound0 yet. // We do that upon Start(). - cs.reconstructLastCommit(state) + cs.BaseService = *service.NewBaseService(nil, "State", cs) for _, option := range options { option(cs) @@ -517,18 +522,17 @@ func (cs *State) sendInternalMessage(mi msgInfo) { // Reconstruct LastCommit from SeenCommit, which we saved along with the block, // (which happens even before saving the state) func (cs *State) reconstructLastCommit(state sm.State) { - if state.LastBlockHeight == 0 { - return - } seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight) if seenCommit == nil { panic(fmt.Sprintf("Failed to reconstruct LastCommit: seen commit for height %v not found", state.LastBlockHeight)) } + lastPrecommits := types.CommitToVoteSet(state.ChainID, seenCommit, state.LastValidators) if !lastPrecommits.HasTwoThirdsMajority() { panic("Failed to reconstruct LastCommit: Does not have +2/3 maj") } + cs.LastCommit = lastPrecommits } @@ -564,12 +568,24 @@ func (cs *State) updateToState(state sm.State) { // Reset fields based on state. validators := state.Validators - lastPrecommits := (*types.VoteSet)(nil) - if cs.CommitRound > -1 && cs.Votes != nil { + + switch { + case state.LastBlockHeight == 0: // Very first commit should be empty. + cs.LastCommit = (*types.VoteSet)(nil) + case cs.CommitRound > -1 && cs.Votes != nil: // Otherwise, use cs.Votes if !cs.Votes.Precommits(cs.CommitRound).HasTwoThirdsMajority() { - panic("updateToState(state) called but last Precommit round didn't have +2/3") + panic(fmt.Sprintf("Wanted to form a Commit, but Precommits (H/R: %d/%d) didn't have 2/3+: %v", + state.LastBlockHeight, + cs.CommitRound, + cs.Votes.Precommits(cs.CommitRound))) } - lastPrecommits = cs.Votes.Precommits(cs.CommitRound) + cs.LastCommit = cs.Votes.Precommits(cs.CommitRound) + case cs.LastCommit == nil: + // NOTE: when Tendermint starts, it has no votes. reconstructLastCommit + // must be called to reconstruct LastCommit from SeenCommit. + panic(fmt.Sprintf("LastCommit cannot be empty in heights > 1 (H:%d)", + state.LastBlockHeight+1, + )) } // Next desired block height @@ -601,7 +617,6 @@ func (cs *State) updateToState(state sm.State) { cs.ValidBlockParts = nil cs.Votes = cstypes.NewHeightVoteSet(state.ChainID, height, validators) cs.CommitRound = -1 - cs.LastCommit = lastPrecommits cs.LastValidators = state.LastValidators cs.TriggeredTimeoutPrecommit = false diff --git a/consensus/types/round_state.go b/consensus/types/round_state.go index 5d2bc9ca5..6fd674f73 100644 --- a/consensus/types/round_state.go +++ b/consensus/types/round_state.go @@ -84,7 +84,7 @@ type RoundState struct { ValidRound int32 `json:"valid_round"` ValidBlock *types.Block `json:"valid_block"` // Last known block of POL mentioned above. - // Last known block parts of POL metnioned above. + // Last known block parts of POL mentioned above. ValidBlockParts *types.PartSet `json:"valid_block_parts"` Votes *HeightVoteSet `json:"votes"` CommitRound int32 `json:"commit_round"` // From 5697e144a72cb5f3d5183d19e5d97d6e4c9156c1 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 10 Jun 2020 13:53:55 +0200 Subject: [PATCH 04/12] evidence: adr56 form amnesia evidence (#4821) Creates Amnesia Evidence which is formed from Potential Amnesia Evidence with either a matching proof or after a period of time denoted as the Amnesia Trial Period. This also adds the code necessary so that Amnesia Evidence can be validated and committed on a block --- consensus/common_test.go | 42 ++ consensus/state_test.go | 19 +- evidence/pool.go | 180 +++++- evidence/pool_test.go | 170 +++++- proto/types/evidence.pb.go | 512 +++++++++++++++--- proto/types/evidence.proto | 12 +- proto/types/params.pb.go | 109 ++-- proto/types/params.proto | 5 + state/store_test.go | 4 +- state/validation.go | 31 +- state/validation_test.go | 283 +++++++++- .../internal/test_harness_test.go | 3 +- types/evidence.go | 319 +++++++++-- types/evidence_test.go | 166 ++++-- types/params.go | 19 +- types/params_test.go | 31 +- types/priv_validator.go | 9 + types/validator_set.go | 3 + types/vote_set_test.go | 17 +- 19 files changed, 1658 insertions(+), 276 deletions(-) diff --git a/consensus/common_test.go b/consensus/common_test.go index 3f9378acb..54ee847ea 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -25,6 +25,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" cstypes "github.com/tendermint/tendermint/consensus/types" + "github.com/tendermint/tendermint/evidence" tmbytes "github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" @@ -422,6 +423,47 @@ func randState(nValidators int) (*State, []*validatorStub) { return cs, vss } +func randStateWithEvpool(nValidators int) (*State, []*validatorStub, *evidence.Pool) { + state, privVals := randGenesisState(nValidators, false, 10) + + vss := make([]*validatorStub, nValidators) + + app := counter.NewApplication(true) + config := cfg.ResetTestRoot("consensus_state_test") + + blockStore := store.NewBlockStore(dbm.NewMemDB()) + evidenceDB := dbm.NewMemDB() + + mtx := new(sync.Mutex) + proxyAppConnMem := abcicli.NewLocalClient(mtx, app) + proxyAppConnCon := abcicli.NewLocalClient(mtx, app) + + mempool := mempl.NewCListMempool(config.Mempool, proxyAppConnMem, 0) + mempool.SetLogger(log.TestingLogger().With("module", "mempool")) + if config.Consensus.WaitForTxs() { + mempool.EnableTxsAvailable() + } + stateDB := dbm.NewMemDB() + evpool, _ := evidence.NewPool(stateDB, evidenceDB, blockStore) + blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool, evpool) + cs := NewState(config.Consensus, state, blockExec, blockStore, mempool, evpool) + cs.SetLogger(log.TestingLogger().With("module", "consensus")) + cs.SetPrivValidator(privVals[0]) + + eventBus := types.NewEventBus() + eventBus.SetLogger(log.TestingLogger().With("module", "events")) + eventBus.Start() + cs.SetEventBus(eventBus) + + for i := 0; i < nValidators; i++ { + vss[i] = newValidatorStub(privVals[i], int32(i)) + } + // since cs1 starts at 1 + incrementHeight(vss[1:]...) + + return cs, vss, evpool +} + //------------------------------------------------------------------------------- func ensureNoNewEvent(ch <-chan tmpubsub.Message, timeout time.Duration, diff --git a/consensus/state_test.go b/consensus/state_test.go index 739060e81..52d235190 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -616,7 +616,7 @@ func TestStateLockPOLRelockThenChangeLock(t *testing.T) { // 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka func TestStateLockPOLUnlock(t *testing.T) { - cs1, vss := randState(4) + cs1, vss, evpool := randStateWithEvpool(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -703,6 +703,16 @@ func TestStateLockPOLUnlock(t *testing.T) { signAddVotes(cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3) ensureNewRound(newRoundCh, height, round+1) + // polc should be in the evpool for round 1 + polc, err := evpool.RetrievePOLC(height, round) + assert.NoError(t, err) + assert.False(t, polc.IsAbsent()) + t.Log(polc.Address()) + // but not for round 0 + polc, err = evpool.RetrievePOLC(height, round-1) + assert.Error(t, err) + assert.True(t, polc.IsAbsent()) + } // 4 vals, v1 locks on proposed block in the first round but the other validators only prevote @@ -710,7 +720,7 @@ func TestStateLockPOLUnlock(t *testing.T) { // v1 should unlock and precommit nil. In the third round another block is proposed, all vals // prevote and now v1 can lock onto the third block and precommit that func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) { - cs1, vss := randState(4) + cs1, vss, evpool := randStateWithEvpool(4) vs2, vs3, vs4 := vss[1], vss[2], vss[3] height, round := cs1.Height, cs1.Round @@ -803,6 +813,11 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) { thirdPropBlockHash := propBlock.Hash() require.NotEqual(t, secondBlockHash, thirdPropBlockHash) + // polc should be in the evpool for round 1 + polc, err := evpool.RetrievePOLC(height, round) + assert.NoError(t, err) + assert.False(t, polc.IsAbsent()) + incrementRound(vs2, vs3, vs4) // timeout to new round diff --git a/evidence/pool.go b/evidence/pool.go index 35c8a0b05..4e2a4f53d 100644 --- a/evidence/pool.go +++ b/evidence/pool.go @@ -21,6 +21,7 @@ const ( baseKeyCommitted = byte(0x00) baseKeyPending = byte(0x01) baseKeyPOLC = byte(0x02) + baseKeyAwaiting = byte(0x03) ) // Pool maintains a pool of valid evidence to be broadcasted and committed @@ -43,6 +44,8 @@ type Pool struct { // currently is (ie. [MaxAgeNumBlocks, CurrentHeight]) // In simple words, it means it's still bonded -> therefore slashable. valToLastHeight valToLastHeightMap + + nextEvidenceTrialEndedHeight int64 } // Validator.Address -> Last height it was in validator set @@ -59,22 +62,19 @@ func NewPool(stateDB, evidenceDB dbm.DB, blockStore *store.BlockStore) (*Pool, e } pool := &Pool{ - stateDB: stateDB, - blockStore: blockStore, - state: state, - logger: log.NewNopLogger(), - evidenceStore: evidenceDB, - evidenceList: clist.New(), - valToLastHeight: valToLastHeight, + stateDB: stateDB, + blockStore: blockStore, + state: state, + logger: log.NewNopLogger(), + evidenceStore: evidenceDB, + evidenceList: clist.New(), + valToLastHeight: valToLastHeight, + nextEvidenceTrialEndedHeight: -1, } // if pending evidence already in db, in event of prior failure, then load it back to the evidenceList evList := pool.AllPendingEvidence() for _, ev := range evList { - if pool.IsEvidenceExpired(ev) { - pool.removePendingEvidence(ev) - continue - } pool.evidenceList.PushBack(ev) } @@ -84,6 +84,7 @@ func NewPool(stateDB, evidenceDB dbm.DB, blockStore *store.BlockStore) (*Pool, e // PendingEvidence is used primarily as part of block proposal and returns up to maxNum of uncommitted evidence. // If maxNum is -1, all evidence is returned. Pending evidence is prioritised based on time. func (evpool *Pool) PendingEvidence(maxNum uint32) []types.Evidence { + evpool.removeExpiredPendingEvidence() evidence, err := evpool.listEvidence(baseKeyPending, int64(maxNum)) if err != nil { evpool.logger.Error("Unable to retrieve pending evidence", "err", err) @@ -92,6 +93,7 @@ func (evpool *Pool) PendingEvidence(maxNum uint32) []types.Evidence { } func (evpool *Pool) AllPendingEvidence() []types.Evidence { + evpool.removeExpiredPendingEvidence() evidence, err := evpool.listEvidence(baseKeyPending, -1) if err != nil { evpool.logger.Error("Unable to retrieve pending evidence", "err", err) @@ -104,23 +106,24 @@ func (evpool *Pool) AllPendingEvidence() []types.Evidence { func (evpool *Pool) Update(block *types.Block, state sm.State) { // sanity check if state.LastBlockHeight != block.Height { - panic( - fmt.Sprintf("Failed EvidencePool.Update sanity check: got state.Height=%d with block.Height=%d", - state.LastBlockHeight, - block.Height, - ), + panic(fmt.Sprintf("Failed EvidencePool.Update sanity check: got state.Height=%d with block.Height=%d", + state.LastBlockHeight, + block.Height, + ), ) } // remove evidence from pending and mark committed - evpool.MarkEvidenceAsCommitted(block.Height, block.Time, block.Evidence.Evidence) + evpool.MarkEvidenceAsCommitted(block.Height, block.Evidence.Evidence) - // remove expired evidence - this should be done at every height to ensure we don't send expired evidence to peers - evpool.removeExpiredPendingEvidence() - - // as it's not vital to remove expired POLCs, we only prune periodically + // prune pending, committed and potential evidence and polc's periodically if block.Height%state.ConsensusParams.Evidence.MaxAgeNumBlocks == 0 { evpool.pruneExpiredPOLC() + evpool.removeExpiredPendingEvidence() + } + + if evpool.nextEvidenceTrialEndedHeight > 0 && block.Height < evpool.nextEvidenceTrialEndedHeight { + evpool.upgradePotentialAmnesiaEvidence() } // update the state @@ -202,9 +205,74 @@ func (evpool *Pool) AddEvidence(evidence types.Evidence) error { return fmt.Errorf("failed to verify %v: %w", ev, err) } + // For potential amnesia evidence, if this node is indicted it shall retrieve a polc + // to form AmensiaEvidence + if pe, ok := ev.(types.PotentialAmnesiaEvidence); ok { + var ( + height = pe.Height() + exists = false + polc types.ProofOfLockChange + ) + pe.HeightStamp = evpool.State().LastBlockHeight + + // a) first try to find a corresponding polc + for round := pe.VoteB.Round; round > pe.VoteA.Round; round-- { + polc, err = evpool.RetrievePOLC(height, round) + if err != nil { + evpool.logger.Error("Failed to retrieve polc for potential amnesia evidence", "err", err, "pae", pe.String()) + continue + } + if err == nil && !polc.IsAbsent() { + // we should not need to verify it if both the polc and potential amnesia evidence have already + // been verified. We replace the potential amnesia evidence. + ae := types.MakeAmnesiaEvidence(pe, polc) + err := evpool.AddEvidence(ae) + if err != nil { + evpool.logger.Error("Failed to create amnesia evidence from potential amnesia evidence", "err", err) + // revert back to processing potential amnesia evidence + exists = false + } else { + evpool.logger.Info("Formed amnesia evidence from own polc", "amnesiaEvidence", ae) + } + break + } + } + + // b) check if amnesia evidence can be made now or if we need to enact the trial period + if !exists && pe.Primed(1, pe.HeightStamp) { + err := evpool.AddEvidence(types.MakeAmnesiaEvidence(pe, types.EmptyPOLC())) + if err != nil { + return err + } + } else if !exists && evpool.State().LastBlockHeight+evpool.State().ConsensusParams.Evidence.ProofTrialPeriod < + pe.Height()+evpool.State().ConsensusParams.Evidence.MaxAgeNumBlocks { + // if we can't find a proof of lock change and we know that the trial period will finish before the + // evidence has expired, then we commence the trial period by saving it in the awaiting bucket + pbe, err := types.EvidenceToProto(pe) + if err != nil { + return err + } + evBytes, err := pbe.Marshal() + if err != nil { + return err + } + key := keyAwaiting(pe) + err = evpool.evidenceStore.Set(key, evBytes) + if err != nil { + return err + } + // keep track of when the next pe has finished the trial period + if evpool.nextEvidenceTrialEndedHeight == -1 { + evpool.nextEvidenceTrialEndedHeight = ev.Height() + evpool.State().ConsensusParams.Evidence.ProofTrialPeriod + } + } + // we don't need to do anymore processing so we can move on to the next piece of evidence + continue + } + // 2) Save to store. if err := evpool.addPendingEvidence(ev); err != nil { - return fmt.Errorf("database error: %v", err) + return fmt.Errorf("database error when adding evidence: %v", err) } // 3) Add evidence to clist. @@ -218,7 +286,7 @@ func (evpool *Pool) AddEvidence(evidence types.Evidence) error { // MarkEvidenceAsCommitted marks all the evidence as committed and removes it // from the queue. -func (evpool *Pool) MarkEvidenceAsCommitted(height int64, lastBlockTime time.Time, evidence []types.Evidence) { +func (evpool *Pool) MarkEvidenceAsCommitted(height int64, evidence []types.Evidence) { // make a map of committed evidence to remove from the clist blockEvidenceMap := make(map[string]struct{}) for _, ev := range evidence { @@ -291,17 +359,19 @@ func (evpool *Pool) IsPending(evidence types.Evidence) bool { return ok } -// RetrievePOLC attempts to find a polc at the given height and round, if not there it returns an error +// RetrievePOLC attempts to find a polc at the given height and round, if not there than exist returns false, all +// database errors are automatically logged func (evpool *Pool) RetrievePOLC(height int64, round int32) (polc types.ProofOfLockChange, err error) { var pbpolc tmproto.ProofOfLockChange key := keyPOLCFromHeightAndRound(height, round) polcBytes, err := evpool.evidenceStore.Get(key) if err != nil { + evpool.logger.Error("Unable to retrieve polc", "err", err) return polc, err } if polcBytes == nil { - return polc, fmt.Errorf("unable to find polc at height %d and round %d", height, round) + return polc, fmt.Errorf("nil value in database for key: %s", key) } err = proto.Unmarshal(polcBytes, &pbpolc) @@ -366,7 +436,7 @@ func (evpool *Pool) State() sm.State { func (evpool *Pool) addPendingEvidence(evidence types.Evidence) error { evi, err := types.EvidenceToProto(evidence) if err != nil { - return err + return fmt.Errorf("unable to convert to proto, err: %w", err) } evBytes, err := proto.Marshal(evi) @@ -399,13 +469,12 @@ func (evpool *Pool) listEvidence(prefixKey byte, maxNum int64) ([]types.Evidence } defer iter.Close() for ; iter.Valid(); iter.Next() { - val := iter.Value() - if count == maxNum { return evidence, nil } count++ + val := iter.Value() var ( ev types.Evidence evpb tmproto.Evidence @@ -511,6 +580,57 @@ func (evpool *Pool) pruneExpiredPOLC() { } } +// upgrades any potential evidence that has undergone the trial period and is primed to be made into +// amnesia evidence +func (evpool *Pool) upgradePotentialAmnesiaEvidence() int64 { + iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{baseKeyAwaiting}) + if err != nil { + evpool.logger.Error("Unable to iterate over POLC's", "err", err) + return -1 + } + defer iter.Close() + trialPeriod := evpool.State().ConsensusParams.Evidence.ProofTrialPeriod + // 1) Iterate through all potential amnesia evidence in order of height + for ; iter.Valid(); iter.Next() { + paeBytes := iter.Value() + // 2) Retrieve the evidence + var evpb tmproto.Evidence + err := evpb.Unmarshal(paeBytes) + if err != nil { + evpool.logger.Error("Unable to unmarshal potential amnesia evidence", "err", err) + continue + } + ev, err := types.EvidenceFromProto(&evpb) + if err != nil { + evpool.logger.Error("coverting to evidence from proto", "err", err) + continue + } + // 3) Check if the trial period has lapsed and amnesia evidence can be formed + if pe, ok := ev.(*types.PotentialAmnesiaEvidence); ok { + if pe.Primed(trialPeriod, evpool.State().LastBlockHeight) { + ae := types.MakeAmnesiaEvidence(*pe, types.EmptyPOLC()) + err := evpool.AddEvidence(ae) + if err != nil { + evpool.logger.Error("Unable to add amnesia evidence", "err", err) + continue + } + err = evpool.evidenceStore.Delete(iter.Key()) + if err != nil { + evpool.logger.Error("Unable to delete potential amnesia evidence", "err", err) + continue + } + } else { + evpool.logger.Debug("Potential amnesia evidence not ready to be upgraded. Ready at height", "height", + pe.HeightStamp+trialPeriod) + // once we reach a piece of evidence that isn't ready send back the height with which it will be ready + return pe.HeightStamp + trialPeriod + } + } + } + // if we have no evidence left to process we want to reset nextEvidenceTrialEndedHeight + return -1 +} + func evMapKey(ev types.Evidence) string { return string(ev.Hash()) } @@ -604,6 +724,10 @@ func keyPending(evidence types.Evidence) []byte { return append([]byte{baseKeyPending}, keySuffix(evidence)...) } +func keyAwaiting(evidence types.Evidence) []byte { + return append([]byte{baseKeyAwaiting}, keySuffix(evidence)...) +} + func keyPOLC(polc types.ProofOfLockChange) []byte { return keyPOLCFromHeightAndRound(polc.Height(), polc.Round()) } diff --git a/evidence/pool_test.go b/evidence/pool_test.go index 5aa56e28d..666b4e8e8 100644 --- a/evidence/pool_test.go +++ b/evidence/pool_test.go @@ -12,7 +12,8 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" tmproto "github.com/tendermint/tendermint/proto/types" sm "github.com/tendermint/tendermint/state" @@ -27,6 +28,8 @@ func TestMain(m *testing.M) { os.Exit(code) } +const evidenceChainID = "test_chain" + func TestEvidencePool(t *testing.T) { var ( valAddr = tmrand.Bytes(crypto.AddressSize) @@ -78,14 +81,13 @@ func TestEvidencePool(t *testing.T) { func TestProposingAndCommittingEvidence(t *testing.T) { var ( - valAddr = tmrand.Bytes(crypto.AddressSize) - height = int64(1) - lastBlockTime = time.Now() - stateDB = initializeValidatorState(valAddr, height) - evidenceDB = dbm.NewMemDB() - blockStoreDB = dbm.NewMemDB() - blockStore = initializeBlockStore(blockStoreDB, sm.LoadState(stateDB), valAddr) - evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) + valAddr = tmrand.Bytes(crypto.AddressSize) + height = int64(1) + stateDB = initializeValidatorState(valAddr, height) + evidenceDB = dbm.NewMemDB() + blockStoreDB = dbm.NewMemDB() + blockStore = initializeBlockStore(blockStoreDB, sm.LoadState(stateDB), valAddr) + evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) ) pool, err := NewPool(stateDB, evidenceDB, blockStore) @@ -104,7 +106,7 @@ func TestProposingAndCommittingEvidence(t *testing.T) { assert.Equal(t, proposedEvidence[0], evidence) // evidence seen and committed: - pool.MarkEvidenceAsCommitted(height, lastBlockTime, proposedEvidence) + pool.MarkEvidenceAsCommitted(height, proposedEvidence) assert.True(t, pool.IsCommitted(evidence)) assert.False(t, pool.IsPending(evidence)) assert.Equal(t, 0, pool.evidenceList.Len()) @@ -161,14 +163,10 @@ func TestEvidencePoolUpdate(t *testing.T) { blockStoreDB = dbm.NewMemDB() state = sm.LoadState(stateDB) blockStore = initializeBlockStore(blockStoreDB, state, valAddr) - evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) ) pool, err := NewPool(stateDB, evidenceDB, blockStore) require.NoError(t, err) - expiredEvidence := types.NewMockEvidence(1, evidenceTime, valAddr) - err = pool.AddEvidence(expiredEvidence) - require.NoError(t, err) // create new block (no need to save it to blockStore) evidence := types.NewMockEvidence(height, time.Now(), valAddr) @@ -183,8 +181,6 @@ func TestEvidencePoolUpdate(t *testing.T) { assert.True(t, pool.IsCommitted(evidence)) // b) Update updates valToLastHeight map assert.Equal(t, height+1, pool.ValidatorLastHeight(valAddr)) - // c) Expired ecvidence should be removed - assert.False(t, pool.IsPending(expiredEvidence)) } func TestEvidencePoolNewPool(t *testing.T) { @@ -246,9 +242,7 @@ func TestAddingAndPruningPOLC(t *testing.T) { pool.Update(block, state) emptyPolc, err = pool.RetrievePOLC(1, 1) - if assert.Error(t, err) { - assert.Equal(t, "unable to find polc at height 1 and round 1", err.Error()) - } + assert.Error(t, err) assert.Equal(t, types.ProofOfLockChange{}, emptyPolc) } @@ -290,18 +284,108 @@ func TestRecoverPendingEvidence(t *testing.T) { assert.True(t, pool.IsPending(goodEvidence)) } -func initializeValidatorState(valAddr []byte, height int64) dbm.DB { - stateDB := dbm.NewMemDB() - pk := ed25519.GenPrivKey().PubKey() +func TestPotentialAmnesiaEvidence(t *testing.T) { + var ( + val = types.NewMockPV() + pubKey = val.PrivKey.PubKey() + valSet = &types.ValidatorSet{ + Validators: []*types.Validator{ + val.ExtractIntoValidator(0), + }, + Proposer: val.ExtractIntoValidator(0), + } + height = int64(30) + stateDB = initializeStateFromValidatorSet(valSet, height) + evidenceDB = dbm.NewMemDB() + blockStoreDB = dbm.NewMemDB() + state = sm.LoadState(stateDB) + blockStore = initializeBlockStore(blockStoreDB, state, pubKey.Address()) + //evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) + firstBlockID = types.BlockID{ + Hash: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + PartsHeader: types.PartSetHeader{ + Total: 1, + Hash: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + }, + } + secondBlockID = types.BlockID{ + Hash: []byte("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), + PartsHeader: types.PartSetHeader{ + Total: 1, + Hash: []byte("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), + }, + } + evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) + ) - // create validator set and state - validator := &types.Validator{Address: valAddr, VotingPower: 100, PubKey: pk} - valSet := &types.ValidatorSet{ - Validators: []*types.Validator{validator}, - Proposer: validator, + pool, err := NewPool(stateDB, evidenceDB, blockStore) + require.NoError(t, err) + + pool.SetLogger(log.TestingLogger()) + + polc := types.NewMockPOLC(25, evidenceTime, pubKey) + err = pool.AddPOLC(polc) + require.NoError(t, err) + + _, err = pool.RetrievePOLC(25, 1) + require.NoError(t, err) + + voteA := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) + err = val.SignVote(evidenceChainID, voteA) + require.NoError(t, err) + voteB := makeVote(25, 1, 0, pubKey.Address(), secondBlockID) + err = val.SignVote(evidenceChainID, voteB) + require.NoError(t, err) + voteC := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) + voteC.Timestamp.Add(1 * time.Second) + err = val.SignVote(evidenceChainID, voteC) + require.NoError(t, err) + ev := types.PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, } + // we expect the evidence pool to find the polc but log an error as the polc is not valid -> vote was + // not from a validator in this set. However, an error isn't thrown because the evidence pool + // should still be able to save the regular potential amnesia evidence. + err = pool.AddEvidence(ev) + assert.NoError(t, err) + // evidence requires trial period until it is available -> we expect no evidence to be returned + assert.Equal(t, 0, len(pool.PendingEvidence(1))) + + nextHeight := pool.nextEvidenceTrialEndedHeight + assert.Greater(t, nextHeight, int64(0)) + + // evidence is not ready to be upgraded so we return the height we expect the evidence to be. + nextHeight = pool.upgradePotentialAmnesiaEvidence() + assert.Equal(t, height+pool.state.ConsensusParams.Evidence.ProofTrialPeriod, nextHeight) + + // now evidence is ready to be upgraded to amnesia evidence -> we expect -1 to be the next height as their is + // no more pending potential amnesia evidence left + pool.state.LastBlockHeight = nextHeight + nextHeight = pool.upgradePotentialAmnesiaEvidence() + assert.Equal(t, int64(-1), nextHeight) + + assert.Equal(t, 1, len(pool.PendingEvidence(1))) + + // evidence of voting back in the past which is instantly punishable -> amnesia evidence is made directly + voteA.Timestamp.Add(1 * time.Second) + + ev2 := types.PotentialAmnesiaEvidence{ + VoteA: voteB, + VoteB: voteC, + } + err = pool.AddEvidence(ev2) + assert.NoError(t, err) + + assert.Equal(t, 2, len(pool.AllPendingEvidence())) + +} + +func initializeStateFromValidatorSet(valSet *types.ValidatorSet, height int64) dbm.DB { + stateDB := dbm.NewMemDB() state := sm.State{ + ChainID: evidenceChainID, LastBlockHeight: height, LastBlockTime: tmtime.Now(), Validators: valSet, @@ -314,8 +398,10 @@ func initializeValidatorState(valAddr []byte, height int64) dbm.DB { MaxGas: -1, }, Evidence: tmproto.EvidenceParams{ - MaxAgeNumBlocks: 20, - MaxAgeDuration: 48 * time.Hour, + MaxAgeNumBlocks: 20, + MaxAgeDuration: 48 * time.Hour, + MaxNum: 50, + ProofTrialPeriod: 1, }, }, } @@ -329,6 +415,20 @@ func initializeValidatorState(valAddr []byte, height int64) dbm.DB { return stateDB } +func initializeValidatorState(valAddr []byte, height int64) dbm.DB { + + pubKey, _ := types.NewMockPV().GetPubKey() + validator := &types.Validator{Address: valAddr, VotingPower: 0, PubKey: pubKey} + + // create validator set and state + valSet := &types.ValidatorSet{ + Validators: []*types.Validator{validator}, + Proposer: validator, + } + + return initializeStateFromValidatorSet(valSet, height) +} + // initializeBlockStore creates a block storage and populates it w/ a dummy // block at +height+. func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) *store.BlockStore { @@ -358,3 +458,15 @@ func makeCommit(height int64, valAddr []byte) *types.Commit { }} return types.NewCommit(height, 0, types.BlockID{}, commitSigs) } + +func makeVote(height int64, round, index int32, addr bytes.HexBytes, blockID types.BlockID) *types.Vote { + return &types.Vote{ + Type: tmproto.SignedMsgType(2), + Height: height, + Round: round, + BlockID: blockID, + Timestamp: time.Now(), + ValidatorAddress: addr, + ValidatorIndex: index, + } +} diff --git a/proto/types/evidence.pb.go b/proto/types/evidence.pb.go index d129c04c9..391075d90 100644 --- a/proto/types/evidence.pb.go +++ b/proto/types/evidence.pb.go @@ -83,8 +83,9 @@ func (m *DuplicateVoteEvidence) GetVoteB() *Vote { } type PotentialAmnesiaEvidence struct { - VoteA *Vote `protobuf:"bytes,1,opt,name=vote_a,json=voteA,proto3" json:"vote_a,omitempty"` - VoteB *Vote `protobuf:"bytes,2,opt,name=vote_b,json=voteB,proto3" json:"vote_b,omitempty"` + VoteA *Vote `protobuf:"bytes,1,opt,name=vote_a,json=voteA,proto3" json:"vote_a,omitempty"` + VoteB *Vote `protobuf:"bytes,2,opt,name=vote_b,json=voteB,proto3" json:"vote_b,omitempty"` + HeightStamp int64 `protobuf:"varint,3,opt,name=height_stamp,json=heightStamp,proto3" json:"height_stamp,omitempty"` } func (m *PotentialAmnesiaEvidence) Reset() { *m = PotentialAmnesiaEvidence{} } @@ -134,6 +135,65 @@ func (m *PotentialAmnesiaEvidence) GetVoteB() *Vote { return nil } +func (m *PotentialAmnesiaEvidence) GetHeightStamp() int64 { + if m != nil { + return m.HeightStamp + } + return 0 +} + +type AmnesiaEvidence struct { + PotentialAmnesiaEvidence *PotentialAmnesiaEvidence `protobuf:"bytes,1,opt,name=potential_amnesia_evidence,json=potentialAmnesiaEvidence,proto3" json:"potential_amnesia_evidence,omitempty"` + Polc *ProofOfLockChange `protobuf:"bytes,2,opt,name=polc,proto3" json:"polc,omitempty"` +} + +func (m *AmnesiaEvidence) Reset() { *m = AmnesiaEvidence{} } +func (m *AmnesiaEvidence) String() string { return proto.CompactTextString(m) } +func (*AmnesiaEvidence) ProtoMessage() {} +func (*AmnesiaEvidence) Descriptor() ([]byte, []int) { + return fileDescriptor_86495eef24aeacc0, []int{2} +} +func (m *AmnesiaEvidence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AmnesiaEvidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AmnesiaEvidence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AmnesiaEvidence) XXX_Merge(src proto.Message) { + xxx_messageInfo_AmnesiaEvidence.Merge(m, src) +} +func (m *AmnesiaEvidence) XXX_Size() int { + return m.Size() +} +func (m *AmnesiaEvidence) XXX_DiscardUnknown() { + xxx_messageInfo_AmnesiaEvidence.DiscardUnknown(m) +} + +var xxx_messageInfo_AmnesiaEvidence proto.InternalMessageInfo + +func (m *AmnesiaEvidence) GetPotentialAmnesiaEvidence() *PotentialAmnesiaEvidence { + if m != nil { + return m.PotentialAmnesiaEvidence + } + return nil +} + +func (m *AmnesiaEvidence) GetPolc() *ProofOfLockChange { + if m != nil { + return m.Polc + } + return nil +} + // MockEvidence is used for testing pruposes type MockEvidence struct { EvidenceHeight int64 `protobuf:"varint,1,opt,name=evidence_height,json=evidenceHeight,proto3" json:"evidence_height,omitempty"` @@ -145,7 +205,7 @@ func (m *MockEvidence) Reset() { *m = MockEvidence{} } func (m *MockEvidence) String() string { return proto.CompactTextString(m) } func (*MockEvidence) ProtoMessage() {} func (*MockEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{2} + return fileDescriptor_86495eef24aeacc0, []int{3} } func (m *MockEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -206,7 +266,7 @@ func (m *MockRandomEvidence) Reset() { *m = MockRandomEvidence{} } func (m *MockRandomEvidence) String() string { return proto.CompactTextString(m) } func (*MockRandomEvidence) ProtoMessage() {} func (*MockRandomEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{3} + return fileDescriptor_86495eef24aeacc0, []int{4} } func (m *MockRandomEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -272,7 +332,7 @@ func (m *ConflictingHeadersEvidence) Reset() { *m = ConflictingHeadersEv func (m *ConflictingHeadersEvidence) String() string { return proto.CompactTextString(m) } func (*ConflictingHeadersEvidence) ProtoMessage() {} func (*ConflictingHeadersEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{4} + return fileDescriptor_86495eef24aeacc0, []int{5} } func (m *ConflictingHeadersEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -325,7 +385,7 @@ func (m *LunaticValidatorEvidence) Reset() { *m = LunaticValidatorEviden func (m *LunaticValidatorEvidence) String() string { return proto.CompactTextString(m) } func (*LunaticValidatorEvidence) ProtoMessage() {} func (*LunaticValidatorEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{5} + return fileDescriptor_86495eef24aeacc0, []int{6} } func (m *LunaticValidatorEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -381,6 +441,7 @@ type Evidence struct { // *Evidence_ConflictingHeadersEvidence // *Evidence_LunaticValidatorEvidence // *Evidence_PotentialAmnesiaEvidence + // *Evidence_AmnesiaEvidence // *Evidence_MockEvidence // *Evidence_MockRandomEvidence Sum isEvidence_Sum `protobuf_oneof:"sum"` @@ -390,7 +451,7 @@ func (m *Evidence) Reset() { *m = Evidence{} } func (m *Evidence) String() string { return proto.CompactTextString(m) } func (*Evidence) ProtoMessage() {} func (*Evidence) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{6} + return fileDescriptor_86495eef24aeacc0, []int{7} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -437,17 +498,21 @@ type Evidence_LunaticValidatorEvidence struct { type Evidence_PotentialAmnesiaEvidence struct { PotentialAmnesiaEvidence *PotentialAmnesiaEvidence `protobuf:"bytes,4,opt,name=potential_amnesia_evidence,json=potentialAmnesiaEvidence,proto3,oneof" json:"potential_amnesia_evidence,omitempty"` } +type Evidence_AmnesiaEvidence struct { + AmnesiaEvidence *AmnesiaEvidence `protobuf:"bytes,5,opt,name=amnesia_evidence,json=amnesiaEvidence,proto3,oneof" json:"amnesia_evidence,omitempty"` +} type Evidence_MockEvidence struct { - MockEvidence *MockEvidence `protobuf:"bytes,5,opt,name=mock_evidence,json=mockEvidence,proto3,oneof" json:"mock_evidence,omitempty"` + MockEvidence *MockEvidence `protobuf:"bytes,6,opt,name=mock_evidence,json=mockEvidence,proto3,oneof" json:"mock_evidence,omitempty"` } type Evidence_MockRandomEvidence struct { - MockRandomEvidence *MockRandomEvidence `protobuf:"bytes,6,opt,name=mock_random_evidence,json=mockRandomEvidence,proto3,oneof" json:"mock_random_evidence,omitempty"` + MockRandomEvidence *MockRandomEvidence `protobuf:"bytes,7,opt,name=mock_random_evidence,json=mockRandomEvidence,proto3,oneof" json:"mock_random_evidence,omitempty"` } func (*Evidence_DuplicateVoteEvidence) isEvidence_Sum() {} func (*Evidence_ConflictingHeadersEvidence) isEvidence_Sum() {} func (*Evidence_LunaticValidatorEvidence) isEvidence_Sum() {} func (*Evidence_PotentialAmnesiaEvidence) isEvidence_Sum() {} +func (*Evidence_AmnesiaEvidence) isEvidence_Sum() {} func (*Evidence_MockEvidence) isEvidence_Sum() {} func (*Evidence_MockRandomEvidence) isEvidence_Sum() {} @@ -486,6 +551,13 @@ func (m *Evidence) GetPotentialAmnesiaEvidence() *PotentialAmnesiaEvidence { return nil } +func (m *Evidence) GetAmnesiaEvidence() *AmnesiaEvidence { + if x, ok := m.GetSum().(*Evidence_AmnesiaEvidence); ok { + return x.AmnesiaEvidence + } + return nil +} + func (m *Evidence) GetMockEvidence() *MockEvidence { if x, ok := m.GetSum().(*Evidence_MockEvidence); ok { return x.MockEvidence @@ -507,6 +579,7 @@ func (*Evidence) XXX_OneofWrappers() []interface{} { (*Evidence_ConflictingHeadersEvidence)(nil), (*Evidence_LunaticValidatorEvidence)(nil), (*Evidence_PotentialAmnesiaEvidence)(nil), + (*Evidence_AmnesiaEvidence)(nil), (*Evidence_MockEvidence)(nil), (*Evidence_MockRandomEvidence)(nil), } @@ -522,7 +595,7 @@ func (m *EvidenceData) Reset() { *m = EvidenceData{} } func (m *EvidenceData) String() string { return proto.CompactTextString(m) } func (*EvidenceData) ProtoMessage() {} func (*EvidenceData) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{7} + return fileDescriptor_86495eef24aeacc0, []int{8} } func (m *EvidenceData) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -574,7 +647,7 @@ func (m *ProofOfLockChange) Reset() { *m = ProofOfLockChange{} } func (m *ProofOfLockChange) String() string { return proto.CompactTextString(m) } func (*ProofOfLockChange) ProtoMessage() {} func (*ProofOfLockChange) Descriptor() ([]byte, []int) { - return fileDescriptor_86495eef24aeacc0, []int{8} + return fileDescriptor_86495eef24aeacc0, []int{9} } func (m *ProofOfLockChange) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -620,6 +693,7 @@ func (m *ProofOfLockChange) GetPubKey() *keys.PublicKey { func init() { proto.RegisterType((*DuplicateVoteEvidence)(nil), "tendermint.proto.types.DuplicateVoteEvidence") proto.RegisterType((*PotentialAmnesiaEvidence)(nil), "tendermint.proto.types.PotentialAmnesiaEvidence") + proto.RegisterType((*AmnesiaEvidence)(nil), "tendermint.proto.types.AmnesiaEvidence") proto.RegisterType((*MockEvidence)(nil), "tendermint.proto.types.MockEvidence") proto.RegisterType((*MockRandomEvidence)(nil), "tendermint.proto.types.MockRandomEvidence") proto.RegisterType((*ConflictingHeadersEvidence)(nil), "tendermint.proto.types.ConflictingHeadersEvidence") @@ -632,57 +706,61 @@ func init() { func init() { proto.RegisterFile("proto/types/evidence.proto", fileDescriptor_86495eef24aeacc0) } var fileDescriptor_86495eef24aeacc0 = []byte{ - // 786 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcf, 0x4f, 0xdc, 0x46, - 0x14, 0xb6, 0xd9, 0x1f, 0x85, 0xc7, 0xd2, 0x1f, 0x16, 0x94, 0x95, 0x05, 0x0b, 0xb2, 0xaa, 0x42, - 0xab, 0xd6, 0x0b, 0x4b, 0xd5, 0x73, 0x59, 0x28, 0xda, 0x0a, 0xaa, 0x22, 0x37, 0xe2, 0x90, 0x43, - 0xac, 0xb1, 0x3d, 0x6b, 0x8f, 0xd6, 0xf6, 0x58, 0xf6, 0x78, 0x25, 0x1f, 0xa3, 0xe4, 0x90, 0xdc, - 0xf8, 0x47, 0x72, 0xcd, 0xdf, 0xc0, 0x11, 0xe5, 0x94, 0x53, 0x12, 0xc1, 0x3f, 0x12, 0x79, 0xfc, - 0x6b, 0x11, 0x18, 0xed, 0x2d, 0xca, 0x65, 0x35, 0xfb, 0xe6, 0x7d, 0xef, 0xfb, 0xc6, 0xef, 0xcd, - 0x37, 0x20, 0x07, 0x21, 0x65, 0xb4, 0xcf, 0x92, 0x00, 0x47, 0x7d, 0x3c, 0x25, 0x16, 0xf6, 0x4d, - 0xac, 0xf2, 0xa0, 0xf4, 0x23, 0xc3, 0xbe, 0x85, 0x43, 0x8f, 0xf8, 0x2c, 0x8b, 0xa8, 0x3c, 0x4d, - 0xfe, 0x99, 0x39, 0x24, 0xb4, 0xf4, 0x00, 0x85, 0x2c, 0xe9, 0x67, 0x78, 0x9b, 0xda, 0xb4, 0x5a, - 0x65, 0xd9, 0xf2, 0xfa, 0x6c, 0x6d, 0xfe, 0x9b, 0x6f, 0x6c, 0xd9, 0x94, 0xda, 0x2e, 0xce, 0xb0, - 0x46, 0x3c, 0xee, 0x33, 0xe2, 0xe1, 0x88, 0x21, 0x2f, 0xc8, 0x13, 0x36, 0x33, 0xa4, 0x19, 0x26, - 0x01, 0xa3, 0xfd, 0x09, 0x4e, 0xee, 0xe0, 0x95, 0xe7, 0x22, 0xac, 0x1d, 0xc7, 0x81, 0x4b, 0x4c, - 0xc4, 0xf0, 0x05, 0x65, 0xf8, 0xef, 0x5c, 0xb8, 0x74, 0x00, 0xed, 0x29, 0x65, 0x58, 0x47, 0x5d, - 0x71, 0x5b, 0xdc, 0x5d, 0x1e, 0x6c, 0xa8, 0x0f, 0x9f, 0x41, 0x4d, 0x51, 0x5a, 0x2b, 0xcd, 0x3d, - 0x2c, 0x41, 0x46, 0x77, 0x61, 0x5e, 0xd0, 0x50, 0x79, 0x29, 0x42, 0xf7, 0x9c, 0x32, 0xec, 0x33, - 0x82, 0xdc, 0x43, 0xcf, 0xc7, 0x11, 0x41, 0x5f, 0x40, 0xc6, 0x1b, 0x11, 0x3a, 0xff, 0x52, 0x73, - 0x52, 0x52, 0xef, 0xc0, 0x77, 0x45, 0x1b, 0x75, 0x07, 0x13, 0xdb, 0x61, 0x5c, 0x43, 0x43, 0xfb, - 0xb6, 0x08, 0x8f, 0x78, 0x54, 0xfa, 0x07, 0x56, 0xca, 0xc4, 0xf4, 0xfb, 0xe7, 0xac, 0xb2, 0x9a, - 0x35, 0x47, 0x2d, 0x9a, 0xa3, 0x3e, 0x29, 0x9a, 0x33, 0x5c, 0xbc, 0xfa, 0xb0, 0x25, 0x5c, 0x7e, - 0xdc, 0x12, 0xb5, 0x4e, 0x01, 0x4d, 0x37, 0xa5, 0x5f, 0xe0, 0xfb, 0xb2, 0x14, 0xb2, 0xac, 0x10, - 0x47, 0x51, 0xb7, 0xb1, 0x2d, 0xee, 0x76, 0xb4, 0x52, 0xcb, 0x61, 0x16, 0x56, 0xde, 0x89, 0x20, - 0xa5, 0x7a, 0x35, 0xe4, 0x5b, 0xd4, 0xfb, 0x4a, 0x54, 0x4b, 0x9b, 0x00, 0x21, 0xf2, 0x2d, 0xdd, - 0x48, 0x18, 0x8e, 0xba, 0x4d, 0x9e, 0xb4, 0x94, 0x46, 0x86, 0x69, 0x40, 0x79, 0x25, 0x82, 0x7c, - 0x44, 0xfd, 0xb1, 0x4b, 0x4c, 0x46, 0x7c, 0x7b, 0x84, 0x91, 0x85, 0xc3, 0xa8, 0x3c, 0xdc, 0x1f, - 0xb0, 0xe0, 0xec, 0xe7, 0x93, 0xf0, 0x53, 0x5d, 0x53, 0xff, 0x27, 0xb6, 0x8f, 0xad, 0x0c, 0xaa, - 0x2d, 0x38, 0xfb, 0x1c, 0x35, 0xc8, 0x8f, 0x37, 0x2f, 0x6a, 0xa0, 0xbc, 0x15, 0xa1, 0x7b, 0x16, - 0xfb, 0x88, 0x11, 0xf3, 0x02, 0xb9, 0xc4, 0x42, 0x8c, 0x86, 0xa5, 0x90, 0x3f, 0xa1, 0xed, 0xf0, - 0xd4, 0x5c, 0x4c, 0xaf, 0xae, 0x6c, 0x5e, 0x30, 0xcf, 0x96, 0xf6, 0xa0, 0x99, 0x4e, 0xdb, 0x5c, - 0x73, 0xc9, 0x33, 0xa5, 0x3d, 0x58, 0x25, 0xfe, 0x34, 0x15, 0xa0, 0x67, 0x35, 0xf4, 0x31, 0xc1, - 0xae, 0xc5, 0xbf, 0xef, 0x92, 0x26, 0xe5, 0x7b, 0x19, 0xcd, 0x49, 0xba, 0xa3, 0xbc, 0x68, 0xc1, - 0x62, 0x29, 0xd4, 0x86, 0x75, 0xab, 0xb8, 0xdf, 0x3a, 0xbf, 0x14, 0x45, 0x47, 0x72, 0xe5, 0xbf, - 0xd7, 0x69, 0x78, 0xd0, 0x16, 0x46, 0x82, 0xb6, 0x66, 0x3d, 0xe8, 0x17, 0x53, 0xd8, 0x30, 0xab, - 0xc6, 0xe5, 0x5a, 0xa3, 0x8a, 0x2d, 0x3b, 0xf1, 0xa0, 0x8e, 0xad, 0xbe, 0xe9, 0x23, 0x41, 0x93, - 0xcd, 0xfa, 0x91, 0x08, 0x40, 0x76, 0xb3, 0x2e, 0xe9, 0xd3, 0xa2, 0x4d, 0x15, 0x6b, 0x83, 0xb3, - 0xee, 0xd5, 0xb1, 0xd6, 0xf5, 0x77, 0x24, 0x68, 0x5d, 0xb7, 0xae, 0xf7, 0x01, 0xc8, 0x41, 0x61, - 0x57, 0x3a, 0xca, 0xfc, 0xaa, 0x62, 0x6c, 0x3e, 0xce, 0x58, 0x67, 0x74, 0x29, 0x63, 0x50, 0x67, - 0x82, 0xa7, 0xb0, 0xe2, 0x51, 0x73, 0x52, 0x91, 0xb4, 0x1e, 0x9f, 0xe5, 0x59, 0x1b, 0x1b, 0x09, - 0x5a, 0xc7, 0x9b, 0xb5, 0xb5, 0x67, 0xb0, 0xca, 0x8b, 0x85, 0xdc, 0x37, 0xaa, 0x9a, 0x6d, 0x5e, - 0xf3, 0xd7, 0xc7, 0x6a, 0xde, 0xb5, 0x9a, 0x91, 0xa0, 0x49, 0xde, 0xbd, 0xe8, 0xb0, 0x05, 0x8d, - 0x28, 0xf6, 0x94, 0x31, 0x74, 0x8a, 0xd0, 0x31, 0x62, 0x48, 0x1a, 0xc2, 0xe2, 0xcc, 0xe4, 0x35, - 0x76, 0x97, 0x07, 0xdb, 0x75, 0x54, 0x65, 0xa9, 0x66, 0xea, 0x37, 0x5a, 0x89, 0x93, 0x24, 0x68, - 0x3a, 0x28, 0x72, 0xf8, 0x2c, 0x75, 0x34, 0xbe, 0x56, 0x5e, 0x8b, 0xf0, 0xc3, 0x79, 0x48, 0xe9, - 0xf8, 0xbf, 0xf1, 0x19, 0x35, 0x27, 0x47, 0x0e, 0xf2, 0x6d, 0x2c, 0x0d, 0x80, 0xbb, 0x7a, 0x94, - 0x53, 0xcd, 0xf1, 0x00, 0x44, 0xd2, 0x5f, 0xf0, 0x4d, 0x10, 0x1b, 0xfa, 0x04, 0x27, 0xf9, 0xb0, - 0xee, 0xdc, 0x47, 0x65, 0xef, 0xa8, 0x9a, 0xbe, 0xa3, 0xea, 0x79, 0x6c, 0xb8, 0xc4, 0x3c, 0xc5, - 0x89, 0xd6, 0x0e, 0x62, 0xe3, 0x14, 0x27, 0xc3, 0x93, 0xab, 0x9b, 0x9e, 0x78, 0x7d, 0xd3, 0x13, - 0x3f, 0xdd, 0xf4, 0xc4, 0xcb, 0xdb, 0x9e, 0x70, 0x7d, 0xdb, 0x13, 0xde, 0xdf, 0xf6, 0x84, 0xa7, - 0xbf, 0xd9, 0x84, 0x39, 0xb1, 0xa1, 0x9a, 0xd4, 0xeb, 0x57, 0x45, 0x67, 0x97, 0x33, 0x2f, 0xbc, - 0xd1, 0xe6, 0x7f, 0x0e, 0x3e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x4c, 0xe5, 0x0b, 0x53, 0x08, - 0x00, 0x00, + // 858 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcf, 0x6f, 0xdc, 0x44, + 0x14, 0xb6, 0xb3, 0x9b, 0x6d, 0xfa, 0xb2, 0x25, 0x65, 0xd4, 0x52, 0xcb, 0x6a, 0x37, 0xc1, 0x42, + 0x34, 0x45, 0xe0, 0x4d, 0xb7, 0x88, 0x1b, 0x12, 0xd9, 0x96, 0x6a, 0x51, 0x8a, 0xa8, 0xa6, 0x55, + 0x0f, 0x1c, 0xb0, 0xc6, 0xf6, 0xac, 0x3d, 0x5a, 0xdb, 0x63, 0xd9, 0xe3, 0x95, 0x7c, 0xe4, 0x06, + 0xb7, 0xfe, 0x17, 0x9c, 0xb8, 0x72, 0xe6, 0xd8, 0x63, 0xc5, 0x09, 0x2e, 0x80, 0x92, 0x7f, 0x04, + 0x79, 0xc6, 0xf6, 0x6e, 0x7e, 0x38, 0x8a, 0x38, 0x20, 0x71, 0x59, 0x79, 0xdf, 0xbc, 0xef, 0x7b, + 0xdf, 0x9b, 0xf7, 0xc3, 0x06, 0x33, 0xcd, 0xb8, 0xe0, 0x63, 0x51, 0xa6, 0x34, 0x1f, 0xd3, 0x25, + 0xf3, 0x69, 0xe2, 0x51, 0x5b, 0x1a, 0xd1, 0x7b, 0x82, 0x26, 0x3e, 0xcd, 0x62, 0x96, 0x08, 0x65, + 0xb1, 0xa5, 0x9b, 0xf9, 0xa1, 0x08, 0x59, 0xe6, 0x3b, 0x29, 0xc9, 0x44, 0x39, 0x56, 0xf8, 0x80, + 0x07, 0x7c, 0xf5, 0xa4, 0xbc, 0xcd, 0x3b, 0xeb, 0xdc, 0xf2, 0xb7, 0x3e, 0xd8, 0x0d, 0x38, 0x0f, + 0x22, 0xaa, 0xb0, 0x6e, 0x31, 0x1f, 0x0b, 0x16, 0xd3, 0x5c, 0x90, 0x38, 0xad, 0x1d, 0xee, 0x29, + 0xa4, 0x97, 0x95, 0xa9, 0xe0, 0xe3, 0x05, 0x2d, 0x4f, 0xe1, 0xad, 0xef, 0x75, 0xb8, 0xfd, 0xa4, + 0x48, 0x23, 0xe6, 0x11, 0x41, 0x5f, 0x71, 0x41, 0xbf, 0xac, 0x85, 0xa3, 0x47, 0x30, 0x58, 0x72, + 0x41, 0x1d, 0x62, 0xe8, 0x7b, 0xfa, 0xfe, 0xf6, 0xe4, 0xae, 0x7d, 0x71, 0x0e, 0x76, 0x85, 0xc2, + 0x9b, 0x95, 0xef, 0x61, 0x0b, 0x72, 0x8d, 0x8d, 0xab, 0x82, 0xa6, 0xd6, 0x4f, 0x3a, 0x18, 0xcf, + 0xb9, 0xa0, 0x89, 0x60, 0x24, 0x3a, 0x8c, 0x13, 0x9a, 0x33, 0xf2, 0xdf, 0xcb, 0x40, 0xef, 0xc3, + 0x30, 0xa4, 0x2c, 0x08, 0x85, 0x23, 0xef, 0xcf, 0xe8, 0xed, 0xe9, 0xfb, 0x3d, 0xbc, 0xad, 0x6c, + 0x2f, 0x2a, 0x93, 0xf5, 0xab, 0x0e, 0x3b, 0x67, 0x05, 0x26, 0x60, 0xa6, 0x8d, 0x78, 0x87, 0xa8, + 0x43, 0xa7, 0x29, 0x7f, 0x2d, 0xfa, 0xa0, 0x2b, 0x7e, 0x57, 0xda, 0xd8, 0x48, 0xbb, 0x2e, 0xe4, + 0x73, 0xe8, 0xa7, 0x3c, 0xf2, 0xea, 0xcc, 0x1e, 0x74, 0x32, 0x67, 0x9c, 0xcf, 0xbf, 0x99, 0x3f, + 0xe3, 0xde, 0xe2, 0x71, 0x48, 0x92, 0x80, 0x62, 0x09, 0xb3, 0x7e, 0xd6, 0x61, 0xf8, 0x35, 0xf7, + 0x16, 0x2d, 0xdf, 0x7d, 0xd8, 0x69, 0xd4, 0x3a, 0x2a, 0x57, 0x29, 0xba, 0x87, 0xdf, 0x69, 0xcc, + 0x33, 0x69, 0x45, 0x5f, 0xc1, 0x8d, 0xd6, 0xb1, 0xea, 0xb2, 0x5a, 0x81, 0x69, 0xab, 0x16, 0xb4, + 0x9b, 0x16, 0xb4, 0x5f, 0x36, 0x2d, 0x38, 0xdd, 0x7a, 0xf3, 0xe7, 0xae, 0xf6, 0xfa, 0xaf, 0x5d, + 0x1d, 0x0f, 0x1b, 0x68, 0x75, 0x88, 0x1e, 0xc0, 0xcd, 0x96, 0x8a, 0xf8, 0x7e, 0x46, 0xf3, 0x5c, + 0x5e, 0xf7, 0x10, 0xb7, 0x5a, 0x0e, 0x95, 0xd9, 0xfa, 0x4d, 0x07, 0x54, 0xe9, 0xc5, 0x24, 0xf1, + 0x79, 0xfc, 0x3f, 0x51, 0x8d, 0xee, 0x01, 0x64, 0x24, 0xf1, 0x1d, 0xb7, 0x14, 0x34, 0x37, 0xfa, + 0xd2, 0xe9, 0x7a, 0x65, 0x99, 0x56, 0x06, 0xeb, 0x07, 0x1d, 0xcc, 0xc7, 0x3c, 0x99, 0x47, 0xcc, + 0x13, 0x2c, 0x09, 0x66, 0x94, 0xf8, 0x34, 0xcb, 0xdb, 0xe4, 0x3e, 0x85, 0x8d, 0xf0, 0x61, 0xdd, + 0x3a, 0x1f, 0x74, 0x15, 0xf8, 0x05, 0x0b, 0x12, 0xea, 0x2b, 0x28, 0xde, 0x08, 0x1f, 0x4a, 0xd4, + 0xa4, 0x4e, 0xef, 0xaa, 0xa8, 0x89, 0xf5, 0x8b, 0x0e, 0xc6, 0xb3, 0x22, 0x21, 0x82, 0x79, 0xaf, + 0x48, 0xc4, 0x7c, 0x22, 0x78, 0xd6, 0x0a, 0xf9, 0x0c, 0x06, 0xa1, 0x74, 0xad, 0xc5, 0x8c, 0xba, + 0x68, 0x6b, 0xc2, 0xda, 0x1b, 0x1d, 0x40, 0xbf, 0x9a, 0xa9, 0x2b, 0x4d, 0x9f, 0xf4, 0x44, 0x07, + 0x70, 0x8b, 0x25, 0xcb, 0x4a, 0x80, 0xa3, 0x38, 0x9c, 0x39, 0xa3, 0x91, 0x2f, 0xef, 0xf7, 0x3a, + 0x46, 0xf5, 0x99, 0x0a, 0xf3, 0xb4, 0x3a, 0xb1, 0xfe, 0xd8, 0x84, 0xad, 0x56, 0x68, 0x00, 0x77, + 0xfc, 0x66, 0x8b, 0x39, 0x72, 0xf4, 0xcf, 0x4c, 0xe0, 0x27, 0x5d, 0x1a, 0x2e, 0x5c, 0x7e, 0x33, + 0x0d, 0xdf, 0xf6, 0x2f, 0xdc, 0x8a, 0x4b, 0xb8, 0xeb, 0xad, 0x0a, 0x57, 0x6b, 0xcd, 0x57, 0xd1, + 0x54, 0xc6, 0x93, 0xae, 0x68, 0xdd, 0x45, 0x9f, 0x69, 0xd8, 0xf4, 0xba, 0x5b, 0x22, 0x05, 0x33, + 0x52, 0x55, 0x72, 0x96, 0x4d, 0x99, 0x56, 0x51, 0x7b, 0x97, 0x6f, 0x99, 0xae, 0xfa, 0xce, 0x34, + 0x6c, 0x44, 0x5d, 0xb5, 0x4f, 0x2f, 0xdd, 0x6b, 0xfd, 0x7f, 0xb7, 0xd7, 0xaa, 0x88, 0x9d, 0x9b, + 0xed, 0x25, 0xdc, 0x3c, 0x17, 0x67, 0x53, 0xc6, 0xb9, 0xdf, 0x15, 0xe7, 0x3c, 0xfd, 0x0e, 0x39, + 0xc3, 0x7a, 0x04, 0x37, 0x62, 0xee, 0x2d, 0x56, 0x94, 0x83, 0xcb, 0x27, 0x64, 0x7d, 0x39, 0xce, + 0x34, 0x3c, 0x8c, 0xd7, 0x97, 0xe5, 0x77, 0x70, 0x4b, 0x92, 0x65, 0x72, 0x1b, 0xad, 0x38, 0xaf, + 0x49, 0xce, 0x8f, 0x2e, 0xe3, 0x3c, 0xbd, 0xc0, 0x66, 0x1a, 0x46, 0xf1, 0x39, 0xeb, 0x74, 0x13, + 0x7a, 0x79, 0x11, 0x5b, 0x73, 0x18, 0x36, 0xa6, 0x27, 0x44, 0x10, 0x34, 0x85, 0xad, 0xb5, 0x7e, + 0xee, 0xed, 0x6f, 0x4f, 0xf6, 0xba, 0x42, 0xb5, 0x54, 0xfd, 0x6a, 0x8b, 0xe1, 0x16, 0x87, 0x10, + 0xf4, 0x43, 0x92, 0x87, 0xb2, 0x43, 0x87, 0x58, 0x3e, 0x5b, 0x3f, 0xea, 0xf0, 0xee, 0xb9, 0x17, + 0x05, 0x9a, 0x80, 0x7c, 0x23, 0xe6, 0x75, 0xa8, 0x2b, 0xbc, 0x3c, 0x73, 0xf4, 0x05, 0x5c, 0x4b, + 0x0b, 0xd7, 0x59, 0xd0, 0xb2, 0x1e, 0x81, 0x0b, 0x4a, 0xa6, 0xbe, 0x41, 0xec, 0xea, 0x1b, 0xc4, + 0x7e, 0x5e, 0xb8, 0x11, 0xf3, 0x8e, 0x68, 0x89, 0x07, 0x69, 0xe1, 0x1e, 0xd1, 0x72, 0xfa, 0xf4, + 0xcd, 0xf1, 0x48, 0x7f, 0x7b, 0x3c, 0xd2, 0xff, 0x3e, 0x1e, 0xe9, 0xaf, 0x4f, 0x46, 0xda, 0xdb, + 0x93, 0x91, 0xf6, 0xfb, 0xc9, 0x48, 0xfb, 0xf6, 0xe3, 0x80, 0x89, 0xb0, 0x70, 0x6d, 0x8f, 0xc7, + 0xe3, 0x15, 0xe9, 0xfa, 0xe3, 0xda, 0xd7, 0x91, 0x3b, 0x90, 0x7f, 0x1e, 0xfd, 0x13, 0x00, 0x00, + 0xff, 0xff, 0xa6, 0x62, 0x87, 0x20, 0x8f, 0x09, 0x00, 0x00, } func (m *DuplicateVoteEvidence) Marshal() (dAtA []byte, err error) { @@ -752,6 +830,11 @@ func (m *PotentialAmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error _ = i var l int _ = l + if m.HeightStamp != 0 { + i = encodeVarintEvidence(dAtA, i, uint64(m.HeightStamp)) + i-- + dAtA[i] = 0x18 + } if m.VoteB != nil { { size, err := m.VoteB.MarshalToSizedBuffer(dAtA[:i]) @@ -779,6 +862,53 @@ func (m *PotentialAmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *AmnesiaEvidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AmnesiaEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Polc != nil { + { + size, err := m.Polc.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.PotentialAmnesiaEvidence != nil { + { + size, err := m.PotentialAmnesiaEvidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *MockEvidence) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -806,12 +936,12 @@ func (m *MockEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x1a } - n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EvidenceTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.EvidenceTime):]) - if err5 != nil { - return 0, err5 + n7, err7 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EvidenceTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.EvidenceTime):]) + if err7 != nil { + return 0, err7 } - i -= n5 - i = encodeVarintEvidence(dAtA, i, uint64(n5)) + i -= n7 + i = encodeVarintEvidence(dAtA, i, uint64(n7)) i-- dAtA[i] = 0x12 if m.EvidenceHeight != 0 { @@ -856,12 +986,12 @@ func (m *MockRandomEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x1a } - n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EvidenceTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.EvidenceTime):]) - if err6 != nil { - return 0, err6 + n8, err8 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EvidenceTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.EvidenceTime):]) + if err8 != nil { + return 0, err8 } - i -= n6 - i = encodeVarintEvidence(dAtA, i, uint64(n6)) + i -= n8 + i = encodeVarintEvidence(dAtA, i, uint64(n8)) i-- dAtA[i] = 0x12 if m.EvidenceHeight != 0 { @@ -1089,6 +1219,27 @@ func (m *Evidence_PotentialAmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (i } return len(dAtA) - i, nil } +func (m *Evidence_AmnesiaEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Evidence_AmnesiaEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AmnesiaEvidence != nil { + { + size, err := m.AmnesiaEvidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} func (m *Evidence_MockEvidence) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) @@ -1106,7 +1257,7 @@ func (m *Evidence_MockEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintEvidence(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x2a + dAtA[i] = 0x32 } return len(dAtA) - i, nil } @@ -1127,7 +1278,7 @@ func (m *Evidence_MockRandomEvidence) MarshalToSizedBuffer(dAtA []byte) (int, er i = encodeVarintEvidence(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x32 + dAtA[i] = 0x3a } return len(dAtA) - i, nil } @@ -1266,6 +1417,26 @@ func (m *PotentialAmnesiaEvidence) Size() (n int) { l = m.VoteB.Size() n += 1 + l + sovEvidence(uint64(l)) } + if m.HeightStamp != 0 { + n += 1 + sovEvidence(uint64(m.HeightStamp)) + } + return n +} + +func (m *AmnesiaEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PotentialAmnesiaEvidence != nil { + l = m.PotentialAmnesiaEvidence.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + if m.Polc != nil { + l = m.Polc.Size() + n += 1 + l + sovEvidence(uint64(l)) + } return n } @@ -1407,6 +1578,18 @@ func (m *Evidence_PotentialAmnesiaEvidence) Size() (n int) { } return n } +func (m *Evidence_AmnesiaEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AmnesiaEvidence != nil { + l = m.AmnesiaEvidence.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + return n +} func (m *Evidence_MockEvidence) Size() (n int) { if m == nil { return 0 @@ -1701,6 +1884,150 @@ func (m *PotentialAmnesiaEvidence) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HeightStamp", wireType) + } + m.HeightStamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HeightStamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvidence(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AmnesiaEvidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AmnesiaEvidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AmnesiaEvidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PotentialAmnesiaEvidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PotentialAmnesiaEvidence == nil { + m.PotentialAmnesiaEvidence = &PotentialAmnesiaEvidence{} + } + if err := m.PotentialAmnesiaEvidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Polc", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Polc == nil { + m.Polc = &ProofOfLockChange{} + } + if err := m.Polc.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipEvidence(dAtA[iNdEx:]) @@ -2489,6 +2816,41 @@ func (m *Evidence) Unmarshal(dAtA []byte) error { m.Sum = &Evidence_PotentialAmnesiaEvidence{v} iNdEx = postIndex case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AmnesiaEvidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AmnesiaEvidence{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Evidence_AmnesiaEvidence{v} + iNdEx = postIndex + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field MockEvidence", wireType) } @@ -2523,7 +2885,7 @@ func (m *Evidence) Unmarshal(dAtA []byte) error { } m.Sum = &Evidence_MockEvidence{v} iNdEx = postIndex - case 6: + case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field MockRandomEvidence", wireType) } diff --git a/proto/types/evidence.proto b/proto/types/evidence.proto index 894382f7f..749e010ca 100644 --- a/proto/types/evidence.proto +++ b/proto/types/evidence.proto @@ -18,6 +18,13 @@ message DuplicateVoteEvidence { message PotentialAmnesiaEvidence { Vote vote_a = 1; Vote vote_b = 2; + + int64 height_stamp = 3; +} + +message AmnesiaEvidence { + PotentialAmnesiaEvidence potential_amnesia_evidence = 1; + ProofOfLockChange polc = 2; } // MockEvidence is used for testing pruposes @@ -52,9 +59,10 @@ message Evidence { ConflictingHeadersEvidence conflicting_headers_evidence = 2; LunaticValidatorEvidence lunatic_validator_evidence = 3; PotentialAmnesiaEvidence potential_amnesia_evidence = 4; + AmnesiaEvidence amnesia_evidence = 5; - MockEvidence mock_evidence = 5; - MockRandomEvidence mock_random_evidence = 6; + MockEvidence mock_evidence = 6; + MockRandomEvidence mock_random_evidence = 7; } } diff --git a/proto/types/params.pb.go b/proto/types/params.pb.go index 492070955..ef930e025 100644 --- a/proto/types/params.pb.go +++ b/proto/types/params.pb.go @@ -174,6 +174,10 @@ type EvidenceParams struct { // each evidence (See MaxEvidenceBytes). The maximum number is MaxEvidencePerBlock. // Default is 50 MaxNum uint32 `protobuf:"varint,3,opt,name=max_num,json=maxNum,proto3" json:"max_num,omitempty"` + // Proof trial period dictates the time given for nodes accused of amnesia evidence, incorrectly + // voting twice in two different rounds to respond with their respective proofs. + // Default is half the max age in blocks: 50,000 + ProofTrialPeriod int64 `protobuf:"varint,4,opt,name=proof_trial_period,json=proofTrialPeriod,proto3" json:"proof_trial_period,omitempty"` } func (m *EvidenceParams) Reset() { *m = EvidenceParams{} } @@ -230,6 +234,13 @@ func (m *EvidenceParams) GetMaxNum() uint32 { return 0 } +func (m *EvidenceParams) GetProofTrialPeriod() int64 { + if m != nil { + return m.ProofTrialPeriod + } + return 0 +} + // ValidatorParams restrict the public key types validators can use. // NOTE: uses ABCI pubkey naming, not Amino names. type ValidatorParams struct { @@ -348,39 +359,41 @@ func init() { proto.RegisterFile("proto/types/params.proto", fileDescriptor_95a9 func init() { golang_proto.RegisterFile("proto/types/params.proto", fileDescriptor_95a9f934fa6f056c) } var fileDescriptor_95a9f934fa6f056c = []byte{ - // 512 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0x31, 0x6f, 0xd3, 0x40, - 0x14, 0xce, 0x61, 0x28, 0xe9, 0x4b, 0xd3, 0xa0, 0x1b, 0xc0, 0x14, 0xc9, 0x89, 0x8c, 0x14, 0x2a, - 0x81, 0x6c, 0x09, 0x36, 0x96, 0x0a, 0x03, 0x6a, 0x51, 0x95, 0x08, 0x59, 0x88, 0xa1, 0x8b, 0x75, - 0x8e, 0x0f, 0xc7, 0x6a, 0xce, 0x67, 0xf9, 0xee, 0xaa, 0xf8, 0x5f, 0x30, 0x32, 0x76, 0x41, 0xe2, - 0x27, 0x30, 0x32, 0x76, 0xec, 0xc8, 0x04, 0x28, 0x59, 0xe0, 0x5f, 0x20, 0x9f, 0x63, 0x9c, 0x54, - 0x74, 0xbb, 0x7b, 0xef, 0xfb, 0xbe, 0x7b, 0xdf, 0xf7, 0x6c, 0x30, 0xb3, 0x9c, 0x4b, 0xee, 0xca, - 0x22, 0xa3, 0xc2, 0xcd, 0x48, 0x4e, 0x98, 0x70, 0x74, 0x09, 0xdf, 0x95, 0x34, 0x8d, 0x68, 0xce, - 0x92, 0x54, 0x56, 0x15, 0x47, 0x83, 0xf6, 0x86, 0x72, 0x9a, 0xe4, 0x51, 0x90, 0x91, 0x5c, 0x16, - 0x6e, 0xc5, 0x8e, 0x79, 0xcc, 0x9b, 0x53, 0x85, 0xde, 0xb3, 0x62, 0xce, 0xe3, 0x19, 0xad, 0x20, - 0xa1, 0xfa, 0xe0, 0x46, 0x2a, 0x27, 0x32, 0xe1, 0x69, 0xd5, 0xb7, 0xff, 0x20, 0xe8, 0xbd, 0xe4, - 0xa9, 0xa0, 0xa9, 0x50, 0xe2, 0xad, 0x7e, 0x19, 0x1f, 0xc0, 0xad, 0x70, 0xc6, 0x27, 0xa7, 0x26, - 0x1a, 0xa0, 0xfd, 0xce, 0xd3, 0x87, 0xce, 0xff, 0x67, 0x70, 0xbc, 0x12, 0x54, 0x71, 0xbc, 0x9b, - 0x17, 0x3f, 0xfa, 0x2d, 0xbf, 0xe2, 0xe1, 0x23, 0x68, 0xd3, 0xb3, 0x24, 0xa2, 0xe9, 0x84, 0x9a, - 0x37, 0xb4, 0xc6, 0xf0, 0x3a, 0x8d, 0xd7, 0x2b, 0xdc, 0x86, 0xcc, 0x3f, 0x36, 0x3e, 0x86, 0xed, - 0x33, 0x32, 0x4b, 0x22, 0x22, 0x79, 0x6e, 0x1a, 0x5a, 0xea, 0xd1, 0x75, 0x52, 0xef, 0x6b, 0xe0, - 0x86, 0x56, 0xc3, 0xb7, 0x29, 0x74, 0xd6, 0x46, 0xc6, 0x0f, 0x60, 0x9b, 0x91, 0x79, 0x10, 0x16, - 0x92, 0x0a, 0x6d, 0xd5, 0xf0, 0xdb, 0x8c, 0xcc, 0xbd, 0xf2, 0x8e, 0xef, 0xc1, 0xed, 0xb2, 0x19, - 0x13, 0xa1, 0x1d, 0x18, 0xfe, 0x16, 0x23, 0xf3, 0x43, 0x22, 0xf0, 0x00, 0x76, 0x64, 0xc2, 0x68, - 0x90, 0x70, 0x49, 0x02, 0x26, 0xf4, 0x50, 0x86, 0x0f, 0x65, 0xed, 0x0d, 0x97, 0x64, 0x24, 0xec, - 0xcf, 0x08, 0x76, 0x37, 0x6d, 0xe1, 0xc7, 0x80, 0x4b, 0x35, 0x12, 0xd3, 0x20, 0x55, 0x2c, 0xd0, - 0x29, 0xd5, 0x6f, 0xf6, 0x18, 0x99, 0xbf, 0x88, 0xe9, 0x58, 0x31, 0x3d, 0x9c, 0xc0, 0x23, 0xb8, - 0x53, 0x83, 0xeb, 0x65, 0xad, 0x52, 0xbc, 0xef, 0x54, 0xdb, 0x74, 0xea, 0x6d, 0x3a, 0xaf, 0x56, - 0x00, 0xaf, 0x5d, 0x9a, 0xfd, 0xf4, 0xb3, 0x8f, 0xfc, 0xdd, 0x4a, 0xaf, 0xee, 0xd4, 0x4e, 0x52, - 0xc5, 0xf4, 0xac, 0x5d, 0xed, 0x64, 0xac, 0x98, 0x7d, 0x00, 0xbd, 0x2b, 0x91, 0x61, 0x1b, 0xba, - 0x99, 0x0a, 0x83, 0x53, 0x5a, 0x04, 0x3a, 0x53, 0x13, 0x0d, 0x8c, 0xfd, 0x6d, 0xbf, 0x93, 0xa9, - 0xf0, 0x98, 0x16, 0xef, 0xca, 0xd2, 0xf3, 0xf6, 0xd7, 0xf3, 0x3e, 0xfa, 0x7d, 0xde, 0x47, 0xf6, - 0x09, 0xec, 0x1c, 0x11, 0x31, 0xa5, 0xd1, 0x8a, 0x3d, 0x84, 0x9e, 0x76, 0x16, 0x5c, 0x8d, 0xb5, - 0xab, 0xcb, 0xa3, 0x3a, 0x5b, 0x1b, 0xba, 0x0d, 0xae, 0x49, 0xb8, 0x53, 0xa3, 0x0e, 0x89, 0xf0, - 0xc6, 0x5f, 0x16, 0x16, 0xba, 0x58, 0x58, 0xe8, 0x72, 0x61, 0xa1, 0x5f, 0x0b, 0x0b, 0x7d, 0x5c, - 0x5a, 0xad, 0x6f, 0x4b, 0x0b, 0x5d, 0x2e, 0xad, 0xd6, 0xf7, 0xa5, 0xd5, 0x3a, 0x79, 0x12, 0x27, - 0x72, 0xaa, 0x42, 0x67, 0xc2, 0x99, 0xdb, 0x7c, 0x11, 0xeb, 0xc7, 0xb5, 0x9f, 0x2a, 0xdc, 0xd2, - 0x97, 0x67, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x66, 0x2c, 0xc5, 0x1a, 0x6a, 0x03, 0x00, 0x00, + // 540 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0xbf, 0x6f, 0xd3, 0x40, + 0x18, 0xcd, 0x91, 0x52, 0x92, 0x4b, 0xd3, 0x54, 0x37, 0x80, 0x29, 0x92, 0x13, 0x19, 0x29, 0x54, + 0xa2, 0x72, 0x24, 0xd8, 0x58, 0x2a, 0x02, 0xa8, 0x45, 0x55, 0xa2, 0xca, 0xaa, 0x18, 0xba, 0x9c, + 0xce, 0xf1, 0xd5, 0x39, 0x35, 0xe7, 0xb3, 0xee, 0x47, 0x95, 0xfc, 0x17, 0x8c, 0x8c, 0x1d, 0xf9, + 0x13, 0x18, 0x19, 0x3b, 0x56, 0x62, 0x61, 0x02, 0x94, 0x2c, 0xf0, 0x5f, 0x20, 0x9f, 0x63, 0x9c, + 0x54, 0x74, 0xbb, 0xfb, 0xbe, 0xf7, 0xbd, 0x7b, 0xef, 0x7b, 0x36, 0x74, 0x52, 0x29, 0xb4, 0xe8, + 0xe9, 0x59, 0x4a, 0x55, 0x2f, 0x25, 0x92, 0x70, 0xe5, 0xdb, 0x12, 0x7a, 0xa8, 0x69, 0x12, 0x51, + 0xc9, 0x59, 0xa2, 0xf3, 0x8a, 0x6f, 0x41, 0xbb, 0x5d, 0x3d, 0x66, 0x32, 0xc2, 0x29, 0x91, 0x7a, + 0xd6, 0xcb, 0xa7, 0x63, 0x11, 0x8b, 0xf2, 0x94, 0xa3, 0x77, 0xdd, 0x58, 0x88, 0x78, 0x42, 0x73, + 0x48, 0x68, 0xce, 0x7b, 0x91, 0x91, 0x44, 0x33, 0x91, 0xe4, 0x7d, 0xef, 0x0f, 0x80, 0xad, 0x37, + 0x22, 0x51, 0x34, 0x51, 0x46, 0x9d, 0xd8, 0x97, 0xd1, 0x01, 0xbc, 0x1f, 0x4e, 0xc4, 0xe8, 0xc2, + 0x01, 0x1d, 0xb0, 0xd7, 0x78, 0xf1, 0xd4, 0xff, 0xbf, 0x06, 0xbf, 0x9f, 0x81, 0xf2, 0x99, 0xfe, + 0xc6, 0xf5, 0x8f, 0x76, 0x25, 0xc8, 0xe7, 0xd0, 0x11, 0xac, 0xd1, 0x4b, 0x16, 0xd1, 0x64, 0x44, + 0x9d, 0x7b, 0x96, 0xa3, 0x7b, 0x17, 0xc7, 0xbb, 0x25, 0x6e, 0x8d, 0xe6, 0xdf, 0x34, 0x3a, 0x86, + 0xf5, 0x4b, 0x32, 0x61, 0x11, 0xd1, 0x42, 0x3a, 0x55, 0x4b, 0xf5, 0xec, 0x2e, 0xaa, 0x0f, 0x05, + 0x70, 0x8d, 0xab, 0x9c, 0xf7, 0x28, 0x6c, 0xac, 0x48, 0x46, 0x4f, 0x60, 0x9d, 0x93, 0x29, 0x0e, + 0x67, 0x9a, 0x2a, 0x6b, 0xb5, 0x1a, 0xd4, 0x38, 0x99, 0xf6, 0xb3, 0x3b, 0x7a, 0x04, 0x1f, 0x64, + 0xcd, 0x98, 0x28, 0xeb, 0xa0, 0x1a, 0x6c, 0x72, 0x32, 0x3d, 0x24, 0x0a, 0x75, 0xe0, 0x96, 0x66, + 0x9c, 0x62, 0x26, 0x34, 0xc1, 0x5c, 0x59, 0x51, 0xd5, 0x00, 0x66, 0xb5, 0xf7, 0x42, 0x93, 0x81, + 0xf2, 0xbe, 0x01, 0xb8, 0xbd, 0x6e, 0x0b, 0x3d, 0x87, 0x28, 0x63, 0x23, 0x31, 0xc5, 0x89, 0xe1, + 0xd8, 0x6e, 0xa9, 0x78, 0xb3, 0xc5, 0xc9, 0xf4, 0x75, 0x4c, 0x87, 0x86, 0x5b, 0x71, 0x0a, 0x0d, + 0xe0, 0x4e, 0x01, 0x2e, 0xc2, 0x5a, 0x6e, 0xf1, 0xb1, 0x9f, 0xa7, 0xe9, 0x17, 0x69, 0xfa, 0x6f, + 0x97, 0x80, 0x7e, 0x2d, 0x33, 0xfb, 0xe9, 0x67, 0x1b, 0x04, 0xdb, 0x39, 0x5f, 0xd1, 0x29, 0x9c, + 0x24, 0x86, 0x5b, 0xad, 0x4d, 0xeb, 0x64, 0x68, 0x38, 0xda, 0x87, 0x28, 0x95, 0x42, 0x9c, 0x63, + 0x2d, 0x19, 0x99, 0xe0, 0x94, 0x4a, 0x26, 0x22, 0x67, 0xc3, 0x8a, 0xda, 0xb1, 0x9d, 0xd3, 0xac, + 0x71, 0x62, 0xeb, 0xde, 0x01, 0x6c, 0xdd, 0x5a, 0x30, 0xf2, 0x60, 0x33, 0x35, 0x21, 0xbe, 0xa0, + 0x33, 0x6c, 0x13, 0x70, 0x40, 0xa7, 0xba, 0x57, 0x0f, 0x1a, 0xa9, 0x09, 0x8f, 0xe9, 0xec, 0x34, + 0x2b, 0xbd, 0xaa, 0x7d, 0xb9, 0x6a, 0x83, 0xdf, 0x57, 0x6d, 0xe0, 0x9d, 0xc1, 0xad, 0x23, 0xa2, + 0xc6, 0x34, 0x5a, 0x4e, 0x77, 0x61, 0xcb, 0xee, 0x01, 0xdf, 0x0e, 0xa1, 0x69, 0xcb, 0x83, 0x22, + 0x09, 0x0f, 0x36, 0x4b, 0x5c, 0x99, 0x47, 0xa3, 0x40, 0x1d, 0x12, 0xd5, 0x1f, 0x7e, 0x9e, 0xbb, + 0xe0, 0x7a, 0xee, 0x82, 0x9b, 0xb9, 0x0b, 0x7e, 0xcd, 0x5d, 0xf0, 0x71, 0xe1, 0x56, 0xbe, 0x2e, + 0x5c, 0x70, 0xb3, 0x70, 0x2b, 0xdf, 0x17, 0x6e, 0xe5, 0x6c, 0x3f, 0x66, 0x7a, 0x6c, 0x42, 0x7f, + 0x24, 0x78, 0xaf, 0xfc, 0x7e, 0x56, 0x8f, 0x2b, 0xbf, 0x60, 0xb8, 0x69, 0x2f, 0x2f, 0xff, 0x06, + 0x00, 0x00, 0xff, 0xff, 0x5d, 0x39, 0x60, 0xf5, 0x98, 0x03, 0x00, 0x00, } func (this *ConsensusParams) Equal(that interface{}) bool { @@ -471,6 +484,9 @@ func (this *EvidenceParams) Equal(that interface{}) bool { if this.MaxNum != that1.MaxNum { return false } + if this.ProofTrialPeriod != that1.ProofTrialPeriod { + return false + } return true } func (this *ValidatorParams) Equal(that interface{}) bool { @@ -640,6 +656,11 @@ func (m *EvidenceParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.ProofTrialPeriod != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.ProofTrialPeriod)) + i-- + dAtA[i] = 0x20 + } if m.MaxNum != 0 { i = encodeVarintParams(dAtA, i, uint64(m.MaxNum)) i-- @@ -868,6 +889,9 @@ func (m *EvidenceParams) Size() (n int) { if m.MaxNum != 0 { n += 1 + sovParams(uint64(m.MaxNum)) } + if m.ProofTrialPeriod != 0 { + n += 1 + sovParams(uint64(m.ProofTrialPeriod)) + } return n } @@ -1269,6 +1293,25 @@ func (m *EvidenceParams) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProofTrialPeriod", wireType) + } + m.ProofTrialPeriod = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProofTrialPeriod |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/proto/types/params.proto b/proto/types/params.proto index bc8eeb9ab..9fc5406bc 100644 --- a/proto/types/params.proto +++ b/proto/types/params.proto @@ -52,6 +52,11 @@ message EvidenceParams { // each evidence (See MaxEvidenceBytes). The maximum number is MaxEvidencePerBlock. // Default is 50 uint32 max_num = 3; + + // Proof trial period dictates the time given for nodes accused of amnesia evidence, incorrectly + // voting twice in two different rounds to respond with their respective proofs. + // Default is half the max age in blocks: 50,000 + int64 proof_trial_period = 4; } // ValidatorParams restrict the public key types validators can use. diff --git a/state/store_test.go b/state/store_test.go index 04b952373..2d8e0067b 100644 --- a/state/store_test.go +++ b/state/store_test.go @@ -12,7 +12,9 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + tmrand "github.com/tendermint/tendermint/libs/rand" tmstate "github.com/tendermint/tendermint/proto/state" tmproto "github.com/tendermint/tendermint/proto/types" sm "github.com/tendermint/tendermint/state" @@ -99,7 +101,7 @@ func TestPruneStates(t *testing.T) { // Generate a bunch of state data. Validators change for heights ending with 3, and // parameters when ending with 5. - validator := &types.Validator{Address: []byte{1, 2, 3}, VotingPower: 100, PubKey: pk} + validator := &types.Validator{Address: tmrand.Bytes(crypto.AddressSize), VotingPower: 100, PubKey: pk} validatorSet := &types.ValidatorSet{ Validators: []*types.Validator{validator}, Proposer: validator, diff --git a/state/validation.go b/state/validation.go index 018b8d295..609f66b50 100644 --- a/state/validation.go +++ b/state/validation.go @@ -142,6 +142,16 @@ func validateBlock(evidencePool EvidencePool, stateDB dbm.DB, state State, block continue } } + // if we don't already have amnesia evidence we need to add it to start our own timer unless + // a) a valid polc has already been attached + // b) the accused node voted back on an earlier round + if ae, ok := ev.(types.AmnesiaEvidence); ok && ae.Polc.IsAbsent() && ae.PotentialAmnesiaEvidence.VoteA.Round < + ae.PotentialAmnesiaEvidence.VoteB.Round { + if err := evidencePool.AddEvidence(ae); err != nil { + return types.NewErrEvidenceInvalid(ev, + fmt.Errorf("unknown amnesia evidence, trying to add to evidence pool, err: %w", err)) + } + } var header *types.Header if _, ok := ev.(*types.LunaticValidatorEvidence); ok { @@ -154,6 +164,7 @@ func validateBlock(evidencePool EvidencePool, stateDB dbm.DB, state State, block if err := VerifyEvidence(stateDB, state, ev, header); err != nil { return types.NewErrEvidenceInvalid(ev, err) } + } // NOTE: We can't actually verify it's the right proposer because we dont @@ -197,7 +208,7 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence, commit state.LastBlockTime.Add(evidenceParams.MaxAgeDuration), ) } - if ev, ok := evidence.(*types.LunaticValidatorEvidence); ok { + if ev, ok := evidence.(types.LunaticValidatorEvidence); ok { if err := ev.VerifyHeader(committedHeader); err != nil { return err } @@ -216,7 +227,9 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence, commit // For PhantomValidatorEvidence, check evidence.Address was not part of the // validator set at height evidence.Height, but was a validator before OR // after. - if phve, ok := evidence.(*types.PhantomValidatorEvidence); ok { + if phve, ok := evidence.(types.PhantomValidatorEvidence); ok { + // confirm that it hasn't been forged + _, val = valset.GetByAddress(addr) if val != nil { return fmt.Errorf("address %X was a validator at height %d", addr, evidence.Height()) @@ -224,9 +237,9 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence, commit // check if last height validator was in the validator set is within // MaxAgeNumBlocks. - if ageNumBlocks > 0 && phve.LastHeightValidatorWasInSet <= ageNumBlocks { + if height-phve.LastHeightValidatorWasInSet > evidenceParams.MaxAgeNumBlocks { return fmt.Errorf("last time validator was in the set at height %d, min: %d", - phve.LastHeightValidatorWasInSet, ageNumBlocks+1) + phve.LastHeightValidatorWasInSet, height-phve.LastHeightValidatorWasInSet) } valset, err := LoadValidators(stateDB, phve.LastHeightValidatorWasInSet) @@ -240,6 +253,16 @@ func VerifyEvidence(stateDB dbm.DB, state State, evidence types.Evidence, commit return fmt.Errorf("phantom validator %X not found", addr) } } else { + if ae, ok := evidence.(types.AmnesiaEvidence); ok { + // check the validator set against the polc to make sure that a majority of valid votes was reached + if !ae.Polc.IsAbsent() { + err = ae.Polc.ValidateVotes(valset, state.ChainID) + if err != nil { + return fmt.Errorf("amnesia evidence contains invalid polc, err: %w", err) + } + } + } + // For all other types, expect evidence.Address to be a validator at height // evidence.Height. _, val = valset.GetByAddress(addr) diff --git a/state/validation_test.go b/state/validation_test.go index ad2c63599..89f6e311f 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -1,16 +1,22 @@ package state_test import ( + "fmt" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/proto/version" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/libs/log" memmock "github.com/tendermint/tendermint/mempool/mock" + protostate "github.com/tendermint/tendermint/proto/state" tmproto "github.com/tendermint/tendermint/proto/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/state/mocks" @@ -285,8 +291,8 @@ func TestValidateFailBlockOnCommittedEvidence(t *testing.T) { block.EvidenceHash = block.Evidence.Hash() err := blockExec.ValidateBlock(state, block) - require.Error(t, err) - require.IsType(t, err, &types.ErrEvidenceInvalid{}) + assert.Error(t, err) + assert.IsType(t, err, &types.ErrEvidenceInvalid{}) } func TestValidateAlreadyPendingEvidence(t *testing.T) { @@ -314,7 +320,7 @@ func TestValidateAlreadyPendingEvidence(t *testing.T) { block.EvidenceHash = block.Evidence.Hash() err := blockExec.ValidateBlock(state, block) - require.NoError(t, err) + assert.NoError(t, err) } func TestValidateDuplicateEvidenceShouldFail(t *testing.T) { @@ -336,5 +342,274 @@ func TestValidateDuplicateEvidenceShouldFail(t *testing.T) { block.EvidenceHash = block.Evidence.Hash() err := blockExec.ValidateBlock(state, block) - require.Error(t, err) + assert.Error(t, err) +} + +var blockID = types.BlockID{ + Hash: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + PartsHeader: types.PartSetHeader{ + Total: 1, + Hash: []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + }, +} + +func TestValidateAmnesiaEvidence(t *testing.T) { + var height int64 = 1 + state, stateDB, vals := makeState(1, int(height)) + addr, val := state.Validators.GetByIndex(0) + voteA := makeVote(height, 1, 0, addr, blockID) + err := vals[val.Address.String()].SignVote(chainID, voteA) + require.NoError(t, err) + voteB := makeVote(height, 2, 0, addr, types.BlockID{}) + err = vals[val.Address.String()].SignVote(chainID, voteB) + require.NoError(t, err) + ae := types.AmnesiaEvidence{ + PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, + }, + Polc: types.EmptyPOLC(), + } + + evpool := &mocks.EvidencePool{} + evpool.On("IsPending", ae).Return(false) + evpool.On("IsCommitted", ae).Return(false) + evpool.On("AddEvidence", ae).Return(fmt.Errorf("test error")) + + blockExec := sm.NewBlockExecutor( + stateDB, log.TestingLogger(), + nil, + nil, + evpool) + // A block with a couple pieces of evidence passes. + block := makeBlock(state, height) + block.Evidence.Evidence = []types.Evidence{ae} + block.EvidenceHash = block.Evidence.Hash() + err = blockExec.ValidateBlock(state, block) + + errMsg := "Invalid evidence: unknown amnesia evidence, trying to add to evidence pool, err: test error" + if assert.Error(t, err) { + assert.Equal(t, err.Error()[:len(errMsg)], errMsg) + } +} + +func TestVerifyEvidenceWrongAddress(t *testing.T) { + var height int64 = 1 + state, stateDB, _ := makeState(1, int(height)) + randomAddr := []byte("wrong address") + ev := types.NewMockEvidence(height, defaultTestTime, randomAddr) + + blockExec := sm.NewBlockExecutor( + stateDB, log.TestingLogger(), + nil, + nil, + sm.MockEvidencePool{}) + // A block with a couple pieces of evidence passes. + block := makeBlock(state, height) + block.Evidence.Evidence = []types.Evidence{ev} + block.EvidenceHash = block.Evidence.Hash() + err := blockExec.ValidateBlock(state, block) + errMsg := "Invalid evidence: address 77726F6E672061646472657373 was not a validator at height 1" + if assert.Error(t, err) { + assert.Equal(t, err.Error()[:len(errMsg)], errMsg) + } +} + +func TestVerifyEvidenceExpiredEvidence(t *testing.T) { + var height int64 = 4 + state, stateDB, _ := makeState(1, int(height)) + state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1 + addr, _ := state.Validators.GetByIndex(0) + ev := types.NewMockEvidence(1, defaultTestTime, addr) + err := sm.VerifyEvidence(stateDB, state, ev, nil) + errMsg := "evidence from height 1 (created at: 2019-01-01 00:00:00 +0000 UTC) is too old" + if assert.Error(t, err) { + assert.Equal(t, err.Error()[:len(errMsg)], errMsg) + } +} + +func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) { + var height int64 = 1 + state, stateDB, vals := makeState(4, int(height)) + addr, val := state.Validators.GetByIndex(0) + addr2, val2 := state.Validators.GetByIndex(1) + voteA := makeVote(height, 1, 0, addr, types.BlockID{}) + err := vals[val.Address.String()].SignVote(chainID, voteA) + require.NoError(t, err) + voteB := makeVote(height, 2, 0, addr, blockID) + err = vals[val.Address.String()].SignVote(chainID, voteB) + require.NoError(t, err) + voteC := makeVote(height, 2, 1, addr2, blockID) + err = vals[val2.Address.String()].SignVote(chainID, voteC) + require.NoError(t, err) + //var ae types.Evidence + badAe := types.AmnesiaEvidence{ + PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, + }, + Polc: types.ProofOfLockChange{ + Votes: []types.Vote{*voteC}, + PubKey: val.PubKey, + }, + } + err = sm.VerifyEvidence(stateDB, state, badAe, nil) + if assert.Error(t, err) { + assert.Equal(t, err.Error(), "amnesia evidence contains invalid polc, err: "+ + "invalid commit -- insufficient voting power: got 1000, needed more than 2667") + } + addr3, val3 := state.Validators.GetByIndex(2) + voteD := makeVote(height, 2, 2, addr3, blockID) + err = vals[val3.Address.String()].SignVote(chainID, voteD) + require.NoError(t, err) + addr4, val4 := state.Validators.GetByIndex(3) + voteE := makeVote(height, 2, 3, addr4, blockID) + err = vals[val4.Address.String()].SignVote(chainID, voteE) + require.NoError(t, err) + + goodAe := types.AmnesiaEvidence{ + PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, + }, + Polc: types.ProofOfLockChange{ + Votes: []types.Vote{*voteC, *voteD, *voteE}, + PubKey: val.PubKey, + }, + } + err = sm.VerifyEvidence(stateDB, state, goodAe, nil) + assert.NoError(t, err) + + goodAe = types.AmnesiaEvidence{ + PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, + }, + Polc: types.EmptyPOLC(), + } + err = sm.VerifyEvidence(stateDB, state, goodAe, nil) + assert.NoError(t, err) + +} + +func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) { + state, stateDB, vals := makeState(4, 4) + state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1 + addr, val := state.Validators.GetByIndex(0) + h := &types.Header{ + Version: version.Consensus{Block: 1, App: 2}, + ChainID: chainID, + Height: 3, + Time: defaultTestTime, + LastBlockID: blockID, + LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), + DataHash: tmhash.Sum([]byte("data_hash")), + ValidatorsHash: tmhash.Sum([]byte("validators_hash")), + NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), + ConsensusHash: tmhash.Sum([]byte("consensus_hash")), + AppHash: tmhash.Sum([]byte("app_hash")), + LastResultsHash: tmhash.Sum([]byte("last_results_hash")), + EvidenceHash: tmhash.Sum([]byte("evidence_hash")), + ProposerAddress: crypto.AddressHash([]byte("proposer_address")), + } + vote := makeVote(3, 1, 0, addr, blockID) + err := vals[val.Address.String()].SignVote(chainID, vote) + require.NoError(t, err) + ev := types.LunaticValidatorEvidence{ + Header: h, + Vote: vote, + InvalidHeaderField: "ConsensusHash", + } + err = ev.ValidateBasic() + require.NoError(t, err) + err = sm.VerifyEvidence(stateDB, state, ev, h) + if assert.Error(t, err) { + assert.Equal(t, "ConsensusHash matches committed hash", err.Error()) + } +} + +func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) { + state, stateDB, vals := makeState(4, 4) + state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1 + addr, val := state.Validators.GetByIndex(0) + vote := makeVote(3, 1, 0, addr, blockID) + err := vals[val.Address.String()].SignVote(chainID, vote) + require.NoError(t, err) + ev := types.PhantomValidatorEvidence{ + Vote: vote, + LastHeightValidatorWasInSet: 1, + } + err = ev.ValidateBasic() + require.NoError(t, err) + err = sm.VerifyEvidence(stateDB, state, ev, nil) + if assert.Error(t, err) { + assert.Equal(t, "address 576585A00DD4D58318255611D8AAC60E8E77CB32 was a validator at height 3", err.Error()) + } + + privVal := types.NewMockPV() + pubKey, _ := privVal.GetPubKey() + vote2 := makeVote(3, 1, 0, pubKey.Address(), blockID) + err = privVal.SignVote(chainID, vote2) + require.NoError(t, err) + ev = types.PhantomValidatorEvidence{ + Vote: vote2, + LastHeightValidatorWasInSet: 1, + } + err = ev.ValidateBasic() + assert.NoError(t, err) + err = sm.VerifyEvidence(stateDB, state, ev, nil) + if assert.Error(t, err) { + assert.Equal(t, "last time validator was in the set at height 1, min: 2", err.Error()) + } + + ev = types.PhantomValidatorEvidence{ + Vote: vote2, + LastHeightValidatorWasInSet: 2, + } + err = ev.ValidateBasic() + assert.NoError(t, err) + err = sm.VerifyEvidence(stateDB, state, ev, nil) + errMsg := "phantom validator" + if assert.Error(t, err) { + assert.Equal(t, errMsg, err.Error()[:len(errMsg)]) + } + + vals2, err := sm.LoadValidators(stateDB, 2) + require.NoError(t, err) + vals2.Validators = append(vals2.Validators, types.NewValidator(pubKey, 1000)) + valKey := []byte("validatorsKey:2") + protoVals, err := vals2.ToProto() + require.NoError(t, err) + valInfo := &protostate.ValidatorsInfo{ + LastHeightChanged: 2, + ValidatorSet: protoVals, + } + + bz, err := valInfo.Marshal() + require.NoError(t, err) + + stateDB.Set(valKey, bz) + ev = types.PhantomValidatorEvidence{ + Vote: vote2, + LastHeightValidatorWasInSet: 2, + } + err = ev.ValidateBasic() + assert.NoError(t, err) + err = sm.VerifyEvidence(stateDB, state, ev, nil) + if !assert.NoError(t, err) { + t.Log(err) + } + +} + +func makeVote(height int64, round, index int32, addr bytes.HexBytes, blockID types.BlockID) *types.Vote { + return &types.Vote{ + Type: tmproto.SignedMsgType(2), + Height: height, + Round: round, + BlockID: blockID, + Timestamp: time.Now(), + ValidatorAddress: addr, + ValidatorIndex: index, + } } diff --git a/tools/tm-signer-harness/internal/test_harness_test.go b/tools/tm-signer-harness/internal/test_harness_test.go index 82db9949e..28d0d61c4 100644 --- a/tools/tm-signer-harness/internal/test_harness_test.go +++ b/tools/tm-signer-harness/internal/test_harness_test.go @@ -48,7 +48,8 @@ const ( "evidence": { "max_age_num_blocks": "100000", "max_age_duration": "172800000000000", - "max_num_evidence": 50 + "max_num": 50, + "proof_trial_period": "50000" }, "validator": { "pub_key_types": [ diff --git a/types/evidence.go b/types/evidence.go index 39b16064d..6c59bf93a 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -165,8 +165,9 @@ func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) { tp := &tmproto.Evidence{ Sum: &tmproto.Evidence_PotentialAmnesiaEvidence{ PotentialAmnesiaEvidence: &tmproto.PotentialAmnesiaEvidence{ - VoteA: voteA, - VoteB: voteB, + VoteA: voteA, + VoteB: voteB, + HeightStamp: evi.HeightStamp, }, }, } @@ -179,13 +180,20 @@ func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) { tp := &tmproto.Evidence{ Sum: &tmproto.Evidence_PotentialAmnesiaEvidence{ PotentialAmnesiaEvidence: &tmproto.PotentialAmnesiaEvidence{ - VoteA: voteA, - VoteB: voteB, + VoteA: voteA, + VoteB: voteB, + HeightStamp: evi.HeightStamp, }, }, } - return tp, nil + + case AmnesiaEvidence: + return AmnesiaEvidenceToProto(evi) + + case *AmnesiaEvidence: + return AmnesiaEvidenceToProto(*evi) + case MockEvidence: if err := evi.ValidateBasic(); err != nil { return nil, err @@ -284,21 +292,24 @@ func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) { return &tp, tp.ValidateBasic() case *tmproto.Evidence_PotentialAmnesiaEvidence: - voteA, err := VoteFromProto(evi.PotentialAmnesiaEvidence.GetVoteA()) + return PotentialAmnesiaEvidenceFromProto(evi.PotentialAmnesiaEvidence) + + case *tmproto.Evidence_AmnesiaEvidence: + pae, err := PotentialAmnesiaEvidenceFromProto(evi.AmnesiaEvidence.PotentialAmnesiaEvidence) + if err != nil { + return nil, err + } + polc, err := ProofOfLockChangeFromProto(evi.AmnesiaEvidence.Polc) if err != nil { return nil, err } - voteB, err := VoteFromProto(evi.PotentialAmnesiaEvidence.GetVoteB()) - if err != nil { - return nil, err - } - tp := PotentialAmnesiaEvidence{ - VoteA: voteA, - VoteB: voteB, + tp := AmnesiaEvidence{ + PotentialAmnesiaEvidence: *pae, + Polc: *polc, } - return &tp, tp.ValidateBasic() + return tp, tp.ValidateBasic() case *tmproto.Evidence_MockEvidence: me := MockEvidence{ EvidenceHeight: evi.MockEvidence.GetEvidenceHeight(), @@ -328,6 +339,7 @@ func RegisterEvidences(cdc *amino.Codec) { cdc.RegisterConcrete(&PhantomValidatorEvidence{}, "tendermint/PhantomValidatorEvidence", nil) cdc.RegisterConcrete(&LunaticValidatorEvidence{}, "tendermint/LunaticValidatorEvidence", nil) cdc.RegisterConcrete(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence", nil) + cdc.RegisterConcrete(&AmnesiaEvidence{}, "tendermint/AmnesiaEvidence", nil) } func init() { @@ -336,6 +348,7 @@ func init() { tmjson.RegisterType(&PhantomValidatorEvidence{}, "tendermint/PhantomValidatorEvidence") tmjson.RegisterType(&LunaticValidatorEvidence{}, "tendermint/LunaticValidatorEvidence") tmjson.RegisterType(&PotentialAmnesiaEvidence{}, "tendermint/PotentialAmnesiaEvidence") + tmjson.RegisterType(&AmnesiaEvidence{}, "tendermint/AmnesiaEvidence") } func RegisterMockEvidences(cdc *amino.Codec) { @@ -654,10 +667,26 @@ OUTER_LOOP: } else { // if H1.Round != H2.Round we need to run full detection procedure => not // immediately slashable. - evList = append(evList, &PotentialAmnesiaEvidence{ - VoteA: ev.H1.Commit.GetVote(int32(i)), - VoteB: ev.H2.Commit.GetVote(int32(j)), - }) + firstVote := ev.H1.Commit.GetVote(int32(i)) + secondVote := ev.H2.Commit.GetVote(int32(j)) + var newEv PotentialAmnesiaEvidence + if firstVote.Timestamp.Before(secondVote.Timestamp) { + newEv = PotentialAmnesiaEvidence{ + VoteA: firstVote, + VoteB: secondVote, + } + } else { + newEv = PotentialAmnesiaEvidence{ + VoteA: secondVote, + VoteB: firstVote, + } + } + // has the validator incorrectly voted for a previous round + if newEv.VoteA.Round > newEv.VoteB.Round { + evList = append(evList, MakeAmnesiaEvidence(newEv, EmptyPOLC())) + } else { + evList = append(evList, newEv) + } } i++ @@ -1001,9 +1030,16 @@ func (e LunaticValidatorEvidence) VerifyHeader(committedHeader *Header) error { //------------------------------------------- +// PotentialAmnesiaEvidence is constructed when a validator votes on two different blocks at different rounds +// in the same height. PotentialAmnesiaEvidence can then evolve into AmensiaEvidence if the indicted validator +// is incapable of providing the proof of lock change that validates voting twice in the allotted trial period. +// Heightstamp is used for each node to keep a track of how much time has passed so as to know when the trial period +// is finished and is set when the node first receives the evidence. type PotentialAmnesiaEvidence struct { VoteA *Vote `json:"vote_a"` VoteB *Vote `json:"vote_b"` + + HeightStamp int64 } var _ Evidence = PotentialAmnesiaEvidence{} @@ -1013,10 +1049,7 @@ func (e PotentialAmnesiaEvidence) Height() int64 { } func (e PotentialAmnesiaEvidence) Time() time.Time { - if e.VoteA.Timestamp.Before(e.VoteB.Timestamp) { - return e.VoteA.Timestamp - } - return e.VoteB.Timestamp + return e.VoteA.Timestamp } func (e PotentialAmnesiaEvidence) Address() []byte { @@ -1053,9 +1086,11 @@ func (e PotentialAmnesiaEvidence) Verify(chainID string, pubKey crypto.PubKey) e func (e PotentialAmnesiaEvidence) Equal(ev Evidence) bool { switch e2 := ev.(type) { case PotentialAmnesiaEvidence: - return bytes.Equal(e.Hash(), e2.Hash()) + return e.Height() == e2.Height() && e.VoteA.Round == e2.VoteA.Round && e.VoteB.Round == e2.VoteB.Round && + bytes.Equal(e.Address(), e2.Address()) case *PotentialAmnesiaEvidence: - return bytes.Equal(e.Hash(), e2.Hash()) + return e.Height() == e2.Height() && e.VoteA.Round == e2.VoteA.Round && e.VoteB.Round == e2.VoteB.Round && + bytes.Equal(e.Address(), e2.Address()) default: return false } @@ -1071,10 +1106,6 @@ func (e PotentialAmnesiaEvidence) ValidateBasic() error { if err := e.VoteB.ValidateBasic(); err != nil { return fmt.Errorf("invalid VoteB: %v", err) } - // Enforce Votes are lexicographically sorted on blockID - if strings.Compare(e.VoteA.BlockID.Key(), e.VoteB.BlockID.Key()) >= 0 { - return errors.New("amnesia votes in invalid order") - } // H/S must be the same if e.VoteA.Height != e.VoteB.Height || @@ -1083,9 +1114,10 @@ func (e PotentialAmnesiaEvidence) ValidateBasic() error { e.VoteA.Height, e.VoteA.Type, e.VoteB.Height, e.VoteB.Type) } - // R must be different - if e.VoteA.Round == e.VoteB.Round { - return fmt.Errorf("expected votes from different rounds, got %d", e.VoteA.Round) + // Enforce that vote A came before vote B + if e.VoteA.Timestamp.After(e.VoteB.Timestamp) { + return fmt.Errorf("vote A should have a timestamp before vote B, but got %s > %s", + e.VoteA.Timestamp, e.VoteB.Timestamp) } // Address must be the same @@ -1121,6 +1153,21 @@ func (e PotentialAmnesiaEvidence) String() string { return fmt.Sprintf("PotentialAmnesiaEvidence{VoteA: %v, VoteB: %v}", e.VoteA, e.VoteB) } +// Primed finds whether the PotentialAmnesiaEvidence is ready to be upgraded to Amnesia Evidence. It is decided if +// either the prosecuted node voted in the past or if the allocated trial period has expired without a proof of lock +// change having been provided. +func (e PotentialAmnesiaEvidence) Primed(trialPeriod, currentHeight int64) bool { + // voted in the past can be instantly punishable + if e.VoteA.Round > e.VoteB.Round { + return true + } + // has the trial period expired + if e.HeightStamp > 0 { + return e.HeightStamp+trialPeriod <= currentHeight + } + return false +} + // ProofOfLockChange (POLC) proves that a node followed the consensus protocol and voted for a precommit in two // different rounds because the node received a majority of votes for a different block in the latter round. In cases of // amnesia evidence, a suspected node will need ProofOfLockChange to prove that the node did not break protocol. @@ -1151,6 +1198,15 @@ func makePOLCFromVoteSet(voteSet *VoteSet, pubKey crypto.PubKey, blockID BlockID } } +// EmptyPOLC returns an empty polc. This is used when no polc has been provided in the allocated trial period time +// and the node now needs to move to upgrading to AmnesiaEvidence and hence uses an empty polc +func EmptyPOLC() ProofOfLockChange { + return ProofOfLockChange{ + nil, + nil, + } +} + func (e ProofOfLockChange) Height() int64 { return e.Votes[0].Height } @@ -1178,23 +1234,38 @@ func (e ProofOfLockChange) BlockID() BlockID { return e.Votes[0].BlockID } -// In order for a ProofOfLockChange to be valid, a validator must have received +2/3 majority of votes -// MajorityOfVotes checks that there were sufficient votes in order to change locks -func (e ProofOfLockChange) MajorityOfVotes(valSet *ValidatorSet) bool { +// ValidateVotes checks the polc against the validator set of that height. The function makes sure that the polc +// contains a majority of votes and that each +func (e ProofOfLockChange) ValidateVotes(valSet *ValidatorSet, chainID string) error { + if e.IsAbsent() { + return errors.New("polc is empty") + } talliedVotingPower := int64(0) votingPowerNeeded := valSet.TotalVotingPower() * 2 / 3 - for _, validator := range valSet.Validators { - for _, vote := range e.Votes { + for _, vote := range e.Votes { + exists := false + for _, validator := range valSet.Validators { if bytes.Equal(validator.Address, vote.ValidatorAddress) { - talliedVotingPower += validator.VotingPower - - if talliedVotingPower > votingPowerNeeded { - return true + exists = true + if !validator.PubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) { + return fmt.Errorf("cannot verify vote (from validator: %d) against signature: %v", + vote.ValidatorIndex, vote.Signature) } + + talliedVotingPower += validator.VotingPower } } + if !exists { + return fmt.Errorf("vote was not from a validator in this set: %v", vote.String()) + } } - return false + if talliedVotingPower <= votingPowerNeeded { + return ErrNotEnoughVotingPowerSigned{ + Got: talliedVotingPower, + Needed: votingPowerNeeded + 1, + } + } + return nil } func (e ProofOfLockChange) Equal(e2 ProofOfLockChange) bool { @@ -1203,6 +1274,11 @@ func (e ProofOfLockChange) Equal(e2 ProofOfLockChange) bool { } func (e ProofOfLockChange) ValidateBasic() error { + // first check if the polc is absent / empty + if e.IsAbsent() { + return nil + } + if e.PubKey == nil { return errors.New("missing public key") } @@ -1240,7 +1316,7 @@ func (e ProofOfLockChange) ValidateBasic() error { if bytes.Equal(vote.ValidatorAddress.Bytes(), e.PubKey.Address().Bytes()) { return fmt.Errorf("vote validator address cannot be the same as the public key address: %X all votes %v", - vote.ValidatorAddress.Bytes(), e.Votes) + vote.ValidatorAddress.Bytes(), e.PubKey.Address().Bytes()) } for i := idx + 1; i < len(e.Votes); i++ { @@ -1254,10 +1330,18 @@ func (e ProofOfLockChange) ValidateBasic() error { } func (e ProofOfLockChange) String() string { + if e.IsAbsent() { + return "Empty ProofOfLockChange" + } return fmt.Sprintf("ProofOfLockChange {Address: %X, Height: %d, Round: %d", e.Address(), e.Height(), e.Votes[0].Round) } +// IsAbsent checks if the polc is empty +func (e ProofOfLockChange) IsAbsent() bool { + return e.Votes == nil && e.PubKey == nil +} + func (e *ProofOfLockChange) ToProto() (*tmproto.ProofOfLockChange, error) { if e == nil { return nil, errors.New("nil proof of lock change") @@ -1265,6 +1349,14 @@ func (e *ProofOfLockChange) ToProto() (*tmproto.ProofOfLockChange, error) { plc := new(tmproto.ProofOfLockChange) vpb := make([]*tmproto.Vote, len(e.Votes)) + // if absent create empty proto polc + if e.IsAbsent() { + return plc, nil + } + + if e.Votes == nil { + return nil, errors.New("polc is not absent but has no votes") + } for i, v := range e.Votes { pb := v.ToProto() if pb != nil { @@ -1282,12 +1374,105 @@ func (e *ProofOfLockChange) ToProto() (*tmproto.ProofOfLockChange, error) { return plc, nil } +// AmnesiaEvidence is the progression of PotentialAmnesiaEvidence and is used to prove an infringement of the +// Tendermint consensus when a validator incorrectly sends a vote in a later round without correctly changing the lock +type AmnesiaEvidence struct { + PotentialAmnesiaEvidence + Polc ProofOfLockChange +} + +// Height, Time, Address and Verify functions are all inherited by the PotentialAmnesiaEvidence struct +var _ Evidence = &AmnesiaEvidence{} +var _ Evidence = AmnesiaEvidence{} + +func MakeAmnesiaEvidence(pe PotentialAmnesiaEvidence, proof ProofOfLockChange) AmnesiaEvidence { + return AmnesiaEvidence{ + pe, + proof, + } +} + +func (e AmnesiaEvidence) Equal(ev Evidence) bool { + e2, ok := ev.(AmnesiaEvidence) + if !ok { + return false + } + return e.PotentialAmnesiaEvidence.Equal(e2.PotentialAmnesiaEvidence) +} + +func (e AmnesiaEvidence) ValidateBasic() error { + if err := e.PotentialAmnesiaEvidence.ValidateBasic(); err != nil { + return fmt.Errorf("invalid potential amnesia evidence: %w", err) + } + if !e.Polc.IsAbsent() { + if err := e.Polc.ValidateBasic(); err != nil { + return fmt.Errorf("invalid proof of lock change: %w", err) + } + + if !bytes.Equal(e.PotentialAmnesiaEvidence.Address(), e.Polc.Address()) { + return fmt.Errorf("validator addresses do not match (%X - %X)", e.PotentialAmnesiaEvidence.Address(), + e.Polc.Address()) + } + + if e.PotentialAmnesiaEvidence.Height() != e.Polc.Height() { + return fmt.Errorf("heights do not match (%d - %d)", e.PotentialAmnesiaEvidence.Height(), + e.Polc.Height()) + } + + if e.Polc.Round() <= e.VoteA.Round || e.Polc.Round() > e.VoteB.Round { + return fmt.Errorf("polc must be between %d and %d (inclusive)", e.VoteA.Round+1, e.VoteB.Round) + } + + if !e.Polc.BlockID().Equals(e.PotentialAmnesiaEvidence.VoteB.BlockID) && !e.Polc.BlockID().IsZero() { + return fmt.Errorf("polc must be either for a nil block or for the same block as the second vote: %v != %v", + e.Polc.BlockID(), e.PotentialAmnesiaEvidence.VoteB.BlockID) + } + + if e.Polc.Time().After(e.PotentialAmnesiaEvidence.VoteB.Timestamp) { + return fmt.Errorf("validator voted again before receiving a majority of votes for the new block: %v is after %v", + e.Polc.Time(), e.PotentialAmnesiaEvidence.VoteB.Timestamp) + } + } + return nil +} + +// ViolatedConsensus assess on the basis of the AmensiaEvidence whether the validator has violated the +// Tendermint consensus. Evidence must be validated first (see ValidateBasic). +// We are only interested in proving that the latter of the votes in terms of time was correctly done. +func (e AmnesiaEvidence) ViolatedConsensus() (bool, string) { + // a validator having voted cannot go back and vote on an earlier round + if e.PotentialAmnesiaEvidence.VoteA.Round > e.PotentialAmnesiaEvidence.VoteB.Round { + return true, "validator went back and voted on a previous round" + } + + // if empty, then no proof was provided to defend the validators actions + if e.Polc.IsAbsent() { + return true, "no proof of lock was provided" + } + + return false, "" +} + +func (e AmnesiaEvidence) String() string { + return fmt.Sprintf("AmnesiaEvidence{ %v, polc: %v }", e.PotentialAmnesiaEvidence, e.Polc) +} + func ProofOfLockChangeFromProto(pb *tmproto.ProofOfLockChange) (*ProofOfLockChange, error) { if pb == nil { return nil, errors.New("nil proof of lock change") } plc := new(ProofOfLockChange) + + // check if it is an empty polc + if pb.PubKey == nil && pb.Votes == nil { + return plc, nil + } + + if pb.Votes == nil { + return nil, errors.New("proofOfLockChange: is not absent but has no votes") + } + vpb := make([]Vote, len(pb.Votes)) for i, v := range pb.Votes { vi, err := VoteFromProto(v) @@ -1298,7 +1483,7 @@ func ProofOfLockChangeFromProto(pb *tmproto.ProofOfLockChange) (*ProofOfLockChan } if pb.PubKey == nil { - return nil, errors.New("proofOfLockChange: nil PubKey") + return nil, errors.New("proofOfLockChange: is not abest but has nil PubKey") } pk, err := cryptoenc.PubKeyFromProto(*pb.PubKey) if err != nil { @@ -1311,6 +1496,54 @@ func ProofOfLockChangeFromProto(pb *tmproto.ProofOfLockChange) (*ProofOfLockChan return plc, nil } +func PotentialAmnesiaEvidenceFromProto(pb *tmproto.PotentialAmnesiaEvidence) (*PotentialAmnesiaEvidence, error) { + voteA, err := VoteFromProto(pb.GetVoteA()) + if err != nil { + return nil, err + } + + voteB, err := VoteFromProto(pb.GetVoteB()) + if err != nil { + return nil, err + } + tp := PotentialAmnesiaEvidence{ + VoteA: voteA, + VoteB: voteB, + HeightStamp: pb.GetHeightStamp(), + } + + return &tp, tp.ValidateBasic() +} + +func AmnesiaEvidenceToProto(evi AmnesiaEvidence) (*tmproto.Evidence, error) { + ev, err := EvidenceToProto(evi.PotentialAmnesiaEvidence) + if err != nil { + return nil, err + } + + paepb := ev.GetPotentialAmnesiaEvidence() + if paepb == nil { + return nil, errors.New("provided evidence is not potential amnesia evidence") + } + + polc, err := evi.Polc.ToProto() + if err != nil { + return nil, err + } + + tp := &tmproto.Evidence{ + Sum: &tmproto.Evidence_AmnesiaEvidence{ + AmnesiaEvidence: &tmproto.AmnesiaEvidence{ + PotentialAmnesiaEvidence: paepb, + Polc: polc, + }, + }, + } + + return tp, nil + +} + //----------------------------------------------------------------- // UNSTABLE diff --git a/types/evidence_test.go b/types/evidence_test.go index 6f4488346..d26919b59 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -22,27 +22,6 @@ type voteData struct { var defaultVoteTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) -func makeVote( - t *testing.T, val PrivValidator, chainID string, valIndex int32, height int64, round int32, step int, blockID BlockID, - time time.Time) *Vote { - pubKey, err := val.GetPubKey() - require.NoError(t, err) - v := &Vote{ - ValidatorAddress: pubKey.Address(), - ValidatorIndex: valIndex, - Height: height, - Round: round, - Type: tmproto.SignedMsgType(step), - Timestamp: time, - BlockID: blockID, - } - err = val.SignVote(chainID, v) - if err != nil { - panic(err) - } - return v -} - func TestEvidence(t *testing.T) { val := NewMockPV() val2 := NewMockPV() @@ -368,8 +347,8 @@ func TestPotentialAmnesiaEvidence(t *testing.T) { ) ev := &PotentialAmnesiaEvidence{ - VoteA: vote2, - VoteB: vote1, + VoteA: vote1, + VoteB: vote2, } assert.Equal(t, height, ev.Height()) @@ -391,7 +370,7 @@ func TestPotentialAmnesiaEvidence(t *testing.T) { func TestProofOfLockChange(t *testing.T) { const ( - chainID = "TestProofOfLockChange" + chainID = "test_chain_id" height int64 = 37 ) // 1: valid POLC - nothing should fail @@ -402,9 +381,21 @@ func TestProofOfLockChange(t *testing.T) { assert.Equal(t, height, polc.Height()) assert.NoError(t, polc.ValidateBasic()) - assert.True(t, polc.MajorityOfVotes(valSet)) + assert.NoError(t, polc.ValidateVotes(valSet, chainID)) assert.NotEmpty(t, polc.String()) + // tamper with one of the votes + polc.Votes[0].Timestamp = time.Now().Add(1 * time.Second) + err = polc.ValidateVotes(valSet, chainID) + t.Log(err) + assert.Error(t, err) + + // remove a vote such that majority wasn't reached + polc.Votes = polc.Votes[1:] + err = polc.ValidateVotes(valSet, chainID) + t.Log(err) + assert.Error(t, err) + // test validate basic on a set of bad cases var badPOLCs []ProofOfLockChange // 2: node has already voted in next round @@ -438,6 +429,7 @@ func TestProofOfLockChange(t *testing.T) { for idx, polc := range badPOLCs { err := polc.ValidateBasic() + t.Logf("case: %d: %v", idx+2, err) assert.Error(t, err) if err == nil { t.Errorf("test no. %d failed", idx+2) @@ -446,6 +438,117 @@ func TestProofOfLockChange(t *testing.T) { } +func TestAmnesiaEvidence(t *testing.T) { + const ( + chainID = "test_chain_id" + height int64 = 37 + ) + + voteSet, valSet, privValidators, blockID := buildVoteSet(height, 1, 2, 7, 0, tmproto.PrecommitType) + + var ( + val = privValidators[7] + pubKey, _ = val.GetPubKey() + blockID2 = makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + vote1 = makeVote(t, val, chainID, 7, height, 0, 2, blockID2, time.Now()) + vote2 = makeVote(t, val, chainID, 7, height, 1, 2, blockID, + time.Now().Add(time.Second)) + vote3 = makeVote(t, val, chainID, 7, height, 2, 2, blockID2, time.Now()) + polc = makePOLCFromVoteSet(voteSet, pubKey, blockID) + ) + + require.False(t, polc.IsAbsent()) + + pe := PotentialAmnesiaEvidence{ + VoteA: vote1, + VoteB: vote2, + } + + emptyAmnesiaEvidence := MakeAmnesiaEvidence(pe, EmptyPOLC()) + + assert.NoError(t, emptyAmnesiaEvidence.ValidateBasic()) + violated, reason := emptyAmnesiaEvidence.ViolatedConsensus() + if assert.True(t, violated) { + assert.Equal(t, reason, "no proof of lock was provided") + } + assert.NoError(t, emptyAmnesiaEvidence.Verify(chainID, pubKey)) + + completeAmnesiaEvidence := MakeAmnesiaEvidence(pe, polc) + + assert.NoError(t, completeAmnesiaEvidence.ValidateBasic()) + violated, reason = completeAmnesiaEvidence.ViolatedConsensus() + if !assert.False(t, violated) { + t.Log(reason) + } + assert.NoError(t, completeAmnesiaEvidence.Verify(chainID, pubKey)) + assert.NoError(t, completeAmnesiaEvidence.Polc.ValidateVotes(valSet, chainID)) + + assert.True(t, completeAmnesiaEvidence.Equal(emptyAmnesiaEvidence)) + assert.NotEmpty(t, completeAmnesiaEvidence.Hash()) + assert.NotEmpty(t, completeAmnesiaEvidence.Bytes()) + + pe2 := PotentialAmnesiaEvidence{ + VoteA: vote3, + VoteB: vote2, + } + + // validator has incorrectly voted for a previous round after voting for a later round + ae := MakeAmnesiaEvidence(pe2, EmptyPOLC()) + assert.NoError(t, ae.ValidateBasic()) + violated, reason = ae.ViolatedConsensus() + if assert.True(t, violated) { + assert.Equal(t, reason, "validator went back and voted on a previous round") + } + + var badAE []AmnesiaEvidence + // 1) Polc is at an incorrect height + voteSet, _, _ = buildVoteSetForBlock(height+1, 1, 2, 7, 0, tmproto.PrecommitType, blockID) + polc = makePOLCFromVoteSet(voteSet, pubKey, blockID) + badAE = append(badAE, MakeAmnesiaEvidence(pe, polc)) + // 2) Polc is of a later round + voteSet, _, _ = buildVoteSetForBlock(height, 2, 2, 7, 0, tmproto.PrecommitType, blockID) + polc = makePOLCFromVoteSet(voteSet, pubKey, blockID) + badAE = append(badAE, MakeAmnesiaEvidence(pe, polc)) + // 3) Polc has a different public key + voteSet, _, privValidators = buildVoteSetForBlock(height, 1, 2, 7, 0, tmproto.PrecommitType, blockID) + pubKey2, _ := privValidators[7].GetPubKey() + polc = makePOLCFromVoteSet(voteSet, pubKey2, blockID) + badAE = append(badAE, MakeAmnesiaEvidence(pe, polc)) + // 4) Polc has a different block ID + voteSet, _, _, blockID = buildVoteSet(height, 1, 2, 7, 0, tmproto.PrecommitType) + polc = makePOLCFromVoteSet(voteSet, pubKey, blockID) + badAE = append(badAE, MakeAmnesiaEvidence(pe, polc)) + + for idx, ae := range badAE { + t.Log(ae.ValidateBasic()) + if !assert.Error(t, ae.ValidateBasic()) { + t.Errorf("test no. %d failed", idx+1) + } + } + +} + +func makeVote( + t *testing.T, val PrivValidator, chainID string, valIndex int32, height int64, round int32, step int, blockID BlockID, + time time.Time) *Vote { + pubKey, err := val.GetPubKey() + require.NoError(t, err) + v := &Vote{ + ValidatorAddress: pubKey.Address(), + ValidatorIndex: valIndex, + Height: height, + Round: round, + Type: tmproto.SignedMsgType(step), + BlockID: blockID, + Timestamp: time, + } + err = val.SignVote(chainID, v) + if err != nil { + panic(err) + } + return v +} + func makeHeaderRandom() *Header { return &Header{ ChainID: tmrand.Str(12), @@ -591,24 +694,25 @@ func TestProofOfLockChangeProtoBuf(t *testing.T) { expErr2 bool }{ {"failure, empty key", ProofOfLockChange{Votes: []Vote{*v, *v2}}, true, true}, - {"failure empty ProofOfLockChange", ProofOfLockChange{}, true, true}, + {"failure, empty votes", ProofOfLockChange{PubKey: val3.PrivKey.PubKey()}, true, true}, + {"success empty ProofOfLockChange", EmptyPOLC(), false, false}, {"success", ProofOfLockChange{Votes: []Vote{*v, *v2}, PubKey: val3.PrivKey.PubKey()}, false, false}, } for _, tc := range testCases { tc := tc pbpolc, err := tc.polc.ToProto() if tc.expErr { - require.Error(t, err) + assert.Error(t, err, tc.msg) } else { - require.NoError(t, err) + assert.NoError(t, err, tc.msg) } c, err := ProofOfLockChangeFromProto(pbpolc) if !tc.expErr2 { - require.NoError(t, err, tc.msg) - require.Equal(t, &tc.polc, c, tc.msg) + assert.NoError(t, err, tc.msg) + assert.Equal(t, &tc.polc, c, tc.msg) } else { - require.Error(t, err, tc.msg) + assert.Error(t, err, tc.msg) } } } diff --git a/types/params.go b/types/params.go index e384435a4..022fd9561 100644 --- a/types/params.go +++ b/types/params.go @@ -42,12 +42,13 @@ func DefaultBlockParams() tmproto.BlockParams { } } -// DefaultEvidenceParams Params returns a default EvidenceParams. +// DefaultEvidenceParams returns a default EvidenceParams. func DefaultEvidenceParams() tmproto.EvidenceParams { return tmproto.EvidenceParams{ - MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s - MaxAgeDuration: 48 * time.Hour, - MaxNum: 50, + MaxAgeNumBlocks: 100000, // 27.8 hrs at 1block/s + MaxAgeDuration: 48 * time.Hour, + MaxNum: 50, + ProofTrialPeriod: 50000, // half MaxAgeNumBlocks } } @@ -110,6 +111,16 @@ func ValidateConsensusParams(params tmproto.ConsensusParams) error { int64(params.Evidence.MaxNum)*MaxEvidenceBytes, params.Block.MaxBytes) } + if params.Evidence.ProofTrialPeriod <= 0 { + return fmt.Errorf("evidenceParams.ProofTrialPeriod must be grater than 0 if provided, Got %v", + params.Evidence.ProofTrialPeriod) + } + + if params.Evidence.ProofTrialPeriod >= params.Evidence.MaxAgeNumBlocks { + return fmt.Errorf("evidenceParams.ProofTrialPeriod must be smaller than evidenceParams.MaxAgeNumBlocks, %d > %d", + params.Evidence.ProofTrialPeriod, params.Evidence.MaxAgeDuration) + } + if len(params.Validator.PubKeyTypes) == 0 { return errors.New("len(Validator.PubKeyTypes) must be greater than 0") } diff --git a/types/params_test.go b/types/params_test.go index c2e14b191..943ca8d55 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -23,24 +23,24 @@ func TestConsensusParamsValidation(t *testing.T) { valid bool }{ // test block params - 0: {makeParams(1, 0, 10, 1, 0, valEd25519), true}, - 1: {makeParams(0, 0, 10, 1, 0, valEd25519), false}, - 2: {makeParams(47*1024*1024, 0, 10, 1, 0, valEd25519), true}, - 3: {makeParams(10, 0, 10, 1, 0, valEd25519), true}, - 4: {makeParams(100*1024*1024, 0, 10, 1, 0, valEd25519), true}, - 5: {makeParams(101*1024*1024, 0, 10, 1, 0, valEd25519), false}, - 6: {makeParams(1024*1024*1024, 0, 10, 1, 0, valEd25519), false}, + 0: {makeParams(1, 0, 10, 2, 0, valEd25519), true}, + 1: {makeParams(0, 0, 10, 2, 0, valEd25519), false}, + 2: {makeParams(47*1024*1024, 0, 10, 2, 0, valEd25519), true}, + 3: {makeParams(10, 0, 10, 2, 0, valEd25519), true}, + 4: {makeParams(100*1024*1024, 0, 10, 2, 0, valEd25519), true}, + 5: {makeParams(101*1024*1024, 0, 10, 2, 0, valEd25519), false}, + 6: {makeParams(1024*1024*1024, 0, 10, 2, 0, valEd25519), false}, 7: {makeParams(1024*1024*1024, 0, 10, -1, 0, valEd25519), false}, - 8: {makeParams(1, 0, -10, 1, 0, valEd25519), false}, + 8: {makeParams(1, 0, -10, 2, 0, valEd25519), false}, // test evidence params 9: {makeParams(1, 0, 10, 0, 0, valEd25519), false}, - 10: {makeParams(1, 0, 10, 1, 1, valEd25519), false}, - 11: {makeParams(1000, 0, 10, 1, 1, valEd25519), true}, + 10: {makeParams(1, 0, 10, 2, 1, valEd25519), false}, + 11: {makeParams(1000, 0, 10, 2, 1, valEd25519), true}, 12: {makeParams(1, 0, 10, -1, 0, valEd25519), false}, // test no pubkey type provided - 13: {makeParams(1, 0, 10, 1, 0, []string{}), false}, + 13: {makeParams(1, 0, 10, 2, 0, []string{}), false}, // test invalid pubkey type provided - 14: {makeParams(1, 0, 10, 1, 0, []string{"potatoes make good pubkeys"}), false}, + 14: {makeParams(1, 0, 10, 2, 0, []string{"potatoes make good pubkeys"}), false}, } for i, tc := range testCases { if tc.valid { @@ -65,9 +65,10 @@ func makeParams( TimeIotaMs: blockTimeIotaMs, }, Evidence: tmproto.EvidenceParams{ - MaxAgeNumBlocks: evidenceAge, - MaxAgeDuration: time.Duration(evidenceAge), - MaxNum: maxEvidence, + MaxAgeNumBlocks: evidenceAge, + MaxAgeDuration: time.Duration(evidenceAge), + MaxNum: maxEvidence, + ProofTrialPeriod: 1, }, Validator: tmproto.ValidatorParams{ PubKeyTypes: pubkeyTypes, diff --git a/types/priv_validator.go b/types/priv_validator.go index 3d8e72bba..de1407150 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -100,6 +100,15 @@ func (pv MockPV) SignProposal(chainID string, proposal *Proposal) error { return nil } +func (pv MockPV) ExtractIntoValidator(votingPower int64) *Validator { + pubKey, _ := pv.GetPubKey() + return &Validator{ + Address: pubKey.Address(), + PubKey: pubKey, + VotingPower: votingPower, + } +} + // String returns a string representation of the MockPV. func (pv MockPV) String() string { mpv, _ := pv.GetPubKey() // mockPV will never return an error, ignored here diff --git a/types/validator_set.go b/types/validator_set.go index cf04df6dd..1f56faaac 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -856,6 +856,9 @@ func (vals *ValidatorSet) ToProto() (*tmproto.ValidatorSet, error) { if vals == nil { return nil, errors.New("nil validator set") // validator set should never be nil } + if err := vals.ValidateBasic(); err != nil { + return nil, fmt.Errorf("validator set failed basic: %w", err) + } vp := new(tmproto.ValidatorSet) valsProto := make([]*tmproto.Validator, len(vals.Validators)) for i := 0; i < len(vals.Validators); i++ { diff --git a/types/vote_set_test.go b/types/vote_set_test.go index d87300bdc..63b61e81b 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -598,12 +598,21 @@ func TestMakeCommit(t *testing.T) { } func buildVoteSet( - height int64, + height int64, round int32, nonVotes, nonNilVotes, nilVotes int, + voteType tmproto.SignedMsgType) (voteSet *VoteSet, valSet *ValidatorSet, + privValidators []PrivValidator, blockID BlockID) { + + blockID = makeBlockIDRandom() + voteSet, valSet, privValidators = buildVoteSetForBlock(height, round, nonVotes, nonNilVotes, nilVotes, voteType, + blockID) + return +} + +func buildVoteSetForBlock(height int64, round int32, nonVotes, nonNilVotes, nilVotes int, - voteType tmproto.SignedMsgType) (*VoteSet, *ValidatorSet, []PrivValidator, BlockID) { + voteType tmproto.SignedMsgType, blockID BlockID) (*VoteSet, *ValidatorSet, []PrivValidator) { valSize := nonVotes + nilVotes + nonNilVotes voteSet, valSet, privValidators := randVoteSet(height, round, voteType, valSize, 1) - blockID := makeBlockIDRandom() voteProto := &Vote{ ValidatorAddress: nil, ValidatorIndex: -1, @@ -625,5 +634,5 @@ func buildVoteSet( vote := withValidator(voteProto, addr, int32(i)) _, _ = signAddVote(privValidators[i], withBlockHash(vote, nil), voteSet) } - return voteSet, valSet, privValidators, blockID + return voteSet, valSet, privValidators } From d54de61bf655c8a3e9312c4c42e3ce73cf1f42bf Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 10 Jun 2020 14:08:47 +0200 Subject: [PATCH 05/12] consensus: proto migration (#4984) ## Description migrate consensus to protobuf Closes: #XXX --- consensus/byzantine_test.go | 8 +- consensus/codec.go | 15 -- consensus/msgs.go | 377 ++++++++++++++++++++++++++++ consensus/msgs_test.go | 312 +++++++++++++++++++++++ consensus/reactor.go | 56 ++--- consensus/reactor_test.go | 9 +- consensus/replay_stubs.go | 2 +- consensus/replay_test.go | 9 +- consensus/state.go | 4 +- consensus/types/codec.go | 13 - consensus/types/peer_round_state.go | 28 --- consensus/types/round_state.go | 28 --- consensus/types/round_state_test.go | 1 + consensus/wal.go | 56 +++-- consensus/wal_test.go | 7 +- crypto/merkle/simple_proof_test.go | 35 +++ crypto/merkle/simple_tree_test.go | 2 +- libs/math/safemath.go | 12 + proto/consensus/msgs.pb.go | 114 ++++----- proto/consensus/msgs.proto | 2 +- 20 files changed, 873 insertions(+), 217 deletions(-) delete mode 100644 consensus/codec.go create mode 100644 consensus/msgs.go create mode 100644 consensus/msgs_test.go delete mode 100644 consensus/types/codec.go diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index 4b52f99fe..a9adf0baa 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -219,7 +219,7 @@ func sendProposalAndParts( ) { // proposal msg := &ProposalMessage{Proposal: proposal} - peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) + peer.Send(DataChannel, MustEncode(msg)) // parts for i := 0; i < int(parts.Total()); i++ { @@ -229,7 +229,7 @@ func sendProposalAndParts( Round: round, // This tells peer that this part applies to us. Part: part, } - peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) + peer.Send(DataChannel, MustEncode(msg)) } // votes @@ -238,8 +238,8 @@ func sendProposalAndParts( precommit, _ := cs.signVote(tmproto.PrecommitType, blockHash, parts.Header()) cs.mtx.Unlock() - peer.Send(VoteChannel, cdc.MustMarshalBinaryBare(&VoteMessage{prevote})) - peer.Send(VoteChannel, cdc.MustMarshalBinaryBare(&VoteMessage{precommit})) + peer.Send(VoteChannel, MustEncode(&VoteMessage{prevote})) + peer.Send(VoteChannel, MustEncode(&VoteMessage{precommit})) } //---------------------------------------- diff --git a/consensus/codec.go b/consensus/codec.go deleted file mode 100644 index ae7dbaab2..000000000 --- a/consensus/codec.go +++ /dev/null @@ -1,15 +0,0 @@ -package consensus - -import ( - amino "github.com/tendermint/go-amino" - - "github.com/tendermint/tendermint/types" -) - -var cdc = amino.NewCodec() - -func init() { - RegisterMessages(cdc) - RegisterWALMessages(cdc) - types.RegisterBlockAmino(cdc) -} diff --git a/consensus/msgs.go b/consensus/msgs.go new file mode 100644 index 000000000..c218da6c8 --- /dev/null +++ b/consensus/msgs.go @@ -0,0 +1,377 @@ +package consensus + +import ( + "errors" + "fmt" + + "github.com/gogo/protobuf/proto" + + cstypes "github.com/tendermint/tendermint/consensus/types" + "github.com/tendermint/tendermint/libs/bits" + tmmath "github.com/tendermint/tendermint/libs/math" + "github.com/tendermint/tendermint/p2p" + tmcons "github.com/tendermint/tendermint/proto/consensus" + tmproto "github.com/tendermint/tendermint/proto/types" + "github.com/tendermint/tendermint/types" +) + +// MsgToProto takes a consensus message type and returns the proto defined consensus message +func MsgToProto(msg Message) (*tmcons.Message, error) { + if msg == nil { + return nil, errors.New("consensus: message is nil") + } + var pb tmcons.Message + + switch msg := msg.(type) { + case *NewRoundStepMessage: + pb = tmcons.Message{ + Sum: &tmcons.Message_NewRoundStep{ + NewRoundStep: &tmcons.NewRoundStep{ + Height: msg.Height, + Round: msg.Round, + Step: uint32(msg.Step), + SecondsSinceStartTime: msg.SecondsSinceStartTime, + LastCommitRound: msg.LastCommitRound, + }, + }, + } + case *NewValidBlockMessage: + pbPartsHeader := msg.BlockPartsHeader.ToProto() + pbBits := msg.BlockParts.ToProto() + pb = tmcons.Message{ + Sum: &tmcons.Message_NewValidBlock{ + NewValidBlock: &tmcons.NewValidBlock{ + Height: msg.Height, + Round: msg.Round, + BlockPartsHeader: pbPartsHeader, + BlockParts: pbBits, + IsCommit: msg.IsCommit, + }, + }, + } + case *ProposalMessage: + pbP := msg.Proposal.ToProto() + pb = tmcons.Message{ + Sum: &tmcons.Message_Proposal{ + Proposal: &tmcons.Proposal{ + Proposal: *pbP, + }, + }, + } + case *ProposalPOLMessage: + pbBits := msg.ProposalPOL.ToProto() + pb = tmcons.Message{ + Sum: &tmcons.Message_ProposalPol{ + ProposalPol: &tmcons.ProposalPOL{ + Height: msg.Height, + ProposalPolRound: msg.ProposalPOLRound, + ProposalPol: *pbBits, + }, + }, + } + case *BlockPartMessage: + parts, err := msg.Part.ToProto() + if err != nil { + return nil, fmt.Errorf("msg to proto error: %w", err) + } + pb = tmcons.Message{ + Sum: &tmcons.Message_BlockPart{ + BlockPart: &tmcons.BlockPart{ + Height: msg.Height, + Round: msg.Round, + Part: *parts, + }, + }, + } + case *VoteMessage: + vote := msg.Vote.ToProto() + pb = tmcons.Message{ + Sum: &tmcons.Message_Vote{ + Vote: &tmcons.Vote{ + Vote: vote, + }, + }, + } + case *HasVoteMessage: + pb = tmcons.Message{ + Sum: &tmcons.Message_HasVote{ + HasVote: &tmcons.HasVote{ + Height: msg.Height, + Round: msg.Round, + Type: msg.Type, + Index: msg.Index, + }, + }, + } + case *VoteSetMaj23Message: + bi := msg.BlockID.ToProto() + pb = tmcons.Message{ + Sum: &tmcons.Message_VoteSetMaj23{ + VoteSetMaj23: &tmcons.VoteSetMaj23{ + Height: msg.Height, + Round: msg.Round, + Type: msg.Type, + BlockID: bi, + }, + }, + } + case *VoteSetBitsMessage: + bi := msg.BlockID.ToProto() + bits := msg.Votes.ToProto() + + vsb := &tmcons.Message_VoteSetBits{ + VoteSetBits: &tmcons.VoteSetBits{ + Height: msg.Height, + Round: msg.Round, + Type: msg.Type, + BlockID: bi, + }, + } + + if bits != nil { + vsb.VoteSetBits.Votes = *bits + } + + pb = tmcons.Message{ + Sum: vsb, + } + + default: + return nil, fmt.Errorf("consensus: message not recognized: %T", msg) + } + + return &pb, nil +} + +// MsgFromProto takes a consensus proto message and returns the native go type +func MsgFromProto(msg *tmcons.Message) (Message, error) { + if msg == nil { + return nil, errors.New("consensus: nil message") + } + var pb Message + + switch msg := msg.Sum.(type) { + case *tmcons.Message_NewRoundStep: + rs, err := tmmath.SafeConvertUint8(int64(msg.NewRoundStep.Step)) + // deny message based on possible overflow + if err != nil { + return nil, fmt.Errorf("denying message due to possible overflow: %w", err) + } + pb = &NewRoundStepMessage{ + Height: msg.NewRoundStep.Height, + Round: msg.NewRoundStep.Round, + Step: cstypes.RoundStepType(rs), + SecondsSinceStartTime: msg.NewRoundStep.SecondsSinceStartTime, + LastCommitRound: msg.NewRoundStep.LastCommitRound, + } + case *tmcons.Message_NewValidBlock: + pbPartsHeader, err := types.PartSetHeaderFromProto(&msg.NewValidBlock.BlockPartsHeader) + if err != nil { + return nil, fmt.Errorf("parts to proto error: %w", err) + } + + pbBits := new(bits.BitArray) + pbBits.FromProto(msg.NewValidBlock.BlockParts) + + pb = &NewValidBlockMessage{ + Height: msg.NewValidBlock.Height, + Round: msg.NewValidBlock.Round, + BlockPartsHeader: *pbPartsHeader, + BlockParts: pbBits, + IsCommit: msg.NewValidBlock.IsCommit, + } + case *tmcons.Message_Proposal: + pbP, err := types.ProposalFromProto(&msg.Proposal.Proposal) + if err != nil { + return nil, fmt.Errorf("proposal msg to proto error: %w", err) + } + + pb = &ProposalMessage{ + Proposal: pbP, + } + case *tmcons.Message_ProposalPol: + pbBits := new(bits.BitArray) + pbBits.FromProto(&msg.ProposalPol.ProposalPol) + pb = &ProposalPOLMessage{ + Height: msg.ProposalPol.Height, + ProposalPOLRound: msg.ProposalPol.ProposalPolRound, + ProposalPOL: pbBits, + } + case *tmcons.Message_BlockPart: + parts, err := types.PartFromProto(&msg.BlockPart.Part) + if err != nil { + return nil, fmt.Errorf("blockpart msg to proto error: %w", err) + } + pb = &BlockPartMessage{ + Height: msg.BlockPart.Height, + Round: msg.BlockPart.Round, + Part: parts, + } + case *tmcons.Message_Vote: + vote, err := types.VoteFromProto(msg.Vote.Vote) + if err != nil { + return nil, fmt.Errorf("vote msg to proto error: %w", err) + } + + pb = &VoteMessage{ + Vote: vote, + } + case *tmcons.Message_HasVote: + pb = &HasVoteMessage{ + Height: msg.HasVote.Height, + Round: msg.HasVote.Round, + Type: msg.HasVote.Type, + Index: msg.HasVote.Index, + } + case *tmcons.Message_VoteSetMaj23: + bi, err := types.BlockIDFromProto(&msg.VoteSetMaj23.BlockID) + if err != nil { + return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err) + } + pb = &VoteSetMaj23Message{ + Height: msg.VoteSetMaj23.Height, + Round: msg.VoteSetMaj23.Round, + Type: msg.VoteSetMaj23.Type, + BlockID: *bi, + } + case *tmcons.Message_VoteSetBits: + bi, err := types.BlockIDFromProto(&msg.VoteSetBits.BlockID) + if err != nil { + return nil, fmt.Errorf("voteSetBits msg to proto error: %w", err) + } + bits := new(bits.BitArray) + bits.FromProto(&msg.VoteSetBits.Votes) + + pb = &VoteSetBitsMessage{ + Height: msg.VoteSetBits.Height, + Round: msg.VoteSetBits.Round, + Type: msg.VoteSetBits.Type, + BlockID: *bi, + Votes: bits, + } + default: + return nil, fmt.Errorf("consensus: message not recognized: %T", msg) + } + + if err := pb.ValidateBasic(); err != nil { + return nil, err + } + + return pb, nil +} + +// MustEncode takes the reactors msg, makes it proto and marshals it +// this mimics `MustMarshalBinaryBare` in that is panics on error +func MustEncode(msg Message) []byte { + pb, err := MsgToProto(msg) + if err != nil { + panic(err) + } + enc, err := proto.Marshal(pb) + if err != nil { + panic(err) + } + return enc +} + +// WALToProto takes a WAL message and return a proto walMessage and error +func WALToProto(msg WALMessage) (*tmcons.WALMessage, error) { + var pb tmcons.WALMessage + + switch msg := msg.(type) { + case types.EventDataRoundState: + pb = tmcons.WALMessage{ + Sum: &tmcons.WALMessage_EventDataRoundState{ + EventDataRoundState: &tmproto.EventDataRoundState{ + Height: msg.Height, + Round: msg.Round, + Step: msg.Step, + }, + }, + } + case msgInfo: + consMsg, err := MsgToProto(msg.Msg) + if err != nil { + return nil, err + } + pb = tmcons.WALMessage{ + Sum: &tmcons.WALMessage_MsgInfo{ + MsgInfo: &tmcons.MsgInfo{ + Msg: *consMsg, + PeerID: string(msg.PeerID), + }, + }, + } + case timeoutInfo: + pb = tmcons.WALMessage{ + Sum: &tmcons.WALMessage_TimeoutInfo{ + TimeoutInfo: &tmcons.TimeoutInfo{ + Duration: msg.Duration, + Height: msg.Height, + Round: msg.Round, + Step: uint32(msg.Step), + }, + }, + } + case EndHeightMessage: + pb = tmcons.WALMessage{ + Sum: &tmcons.WALMessage_EndHeight{ + EndHeight: &tmcons.EndHeight{ + Height: msg.Height, + }, + }, + } + default: + return nil, fmt.Errorf("to proto: wal message not recognized: %T", msg) + } + + return &pb, nil +} + +// WALFromProto takes a proto wal message and return a consensus walMessage and error +func WALFromProto(msg *tmcons.WALMessage) (WALMessage, error) { + if msg == nil { + return nil, errors.New("nil WAL message") + } + var pb WALMessage + + switch msg := msg.Sum.(type) { + case *tmcons.WALMessage_EventDataRoundState: + pb = types.EventDataRoundState{ + Height: msg.EventDataRoundState.Height, + Round: msg.EventDataRoundState.Round, + Step: msg.EventDataRoundState.Step, + } + case *tmcons.WALMessage_MsgInfo: + walMsg, err := MsgFromProto(&msg.MsgInfo.Msg) + if err != nil { + return nil, fmt.Errorf("msgInfo from proto error: %w", err) + } + pb = msgInfo{ + Msg: walMsg, + PeerID: p2p.ID(msg.MsgInfo.PeerID), + } + + case *tmcons.WALMessage_TimeoutInfo: + tis, err := tmmath.SafeConvertUint8(int64(msg.TimeoutInfo.Step)) + // deny message based on possible overflow + if err != nil { + return nil, fmt.Errorf("denying message due to possible overflow: %w", err) + } + pb = timeoutInfo{ + Duration: msg.TimeoutInfo.Duration, + Height: msg.TimeoutInfo.Height, + Round: msg.TimeoutInfo.Round, + Step: cstypes.RoundStepType(tis), + } + return pb, nil + case *tmcons.WALMessage_EndHeight: + pb := EndHeightMessage{ + Height: msg.EndHeight.Height, + } + return pb, nil + default: + return nil, fmt.Errorf("from proto: wal message not recognized: %T", msg) + } + return pb, nil +} diff --git a/consensus/msgs_test.go b/consensus/msgs_test.go new file mode 100644 index 000000000..c652a82a9 --- /dev/null +++ b/consensus/msgs_test.go @@ -0,0 +1,312 @@ +package consensus + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/libs/bits" + tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/p2p" + tmcons "github.com/tendermint/tendermint/proto/consensus" + tmproto "github.com/tendermint/tendermint/proto/types" + "github.com/tendermint/tendermint/types" +) + +func TestMsgToProto(t *testing.T) { + psh := types.PartSetHeader{ + Total: 1, + Hash: tmrand.Bytes(32), + } + pbPsh := psh.ToProto() + bi := types.BlockID{ + Hash: tmrand.Bytes(32), + PartsHeader: psh, + } + pbBi := bi.ToProto() + bits := bits.NewBitArray(1) + pbBits := bits.ToProto() + + parts := types.Part{ + Index: 1, + Bytes: []byte("test"), + Proof: merkle.SimpleProof{ + Total: 1, + Index: 1, + LeafHash: tmrand.Bytes(32), + Aunts: [][]byte{}, + }, + } + pbParts, err := parts.ToProto() + require.NoError(t, err) + + proposal := types.Proposal{ + Type: tmproto.ProposalType, + Height: 1, + Round: 1, + POLRound: 1, + BlockID: bi, + Timestamp: time.Now(), + Signature: tmrand.Bytes(20), + } + pbProposal := proposal.ToProto() + + pv := types.NewMockPV() + pk, err := pv.GetPubKey() + require.NoError(t, err) + val := types.NewValidator(pk, 100) + + vote, err := types.MakeVote( + 1, types.BlockID{}, &types.ValidatorSet{Proposer: val, Validators: []*types.Validator{val}}, + pv, "chainID", time.Now()) + require.NoError(t, err) + pbVote := vote.ToProto() + + testsCases := []struct { + testName string + msg Message + want *tmcons.Message + wantErr bool + }{ + {"successful NewRoundStepMessage", &NewRoundStepMessage{ + Height: 2, + Round: 1, + Step: 1, + SecondsSinceStartTime: 1, + LastCommitRound: 2, + }, &tmcons.Message{ + Sum: &tmcons.Message_NewRoundStep{ + NewRoundStep: &tmcons.NewRoundStep{ + Height: 2, + Round: 1, + Step: 1, + SecondsSinceStartTime: 1, + LastCommitRound: 2, + }, + }, + }, false}, + + {"successful NewValidBlockMessage", &NewValidBlockMessage{ + Height: 1, + Round: 1, + BlockPartsHeader: psh, + BlockParts: bits, + IsCommit: false, + }, &tmcons.Message{ + Sum: &tmcons.Message_NewValidBlock{ + NewValidBlock: &tmcons.NewValidBlock{ + Height: 1, + Round: 1, + BlockPartsHeader: pbPsh, + BlockParts: pbBits, + IsCommit: false, + }, + }, + }, false}, + {"successful BlockPartMessage", &BlockPartMessage{ + Height: 100, + Round: 1, + Part: &parts, + }, &tmcons.Message{ + Sum: &tmcons.Message_BlockPart{ + BlockPart: &tmcons.BlockPart{ + Height: 100, + Round: 1, + Part: *pbParts, + }, + }, + }, false}, + {"successful ProposalPOLMessage", &ProposalPOLMessage{ + Height: 1, + ProposalPOLRound: 1, + ProposalPOL: bits, + }, &tmcons.Message{ + Sum: &tmcons.Message_ProposalPol{ + ProposalPol: &tmcons.ProposalPOL{ + Height: 1, + ProposalPolRound: 1, + ProposalPol: *pbBits, + }, + }}, false}, + {"successful ProposalMessage", &ProposalMessage{ + Proposal: &proposal, + }, &tmcons.Message{ + Sum: &tmcons.Message_Proposal{ + Proposal: &tmcons.Proposal{ + Proposal: *pbProposal, + }, + }, + }, false}, + {"successful VoteMessage", &VoteMessage{ + Vote: vote, + }, &tmcons.Message{ + Sum: &tmcons.Message_Vote{ + Vote: &tmcons.Vote{ + Vote: pbVote, + }, + }, + }, false}, + {"successful VoteSetMaj23", &VoteSetMaj23Message{ + Height: 1, + Round: 1, + Type: 1, + BlockID: bi, + }, &tmcons.Message{ + Sum: &tmcons.Message_VoteSetMaj23{ + VoteSetMaj23: &tmcons.VoteSetMaj23{ + Height: 1, + Round: 1, + Type: 1, + BlockID: pbBi, + }, + }, + }, false}, + {"successful VoteSetBits", &VoteSetBitsMessage{ + Height: 1, + Round: 1, + Type: 1, + BlockID: bi, + Votes: bits, + }, &tmcons.Message{ + Sum: &tmcons.Message_VoteSetBits{ + VoteSetBits: &tmcons.VoteSetBits{ + Height: 1, + Round: 1, + Type: 1, + BlockID: pbBi, + Votes: *pbBits, + }, + }, + }, false}, + {"failure", nil, &tmcons.Message{}, true}, + } + for _, tt := range testsCases { + tt := tt + t.Run(tt.testName, func(t *testing.T) { + pb, err := MsgToProto(tt.msg) + if tt.wantErr == true { + assert.Equal(t, err != nil, tt.wantErr) + return + } + assert.EqualValues(t, tt.want, pb, tt.testName) + + msg, err := MsgFromProto(pb) + + if !tt.wantErr { + require.NoError(t, err) + bcm := assert.Equal(t, tt.msg, msg, tt.testName) + assert.True(t, bcm, tt.testName) + } else { + require.Error(t, err, tt.testName) + } + }) + } +} + +func TestWALMsgProto(t *testing.T) { + + parts := types.Part{ + Index: 1, + Bytes: []byte("test"), + Proof: merkle.SimpleProof{ + Total: 1, + Index: 1, + LeafHash: tmrand.Bytes(32), + Aunts: [][]byte{}, + }, + } + pbParts, err := parts.ToProto() + require.NoError(t, err) + + testsCases := []struct { + testName string + msg WALMessage + want *tmcons.WALMessage + wantErr bool + }{ + {"successful EventDataRoundState", types.EventDataRoundState{ + Height: 2, + Round: 1, + Step: "ronies", + }, &tmcons.WALMessage{ + Sum: &tmcons.WALMessage_EventDataRoundState{ + EventDataRoundState: &tmproto.EventDataRoundState{ + Height: 2, + Round: 1, + Step: "ronies", + }, + }, + }, false}, + {"successful msgInfo", msgInfo{ + Msg: &BlockPartMessage{ + Height: 100, + Round: 1, + Part: &parts, + }, + PeerID: p2p.ID("string"), + }, &tmcons.WALMessage{ + Sum: &tmcons.WALMessage_MsgInfo{ + MsgInfo: &tmcons.MsgInfo{ + Msg: tmcons.Message{ + Sum: &tmcons.Message_BlockPart{ + BlockPart: &tmcons.BlockPart{ + Height: 100, + Round: 1, + Part: *pbParts, + }, + }, + }, + PeerID: "string", + }, + }, + }, false}, + {"successful timeoutInfo", timeoutInfo{ + Duration: time.Duration(100), + Height: 1, + Round: 1, + Step: 1, + }, &tmcons.WALMessage{ + Sum: &tmcons.WALMessage_TimeoutInfo{ + TimeoutInfo: &tmcons.TimeoutInfo{ + Duration: time.Duration(100), + Height: 1, + Round: 1, + Step: 1, + }, + }, + }, false}, + {"successful EndHeightMessage", EndHeightMessage{ + Height: 1, + }, &tmcons.WALMessage{ + Sum: &tmcons.WALMessage_EndHeight{ + EndHeight: &tmcons.EndHeight{ + Height: 1, + }, + }, + }, false}, + {"failure", nil, &tmcons.WALMessage{}, true}, + } + for _, tt := range testsCases { + tt := tt + t.Run(tt.testName, func(t *testing.T) { + pb, err := WALToProto(tt.msg) + if tt.wantErr == true { + assert.Equal(t, err != nil, tt.wantErr) + return + } + assert.EqualValues(t, tt.want, pb, tt.testName) + + msg, err := WALFromProto(pb) + + if !tt.wantErr { + require.NoError(t, err) + assert.Equal(t, tt.msg, msg, tt.testName) // need the concrete type as WAL Message is a empty interface + } else { + require.Error(t, err, tt.testName) + } + }) + } +} diff --git a/consensus/reactor.go b/consensus/reactor.go index b427dcec6..b35d5e5f3 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -7,7 +7,7 @@ import ( "sync" "time" - amino "github.com/tendermint/go-amino" + "github.com/gogo/protobuf/proto" cstypes "github.com/tendermint/tendermint/consensus/types" "github.com/tendermint/tendermint/libs/bits" @@ -15,6 +15,7 @@ import ( tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/p2p" + tmcons "github.com/tendermint/tendermint/proto/consensus" tmproto "github.com/tendermint/tendermint/proto/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" @@ -277,7 +278,7 @@ func (conR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { default: panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?") } - src.TrySend(VoteSetBitsChannel, cdc.MustMarshalBinaryBare(&VoteSetBitsMessage{ + src.TrySend(VoteSetBitsChannel, MustEncode(&VoteSetBitsMessage{ Height: msg.Height, Round: msg.Round, Type: msg.Type, @@ -409,7 +410,7 @@ func (conR *Reactor) unsubscribeFromBroadcastEvents() { func (conR *Reactor) broadcastNewRoundStepMessage(rs *cstypes.RoundState) { nrsMsg := makeRoundStepMessage(rs) - conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) + conR.Switch.Broadcast(StateChannel, MustEncode(nrsMsg)) } func (conR *Reactor) broadcastNewValidBlockMessage(rs *cstypes.RoundState) { @@ -420,7 +421,7 @@ func (conR *Reactor) broadcastNewValidBlockMessage(rs *cstypes.RoundState) { BlockParts: rs.ProposalBlockParts.BitArray(), IsCommit: rs.Step == cstypes.RoundStepCommit, } - conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(csMsg)) + conR.Switch.Broadcast(StateChannel, MustEncode(csMsg)) } // Broadcasts HasVoteMessage to peers that care. @@ -431,7 +432,7 @@ func (conR *Reactor) broadcastHasVoteMessage(vote *types.Vote) { Type: vote.Type, Index: vote.ValidatorIndex, } - conR.Switch.Broadcast(StateChannel, cdc.MustMarshalBinaryBare(msg)) + conR.Switch.Broadcast(StateChannel, MustEncode(msg)) /* // TODO: Make this broadcast more selective. for _, peer := range conR.Switch.Peers().List() { @@ -457,7 +458,7 @@ func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) Height: rs.Height, Round: rs.Round, Step: rs.Step, - SecondsSinceStartTime: int(time.Since(rs.StartTime).Seconds()), + SecondsSinceStartTime: int64(time.Since(rs.StartTime).Seconds()), LastCommitRound: rs.LastCommit.GetRound(), } return @@ -466,7 +467,7 @@ func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *NewRoundStepMessage) func (conR *Reactor) sendNewRoundStepMessage(peer p2p.Peer) { rs := conR.conS.GetRoundState() nrsMsg := makeRoundStepMessage(rs) - peer.Send(StateChannel, cdc.MustMarshalBinaryBare(nrsMsg)) + peer.Send(StateChannel, MustEncode(nrsMsg)) } func (conR *Reactor) gossipDataRoutine(peer p2p.Peer, ps *PeerState) { @@ -492,7 +493,7 @@ OUTER_LOOP: Part: part, } logger.Debug("Sending block part", "height", prs.Height, "round", prs.Round) - if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) { + if peer.Send(DataChannel, MustEncode(msg)) { ps.SetHasProposalBlockPart(prs.Height, prs.Round, index) } continue OUTER_LOOP @@ -538,7 +539,7 @@ OUTER_LOOP: { msg := &ProposalMessage{Proposal: rs.Proposal} logger.Debug("Sending proposal", "height", prs.Height, "round", prs.Round) - if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) { + if peer.Send(DataChannel, MustEncode(msg)) { // NOTE[ZM]: A peer might have received different proposal msg so this Proposal msg will be rejected! ps.SetHasProposal(rs.Proposal) } @@ -554,7 +555,7 @@ OUTER_LOOP: ProposalPOL: rs.Votes.Prevotes(rs.Proposal.POLRound).BitArray(), } logger.Debug("Sending POL", "height", prs.Height, "round", prs.Round) - peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) + peer.Send(DataChannel, MustEncode(msg)) } continue OUTER_LOOP } @@ -597,7 +598,7 @@ func (conR *Reactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundSt Part: part, } logger.Debug("Sending block part for catchup", "round", prs.Round, "index", index) - if peer.Send(DataChannel, cdc.MustMarshalBinaryBare(msg)) { + if peer.Send(DataChannel, MustEncode(msg)) { ps.SetHasProposalBlockPart(prs.Height, prs.Round, index) } else { logger.Debug("Sending block part for catchup failed") @@ -757,7 +758,7 @@ OUTER_LOOP: prs := ps.GetRoundState() if rs.Height == prs.Height { if maj23, ok := rs.Votes.Prevotes(prs.Round).TwoThirdsMajority(); ok { - peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{ + peer.TrySend(StateChannel, MustEncode(&VoteSetMaj23Message{ Height: prs.Height, Round: prs.Round, Type: tmproto.PrevoteType, @@ -774,7 +775,7 @@ OUTER_LOOP: prs := ps.GetRoundState() if rs.Height == prs.Height { if maj23, ok := rs.Votes.Precommits(prs.Round).TwoThirdsMajority(); ok { - peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{ + peer.TrySend(StateChannel, MustEncode(&VoteSetMaj23Message{ Height: prs.Height, Round: prs.Round, Type: tmproto.PrecommitType, @@ -791,7 +792,7 @@ OUTER_LOOP: prs := ps.GetRoundState() if rs.Height == prs.Height && prs.ProposalPOLRound >= 0 { if maj23, ok := rs.Votes.Prevotes(prs.ProposalPOLRound).TwoThirdsMajority(); ok { - peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{ + peer.TrySend(StateChannel, MustEncode(&VoteSetMaj23Message{ Height: prs.Height, Round: prs.ProposalPOLRound, Type: tmproto.PrevoteType, @@ -811,7 +812,7 @@ OUTER_LOOP: if prs.CatchupCommitRound != -1 && prs.Height > 0 && prs.Height <= conR.conS.blockStore.Height() && prs.Height >= conR.conS.blockStore.Base() { if commit := conR.conS.LoadCommit(prs.Height); commit != nil { - peer.TrySend(StateChannel, cdc.MustMarshalBinaryBare(&VoteSetMaj23Message{ + peer.TrySend(StateChannel, MustEncode(&VoteSetMaj23Message{ Height: prs.Height, Round: commit.Round, Type: tmproto.PrecommitType, @@ -1032,7 +1033,7 @@ func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool { if vote, ok := ps.PickVoteToSend(votes); ok { msg := &VoteMessage{vote} ps.logger.Debug("Sending vote message", "ps", ps, "vote", vote) - if ps.peer.Send(VoteChannel, cdc.MustMarshalBinaryBare(msg)) { + if ps.peer.Send(VoteChannel, MustEncode(msg)) { ps.SetHasVote(vote) return true } @@ -1386,19 +1387,6 @@ type Message interface { ValidateBasic() error } -func RegisterMessages(cdc *amino.Codec) { - cdc.RegisterInterface((*Message)(nil), nil) - cdc.RegisterConcrete(&NewRoundStepMessage{}, "tendermint/NewRoundStepMessage", nil) - cdc.RegisterConcrete(&NewValidBlockMessage{}, "tendermint/NewValidBlockMessage", nil) - cdc.RegisterConcrete(&ProposalMessage{}, "tendermint/Proposal", nil) - cdc.RegisterConcrete(&ProposalPOLMessage{}, "tendermint/ProposalPOL", nil) - cdc.RegisterConcrete(&BlockPartMessage{}, "tendermint/BlockPart", nil) - cdc.RegisterConcrete(&VoteMessage{}, "tendermint/Vote", nil) - cdc.RegisterConcrete(&HasVoteMessage{}, "tendermint/HasVote", nil) - cdc.RegisterConcrete(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23", nil) - cdc.RegisterConcrete(&VoteSetBitsMessage{}, "tendermint/VoteSetBits", nil) -} - func init() { tmjson.RegisterType(&NewRoundStepMessage{}, "tendermint/NewRoundStepMessage") tmjson.RegisterType(&NewValidBlockMessage{}, "tendermint/NewValidBlockMessage") @@ -1412,8 +1400,12 @@ func init() { } func decodeMsg(bz []byte) (msg Message, err error) { - err = cdc.UnmarshalBinaryBare(bz, &msg) - return + pb := &tmcons.Message{} + if err = proto.Unmarshal(bz, pb); err != nil { + return msg, err + } + + return MsgFromProto(pb) } //------------------------------------- @@ -1424,7 +1416,7 @@ type NewRoundStepMessage struct { Height int64 Round int32 Step cstypes.RoundStepType - SecondsSinceStartTime int + SecondsSinceStartTime int64 LastCommitRound int32 } diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index adfdf4d8e..f85f3b84c 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -109,9 +109,6 @@ func TestReactorBasic(t *testing.T) { // Ensure we can process blocks with evidence func TestReactorWithEvidence(t *testing.T) { - types.RegisterMockEvidences(cdc) - types.RegisterMockEvidences(types.GetCodec()) - nValidators := 4 testName := "consensus_reactor_test" tickerFunc := newMockTickerFunc(true) @@ -273,7 +270,8 @@ func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { var ( reactor = reactors[0] peer = mock.NewPeer(nil) - msg = cdc.MustMarshalBinaryBare(&HasVoteMessage{Height: 1, Round: 1, Index: 1, Type: tmproto.PrevoteType}) + msg = MustEncode(&HasVoteMessage{Height: 1, + Round: 1, Index: 1, Type: tmproto.PrevoteType}) ) reactor.InitPeer(peer) @@ -295,7 +293,8 @@ func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { var ( reactor = reactors[0] peer = mock.NewPeer(nil) - msg = cdc.MustMarshalBinaryBare(&HasVoteMessage{Height: 1, Round: 1, Index: 1, Type: tmproto.PrevoteType}) + msg = MustEncode(&HasVoteMessage{Height: 1, + Round: 1, Index: 1, Type: tmproto.PrevoteType}) ) // we should call InitPeer here diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 4df75c65c..de153ae3b 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -89,7 +89,7 @@ type mockProxyApp struct { func (mock *mockProxyApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { r := mock.abciResponses.DeliverTxs[mock.txCount] mock.txCount++ - if r == nil { //it could be nil because of amino unMarshall, it will cause an empty ResponseDeliverTx to become nil + if r == nil { return abci.ResponseDeliverTx{} } return *r diff --git a/consensus/replay_test.go b/consensus/replay_test.go index cdfe98715..3d77efd08 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -9,15 +9,13 @@ import ( "os" "path/filepath" "runtime" + "sort" "testing" "time" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "sort" - dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/abci/example/kvstore" @@ -584,11 +582,12 @@ func TestMockProxyApp(t *testing.T) { abciResWithEmptyDeliverTx.DeliverTxs = append(abciResWithEmptyDeliverTx.DeliverTxs, &abci.ResponseDeliverTx{}) // called when saveABCIResponses: - bytes := cdc.MustMarshalBinaryBare(abciResWithEmptyDeliverTx) + bytes, err := proto.Marshal(abciResWithEmptyDeliverTx) + require.NoError(t, err) loadedAbciRes := new(tmstate.ABCIResponses) // this also happens sm.LoadABCIResponses - err := cdc.UnmarshalBinaryBare(bytes, loadedAbciRes) + err = proto.Unmarshal(bytes, loadedAbciRes) require.NoError(t, err) mock := newMockProxyApp([]byte("mock_hash"), loadedAbciRes) diff --git a/consensus/state.go b/consensus/state.go index 7e8ce5d40..51e44e99d 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -248,7 +248,7 @@ func (cs *State) GetRoundStateJSON() ([]byte, error) { return tmjson.Marshal(cs.RoundState) } -// GetRoundStateSimpleJSON returns a json of RoundStateSimple, marshalled using go-amino. +// GetRoundStateSimpleJSON returns a json of RoundStateSimple func (cs *State) GetRoundStateSimpleJSON() ([]byte, error) { cs.mtx.RLock() defer cs.mtx.RUnlock() @@ -1976,7 +1976,7 @@ func (cs *State) addVote( } default: - panic(fmt.Sprintf("Unexpected vote type %X", vote.Type)) // go-amino should prevent this. + panic(fmt.Sprintf("Unexpected vote type %v", vote.Type)) } return added, err diff --git a/consensus/types/codec.go b/consensus/types/codec.go deleted file mode 100644 index 69ac8c4a5..000000000 --- a/consensus/types/codec.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -import ( - amino "github.com/tendermint/go-amino" - - "github.com/tendermint/tendermint/types" -) - -var cdc = amino.NewCodec() - -func init() { - types.RegisterBlockAmino(cdc) -} diff --git a/consensus/types/peer_round_state.go b/consensus/types/peer_round_state.go index 5b27811f4..38ec526ce 100644 --- a/consensus/types/peer_round_state.go +++ b/consensus/types/peer_round_state.go @@ -65,31 +65,3 @@ func (prs PeerRoundState) StringIndented(indent string) string { indent, prs.CatchupCommit, prs.CatchupCommitRound, indent) } - -//----------------------------------------------------------- -// These methods are for Protobuf Compatibility - -// Size returns the size of the amino encoding, in bytes. -func (prs *PeerRoundState) Size() int { - bs, _ := prs.Marshal() - return len(bs) -} - -// Marshal returns the amino encoding. -func (prs *PeerRoundState) Marshal() ([]byte, error) { - return cdc.MarshalBinaryBare(prs) -} - -// MarshalTo calls Marshal and copies to the given buffer. -func (prs *PeerRoundState) MarshalTo(data []byte) (int, error) { - bs, err := prs.Marshal() - if err != nil { - return -1, err - } - return copy(data, bs), nil -} - -// Unmarshal deserializes from amino encoded form. -func (prs *PeerRoundState) Unmarshal(bs []byte) error { - return cdc.UnmarshalBinaryBare(bs, prs) -} diff --git a/consensus/types/round_state.go b/consensus/types/round_state.go index 6fd674f73..532afeac0 100644 --- a/consensus/types/round_state.go +++ b/consensus/types/round_state.go @@ -213,31 +213,3 @@ func (rs *RoundState) StringShort() string { return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`, rs.Height, rs.Round, rs.Step, rs.StartTime) } - -//----------------------------------------------------------- -// These methods are for Protobuf Compatibility - -// Size returns the size of the amino encoding, in bytes. -func (rs *RoundStateSimple) Size() int { - bs, _ := rs.Marshal() - return len(bs) -} - -// Marshal returns the amino encoding. -func (rs *RoundStateSimple) Marshal() ([]byte, error) { - return cdc.MarshalBinaryBare(rs) -} - -// MarshalTo calls Marshal and copies to the given buffer. -func (rs *RoundStateSimple) MarshalTo(data []byte) (int, error) { - bs, err := rs.Marshal() - if err != nil { - return -1, err - } - return copy(data, bs), nil -} - -// Unmarshal deserializes from amino encoded form. -func (rs *RoundStateSimple) Unmarshal(bs []byte) error { - return cdc.UnmarshalBinaryBare(bs, rs) -} diff --git a/consensus/types/round_state_test.go b/consensus/types/round_state_test.go index 131158f0e..749546c0d 100644 --- a/consensus/types/round_state_test.go +++ b/consensus/types/round_state_test.go @@ -84,6 +84,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) { LastCommit: nil, // TODO LastValidators: vset, } + b.StartTimer() for i := 0; i < b.N; i++ { diff --git a/consensus/wal.go b/consensus/wal.go index 215bfd1bd..1b434b359 100644 --- a/consensus/wal.go +++ b/consensus/wal.go @@ -2,29 +2,26 @@ package consensus import ( "encoding/binary" + "errors" "fmt" "hash/crc32" "io" "path/filepath" "time" - amino "github.com/tendermint/go-amino" + "github.com/gogo/protobuf/proto" auto "github.com/tendermint/tendermint/libs/autofile" tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" "github.com/tendermint/tendermint/libs/service" - "github.com/tendermint/tendermint/types" + tmcons "github.com/tendermint/tendermint/proto/consensus" tmtime "github.com/tendermint/tendermint/types/time" ) const ( - // amino overhead + time.Time + max consensus msg size - // - // q: where 24 bytes are coming from? - // a: cdc.MustMarshalBinaryBare(empty consensus part msg) = 14 bytes. +10 - // bytes just in case amino will require more space in the future. + // time.Time + max consensus msg size maxMsgSizeBytes = maxMsgSize + 24 // how often the WAL should be sync'd during period sync'ing @@ -48,14 +45,6 @@ type EndHeightMessage struct { type WALMessage interface{} -func RegisterWALMessages(cdc *amino.Codec) { - cdc.RegisterInterface((*WALMessage)(nil), nil) - cdc.RegisterConcrete(types.EventDataRoundState{}, "tendermint/wal/EventDataRoundState", nil) - cdc.RegisterConcrete(msgInfo{}, "tendermint/wal/MsgInfo", nil) - cdc.RegisterConcrete(timeoutInfo{}, "tendermint/wal/TimeoutInfo", nil) - cdc.RegisterConcrete(EndHeightMessage{}, "tendermint/wal/EndHeightMessage", nil) -} - func init() { tmjson.RegisterType(msgInfo{}, "tendermint/wal/MsgInfo") tmjson.RegisterType(timeoutInfo{}, "tendermint/wal/TimeoutInfo") @@ -291,7 +280,7 @@ func (wal *BaseWAL) SearchForEndHeight( // A WALEncoder writes custom-encoded WAL messages to an output stream. // -// Format: 4 bytes CRC sum + 4 bytes length + arbitrary-length value (go-amino encoded) +// Format: 4 bytes CRC sum + 4 bytes length + arbitrary-length value type WALEncoder struct { wr io.Writer } @@ -302,10 +291,22 @@ func NewWALEncoder(wr io.Writer) *WALEncoder { } // Encode writes the custom encoding of v to the stream. It returns an error if -// the amino-encoded size of v is greater than 1MB. Any error encountered +// the encoded size of v is greater than 1MB. Any error encountered // during the write is also returned. func (enc *WALEncoder) Encode(v *TimedWALMessage) error { - data := cdc.MustMarshalBinaryBare(v) + pbMsg, err := WALToProto(v.Msg) + if err != nil { + return err + } + pv := tmcons.TimedWALMessage{ + Time: v.Time, + Msg: pbMsg, + } + + data, err := proto.Marshal(&pv) + if err != nil { + panic(fmt.Errorf("encode timed wall message failure: %w", err)) + } crc := crc32.Checksum(data, crc32c) length := uint32(len(data)) @@ -319,7 +320,7 @@ func (enc *WALEncoder) Encode(v *TimedWALMessage) error { binary.BigEndian.PutUint32(msg[4:8], length) copy(msg[8:], data) - _, err := enc.wr.Write(msg) + _, err = enc.wr.Write(msg) return err } @@ -363,7 +364,7 @@ func (dec *WALDecoder) Decode() (*TimedWALMessage, error) { b := make([]byte, 4) _, err := dec.rd.Read(b) - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, err } if err != nil { @@ -397,13 +398,22 @@ func (dec *WALDecoder) Decode() (*TimedWALMessage, error) { return nil, DataCorruptionError{fmt.Errorf("checksums do not match: read: %v, actual: %v", crc, actualCRC)} } - var res = new(TimedWALMessage) - err = cdc.UnmarshalBinaryBare(data, res) + var res = new(tmcons.TimedWALMessage) + err = proto.Unmarshal(data, res) if err != nil { return nil, DataCorruptionError{fmt.Errorf("failed to decode data: %v", err)} } - return res, err + walMsg, err := WALFromProto(res.Msg) + if err != nil { + return nil, DataCorruptionError{fmt.Errorf("failed to convert from proto: %w", err)} + } + tMsgWal := &TimedWALMessage{ + Time: res.Time, + Msg: walMsg, + } + + return tMsgWal, err } type nilWAL struct{} diff --git a/consensus/wal_test.go b/consensus/wal_test.go index 6871f534d..044ea2ddf 100644 --- a/consensus/wal_test.go +++ b/consensus/wal_test.go @@ -82,6 +82,7 @@ func TestWALEncoderDecoder(t *testing.T) { msgs := []TimedWALMessage{ {Time: now, Msg: EndHeightMessage{0}}, {Time: now, Msg: timeoutInfo{Duration: time.Second, Height: 1, Round: 1, Step: types.RoundStepPropose}}, + {Time: now, Msg: tmtypes.EventDataRoundState{Height: 1, Round: 1, Step: ""}}, } b := new(bytes.Buffer) @@ -98,7 +99,6 @@ func TestWALEncoderDecoder(t *testing.T) { dec := NewWALDecoder(b) decoded, err := dec.Decode() require.NoError(t, err) - assert.Equal(t, msg.Time.UTC(), decoded.Time) assert.Equal(t, msg.Msg, decoded.Msg) } @@ -135,7 +135,10 @@ func TestWALWrite(t *testing.T) { }, }, } - err = wal.Write(msg) + + err = wal.Write(msgInfo{ + Msg: msg, + }) if assert.Error(t, err) { assert.Contains(t, err.Error(), "msg is too big") } diff --git a/crypto/merkle/simple_proof_test.go b/crypto/merkle/simple_proof_test.go index 68e6912fb..2dd8b7eb0 100644 --- a/crypto/merkle/simple_proof_test.go +++ b/crypto/merkle/simple_proof_test.go @@ -4,6 +4,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + tmrand "github.com/tendermint/tendermint/libs/rand" ) func TestSimpleProofValidateBasic(t *testing.T) { @@ -39,3 +42,35 @@ func TestSimpleProofValidateBasic(t *testing.T) { }) } } + +func TestSimpleProofProtoBuf(t *testing.T) { + testCases := []struct { + testName string + ps1 *SimpleProof + expPass bool + }{ + {"failure empty", &SimpleProof{}, false}, + {"failure nil", nil, false}, + {"success", + &SimpleProof{ + Total: 1, + Index: 1, + LeafHash: tmrand.Bytes(32), + Aunts: [][]byte{tmrand.Bytes(32), tmrand.Bytes(32), tmrand.Bytes(32)}, + }, true}, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + proto := tc.ps1.ToProto() + p, err := SimpleProofFromProto(proto) + if tc.expPass { + require.NoError(t, err) + require.Equal(t, tc.ps1, p, tc.testName) + } else { + require.Error(t, err, tc.testName) + } + }) + } +} diff --git a/crypto/merkle/simple_tree_test.go b/crypto/merkle/simple_tree_test.go index d6d4345e8..01d6058c3 100644 --- a/crypto/merkle/simple_tree_test.go +++ b/crypto/merkle/simple_tree_test.go @@ -109,7 +109,7 @@ func BenchmarkSimpleHashAlternatives(b *testing.B) { func Test_getSplitPoint(t *testing.T) { tests := []struct { length int64 - want int + want int64 }{ {1, 0}, {2, 1}, diff --git a/libs/math/safemath.go b/libs/math/safemath.go index 458ad9788..2c59c191c 100644 --- a/libs/math/safemath.go +++ b/libs/math/safemath.go @@ -6,6 +6,7 @@ import ( ) var ErrOverflowInt32 = errors.New("int32 overflow") +var ErrOverflowUint8 = errors.New("uint8 overflow") // SafeAddInt32 adds two int32 integers // If there is an overflow this will panic @@ -39,3 +40,14 @@ func SafeConvertInt32(a int64) int32 { } return int32(a) } + +// SafeConvertUint8 takes an int64 and checks if it overflows +// If there is an overflow it returns an error +func SafeConvertUint8(a int64) (uint8, error) { + if a > math.MaxUint8 { + return 0, ErrOverflowUint8 + } else if a < 0 { + return 0, ErrOverflowUint8 + } + return uint8(a), nil +} diff --git a/proto/consensus/msgs.pb.go b/proto/consensus/msgs.pb.go index 3b6a138c0..80d52749a 100644 --- a/proto/consensus/msgs.pb.go +++ b/proto/consensus/msgs.pb.go @@ -399,7 +399,7 @@ type HasVote struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` Type types.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=tendermint.proto.types.SignedMsgType" json:"type,omitempty"` - Index uint32 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + Index int32 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` } func (m *HasVote) Reset() { *m = HasVote{} } @@ -456,7 +456,7 @@ func (m *HasVote) GetType() types.SignedMsgType { return types.SIGNED_MSG_TYPE_UNKNOWN } -func (m *HasVote) GetIndex() uint32 { +func (m *HasVote) GetIndex() int32 { if m != nil { return m.Index } @@ -802,60 +802,60 @@ func init() { proto.RegisterFile("proto/consensus/msgs.proto", fileDescriptor_9d var fileDescriptor_9de64017f8b3fc88 = []byte{ // 863 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcb, 0x6e, 0xdb, 0x46, - 0x14, 0x25, 0x63, 0xc9, 0x92, 0x2f, 0x2d, 0x3b, 0x1d, 0xf4, 0x21, 0x38, 0x85, 0x6c, 0xb0, 0x4d, - 0xab, 0x16, 0x05, 0x15, 0x28, 0x40, 0x1f, 0xbb, 0x94, 0x7d, 0x80, 0x69, 0x2d, 0x47, 0xa0, 0x82, - 0x00, 0xed, 0x86, 0xa0, 0xc4, 0x01, 0x35, 0xad, 0xc8, 0x61, 0x39, 0x23, 0xb9, 0xfa, 0x80, 0x02, - 0x5d, 0xf6, 0x1b, 0xba, 0xee, 0xb6, 0x7f, 0xd0, 0x45, 0x96, 0x59, 0x76, 0x15, 0x14, 0xf2, 0x6f, - 0x74, 0x51, 0xcc, 0x43, 0x22, 0x9d, 0x80, 0xb6, 0xb5, 0x29, 0x90, 0x8d, 0x30, 0x73, 0x1f, 0x67, - 0xee, 0x9c, 0x3b, 0xf7, 0x88, 0x70, 0x94, 0xe5, 0x94, 0xd3, 0xde, 0x84, 0xa6, 0x0c, 0xa7, 0x6c, - 0xce, 0x7a, 0x09, 0x8b, 0x99, 0x23, 0x8d, 0xe8, 0x88, 0xe3, 0x34, 0xc2, 0x79, 0x42, 0x52, 0xae, - 0x2c, 0xce, 0x26, 0xec, 0xe8, 0x3d, 0x3e, 0x25, 0x79, 0x14, 0x64, 0x61, 0xce, 0x97, 0x3d, 0x85, - 0x11, 0xd3, 0x98, 0x16, 0x2b, 0x95, 0x71, 0xf4, 0x96, 0xb2, 0xf0, 0x65, 0x86, 0x99, 0xfa, 0xd5, - 0x8e, 0x3b, 0xca, 0x31, 0x23, 0x63, 0xd6, 0x1b, 0x13, 0x7e, 0xc9, 0x69, 0xff, 0x69, 0xc2, 0xfe, - 0x19, 0x3e, 0xf7, 0xe9, 0x3c, 0x8d, 0x46, 0x1c, 0x67, 0xe8, 0x4d, 0xd8, 0x9d, 0x62, 0x12, 0x4f, - 0x79, 0xdb, 0x3c, 0x31, 0xbb, 0x3b, 0xbe, 0xde, 0xa1, 0xd7, 0xa1, 0x9e, 0x8b, 0xa0, 0xf6, 0xad, - 0x13, 0xb3, 0x5b, 0xf7, 0xd5, 0x06, 0x21, 0xa8, 0x31, 0x8e, 0xb3, 0xf6, 0xce, 0x89, 0xd9, 0x6d, - 0xf9, 0x72, 0x8d, 0x3e, 0x81, 0x36, 0xc3, 0x13, 0x9a, 0x46, 0x2c, 0x60, 0x24, 0x9d, 0xe0, 0x80, - 0xf1, 0x30, 0xe7, 0x01, 0x27, 0x09, 0x6e, 0xd7, 0x24, 0xe6, 0x1b, 0xda, 0x3f, 0x12, 0xee, 0x91, - 0xf0, 0x3e, 0x26, 0x09, 0x46, 0x1f, 0xc2, 0x6b, 0xb3, 0x90, 0xf1, 0x60, 0x42, 0x93, 0x84, 0xf0, - 0x40, 0x1d, 0x57, 0x97, 0xc7, 0x1d, 0x0a, 0xc7, 0x17, 0xd2, 0x2e, 0x4b, 0xb5, 0xff, 0x35, 0xa1, - 0x75, 0x86, 0xcf, 0x9f, 0x84, 0x33, 0x12, 0xb9, 0x33, 0x3a, 0xf9, 0x71, 0xcb, 0xc2, 0xbf, 0x03, - 0x34, 0x16, 0x69, 0x92, 0x57, 0x16, 0x4c, 0x71, 0x18, 0xe1, 0x5c, 0x5e, 0xc3, 0xea, 0xdf, 0x75, - 0x5e, 0x6a, 0x87, 0xa2, 0x6c, 0x18, 0xe6, 0x7c, 0x84, 0xb9, 0x27, 0x83, 0xdd, 0xda, 0xd3, 0xe7, - 0xc7, 0x86, 0x7f, 0x5b, 0xc2, 0x08, 0x0f, 0x53, 0x76, 0xf4, 0x15, 0x58, 0x25, 0x68, 0x79, 0x65, - 0xab, 0xff, 0xee, 0xcb, 0x98, 0xa2, 0x21, 0x8e, 0x68, 0x88, 0xe3, 0x12, 0xfe, 0x79, 0x9e, 0x87, - 0x4b, 0x1f, 0x0a, 0x30, 0x74, 0x07, 0xf6, 0x08, 0xd3, 0x5c, 0x48, 0x16, 0x9a, 0x7e, 0x93, 0x30, - 0xc5, 0x81, 0x7d, 0x06, 0xcd, 0x61, 0x4e, 0x33, 0xca, 0xc2, 0x19, 0x72, 0xa1, 0x99, 0xe9, 0xb5, - 0xbc, 0xba, 0xd5, 0x3f, 0xa9, 0xbc, 0x80, 0x8e, 0xd3, 0xb5, 0x6f, 0xf2, 0xec, 0xdf, 0x4d, 0xb0, - 0xd6, 0xce, 0xe1, 0xa3, 0xd3, 0x4a, 0x32, 0x3f, 0x02, 0xb4, 0xce, 0x09, 0x32, 0x3a, 0x0b, 0xca, - 0xcc, 0xde, 0x5e, 0x7b, 0x86, 0x74, 0x26, 0x9b, 0x84, 0x06, 0xb0, 0x5f, 0x8e, 0xd6, 0xf4, 0xde, - 0x88, 0x0a, 0x5d, 0xa1, 0x55, 0xc2, 0xb4, 0x7f, 0x82, 0x3d, 0x77, 0xcd, 0xcf, 0x96, 0xed, 0xfe, - 0x18, 0x6a, 0xa2, 0x1b, 0xba, 0x82, 0xb7, 0xaf, 0x6a, 0xb0, 0x3e, 0x59, 0xc6, 0xdb, 0x9f, 0x42, - 0xed, 0x09, 0xe5, 0x18, 0xdd, 0x83, 0xda, 0x82, 0x72, 0xac, 0xf9, 0xad, 0xcc, 0x17, 0xb1, 0xbe, - 0x8c, 0xb4, 0x7f, 0x35, 0xa1, 0xe1, 0x85, 0x4c, 0x66, 0x6f, 0x57, 0xeb, 0x67, 0x50, 0x13, 0x68, - 0xb2, 0xd6, 0x83, 0xea, 0xc7, 0x38, 0x22, 0x71, 0x8a, 0xa3, 0x01, 0x8b, 0x1f, 0x2f, 0x33, 0xec, - 0xcb, 0x14, 0x01, 0x48, 0xd2, 0x08, 0xff, 0x2c, 0x1f, 0x5d, 0xcb, 0x57, 0x1b, 0xfb, 0x2f, 0x13, - 0xf6, 0x45, 0x1d, 0x23, 0xcc, 0x07, 0xe1, 0x0f, 0xfd, 0xfb, 0xff, 0x5f, 0x3d, 0xdf, 0x42, 0x53, - 0x8d, 0x02, 0x89, 0xf4, 0x1c, 0x1c, 0x57, 0xa5, 0xcb, 0xce, 0x3e, 0xfc, 0xd2, 0x3d, 0x14, 0xec, - 0xaf, 0x9e, 0x1f, 0x37, 0xb4, 0xc1, 0x6f, 0x48, 0x84, 0x87, 0x91, 0xfd, 0xcb, 0x2d, 0xb0, 0xf4, - 0x35, 0x5c, 0xc2, 0xd9, 0xab, 0x79, 0x0b, 0xf4, 0x00, 0xea, 0xe2, 0x7d, 0x30, 0x39, 0xd2, 0xdb, - 0x0d, 0x83, 0x4a, 0xb4, 0xff, 0xa8, 0x43, 0x63, 0x80, 0x19, 0x0b, 0x63, 0x8c, 0x86, 0x70, 0x90, - 0xe2, 0x73, 0x35, 0x86, 0x81, 0x54, 0x62, 0xf5, 0x42, 0xbb, 0x4e, 0xf5, 0x3f, 0x8a, 0x53, 0xd6, - 0x7b, 0xcf, 0xf0, 0xf7, 0xd3, 0xb2, 0xfe, 0x8f, 0xe0, 0x50, 0x20, 0x2e, 0x84, 0xb0, 0x06, 0xb2, - 0x68, 0xc9, 0xa3, 0xd5, 0xff, 0xe0, 0x1a, 0xc8, 0x42, 0x8a, 0x3d, 0xc3, 0x6f, 0xa5, 0x97, 0xb4, - 0xb9, 0x2c, 0x51, 0x95, 0x22, 0x50, 0xa0, 0xad, 0x95, 0xc8, 0x2b, 0x49, 0x14, 0x3a, 0x7d, 0x41, - 0x4c, 0x54, 0x27, 0xde, 0xbf, 0x09, 0xce, 0xf0, 0xd1, 0xa9, 0x77, 0x59, 0x4b, 0xd0, 0xd7, 0x00, - 0x85, 0x48, 0xeb, 0x5e, 0xdc, 0xbd, 0x0a, 0x6b, 0xa3, 0x3c, 0x9e, 0xe1, 0xef, 0x6d, 0x64, 0x5a, - 0x08, 0x8b, 0x14, 0x86, 0xdd, 0x2a, 0xe1, 0x2d, 0x10, 0xc4, 0xdb, 0xf5, 0x0c, 0x25, 0x0f, 0xe8, - 0x01, 0x34, 0xa7, 0x21, 0x0b, 0x64, 0x6e, 0x43, 0xe6, 0xbe, 0x73, 0x55, 0xae, 0x56, 0x12, 0xcf, - 0xf0, 0x1b, 0x53, 0x2d, 0x2a, 0x43, 0x38, 0x10, 0xd9, 0x01, 0xc3, 0x3c, 0x48, 0xc4, 0x58, 0xb7, - 0x9b, 0xd7, 0xb7, 0xbe, 0x2c, 0x03, 0xa2, 0xf5, 0x8b, 0xb2, 0x2c, 0x0c, 0xa0, 0xb5, 0x41, 0x14, - 0xef, 0xaf, 0xbd, 0x77, 0x3d, 0xc5, 0xa5, 0x81, 0x14, 0x14, 0x2f, 0x8a, 0xad, 0x5b, 0x87, 0x1d, - 0x36, 0x4f, 0xdc, 0x6f, 0x9e, 0xae, 0x3a, 0xe6, 0xb3, 0x55, 0xc7, 0xfc, 0x67, 0xd5, 0x31, 0x7f, - 0xbb, 0xe8, 0x18, 0xcf, 0x2e, 0x3a, 0xc6, 0xdf, 0x17, 0x1d, 0xe3, 0xfb, 0x7b, 0x31, 0xe1, 0xd3, - 0xf9, 0xd8, 0x99, 0xd0, 0xa4, 0x57, 0x1c, 0x51, 0x5e, 0xbe, 0xf0, 0xc9, 0x34, 0xde, 0x95, 0x86, - 0xfb, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x77, 0x46, 0xa2, 0xe6, 0x4c, 0x09, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcb, 0x8e, 0xe3, 0x44, + 0x14, 0xb5, 0xa7, 0x93, 0x4e, 0xfa, 0xba, 0x1f, 0x43, 0x89, 0x47, 0xd4, 0x83, 0xd2, 0x91, 0x61, + 0x20, 0x20, 0xe4, 0x8c, 0x32, 0x12, 0x8f, 0xdd, 0x60, 0x1e, 0xf2, 0x40, 0xa7, 0x27, 0x72, 0x46, + 0x23, 0xc1, 0xc6, 0x72, 0xe2, 0x92, 0x53, 0x10, 0xbb, 0x8c, 0xab, 0x92, 0x26, 0x1f, 0x80, 0xc4, + 0x92, 0x6f, 0x60, 0xcd, 0x96, 0x3f, 0x60, 0x31, 0xcb, 0x59, 0xb2, 0x1a, 0xa1, 0xf4, 0x6f, 0xb0, + 0x40, 0xf5, 0x48, 0xec, 0x9e, 0x91, 0xbb, 0x3b, 0x1b, 0xa4, 0xd9, 0x44, 0x55, 0xf7, 0x71, 0xea, + 0xd6, 0xb9, 0x75, 0x4f, 0x0c, 0xc7, 0x59, 0x4e, 0x39, 0xed, 0x4d, 0x68, 0xca, 0x70, 0xca, 0xe6, + 0xac, 0x97, 0xb0, 0x98, 0x39, 0xd2, 0x88, 0x8e, 0x39, 0x4e, 0x23, 0x9c, 0x27, 0x24, 0xe5, 0xca, + 0xe2, 0x6c, 0xc2, 0x8e, 0xdf, 0xe3, 0x53, 0x92, 0x47, 0x41, 0x16, 0xe6, 0x7c, 0xd9, 0x53, 0x18, + 0x31, 0x8d, 0x69, 0xb1, 0x52, 0x19, 0xc7, 0x6f, 0x29, 0x0b, 0x5f, 0x66, 0x98, 0xa9, 0x5f, 0xed, + 0xb8, 0xa3, 0x1c, 0x33, 0x32, 0x66, 0xbd, 0x31, 0xe1, 0x97, 0x9c, 0xf6, 0x9f, 0x26, 0xec, 0x9f, + 0xe1, 0x73, 0x9f, 0xce, 0xd3, 0x68, 0xc4, 0x71, 0x86, 0xde, 0x84, 0xdd, 0x29, 0x26, 0xf1, 0x94, + 0xb7, 0xcc, 0x8e, 0xd9, 0xdd, 0xf1, 0xf5, 0x0e, 0xbd, 0x0e, 0xf5, 0x5c, 0x04, 0xb5, 0x6e, 0x75, + 0xcc, 0x6e, 0xdd, 0x57, 0x1b, 0x84, 0xa0, 0xc6, 0x38, 0xce, 0x5a, 0x3b, 0x1d, 0xb3, 0x7b, 0xe0, + 0xcb, 0x35, 0xfa, 0x04, 0x5a, 0x0c, 0x4f, 0x68, 0x1a, 0xb1, 0x80, 0x91, 0x74, 0x82, 0x03, 0xc6, + 0xc3, 0x9c, 0x07, 0x9c, 0x24, 0xb8, 0x55, 0x93, 0x98, 0x6f, 0x68, 0xff, 0x48, 0xb8, 0x47, 0xc2, + 0xfb, 0x98, 0x24, 0x18, 0x7d, 0x08, 0xaf, 0xcd, 0x42, 0xc6, 0x83, 0x09, 0x4d, 0x12, 0xc2, 0x03, + 0x75, 0x5c, 0x5d, 0x1e, 0x77, 0x24, 0x1c, 0x5f, 0x48, 0xbb, 0x2c, 0xd5, 0xfe, 0xd7, 0x84, 0x83, + 0x33, 0x7c, 0xfe, 0x24, 0x9c, 0x91, 0xc8, 0x9d, 0xd1, 0xc9, 0x8f, 0x5b, 0x16, 0xfe, 0x1d, 0xa0, + 0xb1, 0x48, 0x93, 0xbc, 0xb2, 0x60, 0x8a, 0xc3, 0x08, 0xe7, 0xf2, 0x1a, 0x56, 0xff, 0xae, 0xf3, + 0x52, 0x3b, 0x14, 0x65, 0xc3, 0x30, 0xe7, 0x23, 0xcc, 0x3d, 0x19, 0xec, 0xd6, 0x9e, 0x3e, 0x3f, + 0x31, 0xfc, 0xdb, 0x12, 0x46, 0x78, 0x98, 0xb2, 0xa3, 0xaf, 0xc0, 0x2a, 0x41, 0xcb, 0x2b, 0x5b, + 0xfd, 0x77, 0x5f, 0xc6, 0x14, 0x0d, 0x71, 0x44, 0x43, 0x1c, 0x97, 0xf0, 0xcf, 0xf3, 0x3c, 0x5c, + 0xfa, 0x50, 0x80, 0xa1, 0x3b, 0xb0, 0x47, 0x98, 0xe6, 0x42, 0xb2, 0xd0, 0xf4, 0x9b, 0x84, 0x29, + 0x0e, 0xec, 0x33, 0x68, 0x0e, 0x73, 0x9a, 0x51, 0x16, 0xce, 0x90, 0x0b, 0xcd, 0x4c, 0xaf, 0xe5, + 0xd5, 0xad, 0x7e, 0xa7, 0xf2, 0x02, 0x3a, 0x4e, 0xd7, 0xbe, 0xc9, 0xb3, 0x7f, 0x37, 0xc1, 0x5a, + 0x3b, 0x87, 0x8f, 0x4e, 0x2b, 0xc9, 0xfc, 0x08, 0xd0, 0x3a, 0x27, 0xc8, 0xe8, 0x2c, 0x28, 0x33, + 0x7b, 0x7b, 0xed, 0x19, 0xd2, 0x99, 0x6c, 0x12, 0x1a, 0xc0, 0x7e, 0x39, 0x5a, 0xd3, 0x7b, 0x23, + 0x2a, 0x74, 0x85, 0x56, 0x09, 0xd3, 0xfe, 0x09, 0xf6, 0xdc, 0x35, 0x3f, 0x5b, 0xb6, 0xfb, 0x63, + 0xa8, 0x89, 0x6e, 0xe8, 0x0a, 0xde, 0xbe, 0xaa, 0xc1, 0xfa, 0x64, 0x19, 0x6f, 0x7f, 0x0a, 0xb5, + 0x27, 0x94, 0x63, 0x74, 0x0f, 0x6a, 0x0b, 0xca, 0xb1, 0xe6, 0xb7, 0x32, 0x5f, 0xc4, 0xfa, 0x32, + 0xd2, 0xfe, 0xd5, 0x84, 0x86, 0x17, 0x32, 0x99, 0xbd, 0x5d, 0xad, 0x9f, 0x41, 0x4d, 0xa0, 0xc9, + 0x5a, 0x0f, 0xab, 0x1f, 0xe3, 0x88, 0xc4, 0x29, 0x8e, 0x06, 0x2c, 0x7e, 0xbc, 0xcc, 0xb0, 0x2f, + 0x53, 0x04, 0x20, 0x49, 0x23, 0xfc, 0xb3, 0x7c, 0x74, 0x75, 0x5f, 0x6d, 0xec, 0xbf, 0x4c, 0xd8, + 0x17, 0x75, 0x8c, 0x30, 0x1f, 0x84, 0x3f, 0xf4, 0xef, 0xff, 0x7f, 0xf5, 0x7c, 0x0b, 0x4d, 0x35, + 0x0a, 0x24, 0xd2, 0x73, 0x70, 0x52, 0x95, 0x2e, 0x3b, 0xfb, 0xf0, 0x4b, 0xf7, 0x48, 0xb0, 0xbf, + 0x7a, 0x7e, 0xd2, 0xd0, 0x06, 0xbf, 0x21, 0x11, 0x1e, 0x46, 0xf6, 0x2f, 0xb7, 0xc0, 0xd2, 0xd7, + 0x70, 0x09, 0x67, 0xaf, 0xe6, 0x2d, 0xd0, 0x03, 0xa8, 0x8b, 0xf7, 0xc1, 0xe4, 0x48, 0x6f, 0x37, + 0x0c, 0x2a, 0xd1, 0xfe, 0xa3, 0x0e, 0x8d, 0x01, 0x66, 0x2c, 0x8c, 0x31, 0x1a, 0xc2, 0x61, 0x8a, + 0xcf, 0xd5, 0x18, 0x06, 0x52, 0x89, 0xd5, 0x0b, 0xed, 0x3a, 0xd5, 0xff, 0x28, 0x4e, 0x59, 0xef, + 0x3d, 0xc3, 0xdf, 0x4f, 0xcb, 0xfa, 0x3f, 0x82, 0x23, 0x81, 0xb8, 0x10, 0xc2, 0x1a, 0xc8, 0xa2, + 0x25, 0x8f, 0x56, 0xff, 0x83, 0x6b, 0x20, 0x0b, 0x29, 0xf6, 0x0c, 0xff, 0x20, 0xbd, 0xa4, 0xcd, + 0x65, 0x89, 0xaa, 0x14, 0x81, 0x02, 0x6d, 0xad, 0x44, 0x5e, 0x49, 0xa2, 0xd0, 0xe9, 0x0b, 0x62, + 0xa2, 0x3a, 0xf1, 0xfe, 0x4d, 0x70, 0x86, 0x8f, 0x4e, 0xbd, 0xcb, 0x5a, 0x82, 0xbe, 0x06, 0x28, + 0x44, 0x5a, 0xf7, 0xe2, 0xee, 0x55, 0x58, 0x1b, 0xe5, 0xf1, 0x0c, 0x7f, 0x6f, 0x23, 0xd3, 0x42, + 0x58, 0xa4, 0x30, 0xec, 0x56, 0x09, 0x6f, 0x81, 0x20, 0xde, 0xae, 0x67, 0x28, 0x79, 0x40, 0x0f, + 0xa0, 0x39, 0x0d, 0x59, 0x20, 0x73, 0x1b, 0x32, 0xf7, 0x9d, 0xab, 0x72, 0xb5, 0x92, 0x78, 0x86, + 0xdf, 0x98, 0x6a, 0x51, 0x19, 0xc2, 0xa1, 0xc8, 0x0e, 0x18, 0xe6, 0x41, 0x22, 0xc6, 0xba, 0xd5, + 0xbc, 0xbe, 0xf5, 0x65, 0x19, 0x10, 0xad, 0x5f, 0x94, 0x65, 0x61, 0x00, 0x07, 0x1b, 0x44, 0xf1, + 0xfe, 0x5a, 0x7b, 0xd7, 0x53, 0x5c, 0x1a, 0x48, 0x41, 0xf1, 0xa2, 0xd8, 0xba, 0x75, 0xd8, 0x61, + 0xf3, 0xc4, 0xfd, 0xe6, 0xe9, 0xaa, 0x6d, 0x3e, 0x5b, 0xb5, 0xcd, 0x7f, 0x56, 0x6d, 0xf3, 0xb7, + 0x8b, 0xb6, 0xf1, 0xec, 0xa2, 0x6d, 0xfc, 0x7d, 0xd1, 0x36, 0xbe, 0xbf, 0x17, 0x13, 0x3e, 0x9d, + 0x8f, 0x9d, 0x09, 0x4d, 0x7a, 0xc5, 0x11, 0xe5, 0xe5, 0x0b, 0x9f, 0x4c, 0xe3, 0x5d, 0x69, 0xb8, + 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xb5, 0xc3, 0x75, 0x4c, 0x09, 0x00, 0x00, } func (m *NewRoundStep) Marshal() (dAtA []byte, err error) { @@ -2653,7 +2653,7 @@ func (m *HasVote) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Index |= uint32(b&0x7F) << shift + m.Index |= int32(b&0x7F) << shift if b < 0x80 { break } diff --git a/proto/consensus/msgs.proto b/proto/consensus/msgs.proto index 245e0f4c4..ad35f308a 100644 --- a/proto/consensus/msgs.proto +++ b/proto/consensus/msgs.proto @@ -57,7 +57,7 @@ message HasVote { int64 height = 1; int32 round = 2; tendermint.proto.types.SignedMsgType type = 3; - uint32 index = 4; + int32 index = 4; } // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes. From 46f6d176016ee533d5ef8b0585ecc1896826fbef Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 10 Jun 2020 16:57:38 +0200 Subject: [PATCH 06/12] crypto/merkle: remove simple prefix (#4989) ## Description This PR removes simple prefix from all types in the crypto/merkle directory. The two proto types `Proof` & `ProofOp` have been moved to the `proto/crypto/merkle` directory. proto messge `Proof` was renamed to `ProofOps` and `SimpleProof` message to `Proof`. Closes: #2755 --- CHANGELOG_PENDING.md | 7 + abci/cmd/abci-cli/abci-cli.go | 22 +- abci/types/types.pb.go | 377 +++++------ abci/types/types.proto | 73 ++- consensus/msgs_test.go | 4 +- consensus/wal_test.go | 2 +- crypto/armor/armor_test.go | 2 +- crypto/merkle/merkle.pb.go | 617 ------------------ crypto/merkle/merkle.proto | 28 - crypto/merkle/proof.go | 307 ++++++--- crypto/merkle/proof_key_path.go | 2 +- crypto/merkle/proof_op.go | 139 ++++ crypto/merkle/proof_test.go | 43 +- .../{proof_simple_value.go => proof_value.go} | 43 +- crypto/merkle/result.go | 52 -- crypto/merkle/simple_proof.go | 235 ------- crypto/merkle/simple_proof_test.go | 76 --- crypto/merkle/{simple_tree.go => tree.go} | 26 +- .../{simple_tree_test.go => tree_test.go} | 18 +- go.sum | 2 - light/rpc/client.go | 6 +- light/rpc/proof.go | 4 +- proto/crypto/merkle/types.pb.go | 555 ++++++++++++++-- proto/crypto/merkle/types.proto | 18 +- proto/types/types.pb.go | 173 +++-- proto/types/types.proto | 6 +- types/block.go | 4 +- types/block_test.go | 2 +- types/evidence.go | 2 +- types/part_set.go | 10 +- types/part_set_test.go | 4 +- types/results.go | 6 +- types/tx.go | 10 +- types/validator_set.go | 2 +- 34 files changed, 1318 insertions(+), 1559 deletions(-) delete mode 100644 crypto/merkle/merkle.pb.go delete mode 100644 crypto/merkle/merkle.proto create mode 100644 crypto/merkle/proof_op.go rename crypto/merkle/{proof_simple_value.go => proof_value.go} (58%) delete mode 100644 crypto/merkle/result.go delete mode 100644 crypto/merkle/simple_proof.go delete mode 100644 crypto/merkle/simple_proof_test.go rename crypto/merkle/{simple_tree.go => tree.go} (73%) rename crypto/merkle/{simple_tree_test.go => tree_test.go} (86%) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index c1b3faa28..e424bfbc9 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -25,6 +25,12 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [crypto] \#4940 All keys have become `[]byte` instead of `[]byte`. The byte method no longer returns the marshaled value but just the `[]byte` form of the data. - [crypto] \4988 Removal of key type multisig - The key has been moved to the Cosmos-SDK (https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/multisig/multisignature.go) + - [crypto] \#4989 Remove `Simple` prefixes from `SimpleProof`, `SimpleValueOp` & `SimpleProofNode`. + - `merkle.Proof` has been renamed to `ProofOps`. + - Protobuf messages `Proof` & `ProofOp` has been moved to `proto/crypto/merkle` + - `SimpleHashFromByteSlices` has been renamed to `HashFromByteSlices` + - `SimpleHashFromByteSlicesIterative` has been renamed to `HashFromByteSlicesIterative` + - `SimpleProofsFromByteSlices` has been renamed to `ProofsFromByteSlices` - [crypto] \#4941 Remove suffixes from all keys. - ed25519: type `PrivKeyEd25519` is now `PrivKey` - ed25519: type `PubKeyEd25519` is now `PubKey` @@ -48,6 +54,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - Apps - [abci] [\#4704](https://github.com/tendermint/tendermint/pull/4704) Add ABCI methods `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk` for state sync snapshots. `ABCIVersion` bumped to 0.17.0. + - [abci] \#4989 `Proof` within `ResponseQuery` has been renamed to `ProofOps` - P2P Protocol diff --git a/abci/cmd/abci-cli/abci-cli.go b/abci/cmd/abci-cli/abci-cli.go index d5a9aca27..752470977 100644 --- a/abci/cmd/abci-cli/abci-cli.go +++ b/abci/cmd/abci-cli/abci-cli.go @@ -22,7 +22,7 @@ import ( servertest "github.com/tendermint/tendermint/abci/tests/server" "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/abci/version" - "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/proto/crypto/merkle" ) // client is a global variable so it can be reused by the console @@ -98,10 +98,10 @@ type response struct { } type queryResponse struct { - Key []byte - Value []byte - Height int64 - Proof *merkle.Proof + Key []byte + Value []byte + Height int64 + ProofOps *merkle.ProofOps } func Execute() error { @@ -616,10 +616,10 @@ func cmdQuery(cmd *cobra.Command, args []string) error { Info: resQuery.Info, Log: resQuery.Log, Query: &queryResponse{ - Key: resQuery.Key, - Value: resQuery.Value, - Height: resQuery.Height, - Proof: resQuery.Proof, + Key: resQuery.Key, + Value: resQuery.Value, + Height: resQuery.Height, + ProofOps: resQuery.ProofOps, }, }) return nil @@ -719,8 +719,8 @@ func printResponse(cmd *cobra.Command, args []string, rsp response) { fmt.Printf("-> value: %s\n", rsp.Query.Value) fmt.Printf("-> value.hex: %X\n", rsp.Query.Value) } - if rsp.Query.Proof != nil { - fmt.Printf("-> proof: %#v\n", rsp.Query.Proof) + if rsp.Query.ProofOps != nil { + fmt.Printf("-> proof: %#v\n", rsp.Query.ProofOps) } } } diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 37ce711b2..d2427b504 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -10,7 +10,7 @@ import ( proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" _ "github.com/golang/protobuf/ptypes/timestamp" - merkle "github.com/tendermint/tendermint/crypto/merkle" + merkle "github.com/tendermint/tendermint/proto/crypto/merkle" types "github.com/tendermint/tendermint/proto/types" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -1758,14 +1758,14 @@ func (m *ResponseInitChain) GetValidators() []ValidatorUpdate { type ResponseQuery struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // bytes data = 2; // use "value" instead. - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` - Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` - Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` - Proof *merkle.Proof `protobuf:"bytes,8,opt,name=proof,proto3" json:"proof,omitempty"` - Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` - Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` + Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` + ProofOps *merkle.ProofOps `protobuf:"bytes,8,opt,name=proof_ops,json=proofOps,proto3" json:"proof_ops,omitempty"` + Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` + Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"` } func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } @@ -1843,9 +1843,9 @@ func (m *ResponseQuery) GetValue() []byte { return nil } -func (m *ResponseQuery) GetProof() *merkle.Proof { +func (m *ResponseQuery) GetProofOps() *merkle.ProofOps { if m != nil { - return m.Proof + return m.ProofOps } return nil } @@ -3290,175 +3290,176 @@ func init() { func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_9f1eaa49c51fa1ac) } var fileDescriptor_9f1eaa49c51fa1ac = []byte{ - // 2688 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x73, 0x1b, 0xc7, - 0x11, 0xc6, 0x02, 0x20, 0x1e, 0x0d, 0x02, 0x04, 0x47, 0xb2, 0x0c, 0x23, 0x36, 0xa9, 0x5a, 0x59, - 0x2f, 0x5b, 0x21, 0x65, 0xba, 0x92, 0x92, 0x22, 0x25, 0x29, 0x82, 0x82, 0x02, 0x46, 0x0f, 0x52, - 0x4b, 0x52, 0x91, 0x93, 0x2a, 0x6f, 0x06, 0xd8, 0x21, 0xb0, 0x16, 0xb0, 0xbb, 0xde, 0x1d, 0x50, - 0x44, 0x2a, 0x87, 0x54, 0x2e, 0xa9, 0xdc, 0x94, 0x4b, 0x6e, 0xf9, 0x0f, 0x39, 0xa4, 0xca, 0xf9, - 0x03, 0xa9, 0xf2, 0xd1, 0xa7, 0x54, 0x4e, 0x4e, 0x4a, 0xca, 0x29, 0xb9, 0xe6, 0x07, 0xa4, 0xe6, - 0xb1, 0x2f, 0x10, 0x8f, 0x85, 0xa3, 0x5b, 0x2e, 0xe4, 0xf4, 0x6c, 0x77, 0xcf, 0x4c, 0xcf, 0x4c, - 0xf7, 0xd7, 0x3d, 0x80, 0x0b, 0xb8, 0xdd, 0x31, 0x37, 0xe9, 0xc8, 0x21, 0x9e, 0xf8, 0xbb, 0xe1, - 0xb8, 0x36, 0xb5, 0xd1, 0x5b, 0x94, 0x58, 0x06, 0x71, 0x07, 0xa6, 0x45, 0x37, 0x18, 0xcb, 0x06, - 0xff, 0x58, 0xaf, 0x77, 0xdc, 0x91, 0x43, 0xed, 0xcd, 0x01, 0x71, 0x9f, 0xf7, 0x89, 0xfc, 0x27, - 0x44, 0xea, 0x6f, 0xf3, 0x7f, 0x67, 0x75, 0xd5, 0x6b, 0xd1, 0x0f, 0x0e, 0x76, 0xf1, 0xc0, 0xff, - 0xb2, 0xde, 0xb5, 0xed, 0x6e, 0x9f, 0x6c, 0x72, 0xaa, 0x3d, 0x3c, 0xde, 0xa4, 0xe6, 0x80, 0x78, - 0x14, 0x0f, 0x1c, 0xc9, 0x70, 0x85, 0xf6, 0x4c, 0xd7, 0xd0, 0x1d, 0xec, 0xd2, 0x91, 0xe0, 0xda, - 0xec, 0xda, 0x5d, 0x3b, 0x6c, 0x09, 0x3e, 0xf5, 0xdf, 0x05, 0xc8, 0x6b, 0xe4, 0xf3, 0x21, 0xf1, - 0x28, 0xba, 0x05, 0x59, 0xd2, 0xe9, 0xd9, 0xb5, 0xf4, 0x45, 0xe5, 0x5a, 0x69, 0x4b, 0xdd, 0x98, - 0xb8, 0x92, 0x0d, 0xc9, 0xdd, 0xec, 0xf4, 0xec, 0x56, 0x4a, 0xe3, 0x12, 0xe8, 0x0e, 0x2c, 0x1d, - 0xf7, 0x87, 0x5e, 0xaf, 0x96, 0xe1, 0xa2, 0x97, 0x66, 0x8b, 0xde, 0x67, 0xac, 0xad, 0x94, 0x26, - 0x64, 0xd8, 0xb0, 0xa6, 0x75, 0x6c, 0xd7, 0xb2, 0x49, 0x86, 0xdd, 0xb5, 0x8e, 0xf9, 0xb0, 0x4c, - 0x02, 0xb5, 0x00, 0x3c, 0x42, 0x75, 0xdb, 0xa1, 0xa6, 0x6d, 0xd5, 0x96, 0xb8, 0xfc, 0xd5, 0xd9, - 0xf2, 0x07, 0x84, 0xee, 0x71, 0xf6, 0x56, 0x4a, 0x2b, 0x7a, 0x3e, 0xc1, 0x34, 0x99, 0x96, 0x49, - 0xf5, 0x4e, 0x0f, 0x9b, 0x56, 0x2d, 0x97, 0x44, 0xd3, 0xae, 0x65, 0xd2, 0x1d, 0xc6, 0xce, 0x34, - 0x99, 0x3e, 0xc1, 0x4c, 0xf1, 0xf9, 0x90, 0xb8, 0xa3, 0x5a, 0x3e, 0x89, 0x29, 0x9e, 0x30, 0x56, - 0x66, 0x0a, 0x2e, 0x83, 0x1e, 0x40, 0xa9, 0x4d, 0xba, 0xa6, 0xa5, 0xb7, 0xfb, 0x76, 0xe7, 0x79, - 0xad, 0xc0, 0x55, 0x5c, 0x9b, 0xad, 0xa2, 0xc1, 0x04, 0x1a, 0x8c, 0xbf, 0x95, 0xd2, 0xa0, 0x1d, - 0x50, 0xa8, 0x01, 0x85, 0x4e, 0x8f, 0x74, 0x9e, 0xeb, 0xf4, 0xb4, 0x56, 0xe4, 0x9a, 0x2e, 0xcf, - 0xd6, 0xb4, 0xc3, 0xb8, 0x0f, 0x4f, 0x5b, 0x29, 0x2d, 0xdf, 0x11, 0x4d, 0x66, 0x17, 0x83, 0xf4, - 0xcd, 0x13, 0xe2, 0x32, 0x2d, 0xe7, 0x92, 0xd8, 0xe5, 0x9e, 0xe0, 0xe7, 0x7a, 0x8a, 0x86, 0x4f, - 0xa0, 0x26, 0x14, 0x89, 0x65, 0xc8, 0x85, 0x95, 0xb8, 0xa2, 0x2b, 0x73, 0x4e, 0x98, 0x65, 0xf8, - 0xcb, 0x2a, 0x10, 0xd9, 0x46, 0x3f, 0x80, 0x5c, 0xc7, 0x1e, 0x0c, 0x4c, 0x5a, 0x5b, 0xe6, 0x3a, - 0xde, 0x9f, 0xb3, 0x24, 0xce, 0xdb, 0x4a, 0x69, 0x52, 0x0a, 0x1d, 0x42, 0xa5, 0x6f, 0x7a, 0x54, - 0xf7, 0x2c, 0xec, 0x78, 0x3d, 0x9b, 0x7a, 0xb5, 0x32, 0xd7, 0xf3, 0xe1, 0x6c, 0x3d, 0x0f, 0x4d, - 0x8f, 0x1e, 0xf8, 0x22, 0xad, 0x94, 0x56, 0xee, 0x47, 0x3b, 0x98, 0x56, 0xfb, 0xf8, 0x98, 0xb8, - 0x81, 0xda, 0x5a, 0x25, 0x89, 0xd6, 0x3d, 0x26, 0xe3, 0x6b, 0x61, 0x5a, 0xed, 0x68, 0x07, 0xc2, - 0x70, 0xae, 0x6f, 0x63, 0x23, 0x50, 0xaa, 0x77, 0x7a, 0x43, 0xeb, 0x79, 0x6d, 0x85, 0xab, 0xde, - 0x9c, 0x33, 0x61, 0x1b, 0x1b, 0xbe, 0xa2, 0x1d, 0x26, 0xd6, 0x4a, 0x69, 0xab, 0xfd, 0xf1, 0x4e, - 0x64, 0xc0, 0x79, 0xec, 0x38, 0xfd, 0xd1, 0xf8, 0x18, 0x55, 0x3e, 0xc6, 0xcd, 0xd9, 0x63, 0x6c, - 0x33, 0xc9, 0xf1, 0x41, 0x10, 0x3e, 0xd3, 0xdb, 0xc8, 0xc3, 0xd2, 0x09, 0xee, 0x0f, 0x89, 0x7a, - 0x15, 0x4a, 0x11, 0xf7, 0x81, 0x6a, 0x90, 0x1f, 0x10, 0xcf, 0xc3, 0x5d, 0x52, 0x53, 0x2e, 0x2a, - 0xd7, 0x8a, 0x9a, 0x4f, 0xaa, 0x15, 0x58, 0x8e, 0x3a, 0x0b, 0x75, 0x10, 0x08, 0x32, 0x07, 0xc0, - 0x04, 0x4f, 0x88, 0xeb, 0xb1, 0x5b, 0x2f, 0x05, 0x25, 0x89, 0x2e, 0x41, 0x99, 0x1f, 0x31, 0xdd, - 0xff, 0xce, 0x9c, 0x59, 0x56, 0x5b, 0xe6, 0x9d, 0x4f, 0x25, 0xd3, 0x3a, 0x94, 0x9c, 0x2d, 0x27, - 0x60, 0xc9, 0x70, 0x16, 0x70, 0xb6, 0x1c, 0xc9, 0xa0, 0x7e, 0x0f, 0xaa, 0xe3, 0xfe, 0x02, 0x55, - 0x21, 0xf3, 0x9c, 0x8c, 0xe4, 0x78, 0xac, 0x89, 0xce, 0xcb, 0x65, 0xf1, 0x31, 0x8a, 0x9a, 0x5c, - 0xe3, 0x1f, 0xd3, 0x81, 0x70, 0xe0, 0x22, 0x98, 0x8f, 0x63, 0x1e, 0x9a, 0x4b, 0x97, 0xb6, 0xea, - 0x1b, 0xc2, 0x7d, 0x6f, 0xf8, 0xee, 0x7b, 0xe3, 0xd0, 0x77, 0xdf, 0x8d, 0xc2, 0x97, 0x5f, 0xaf, - 0xa7, 0x5e, 0xfe, 0x7d, 0x5d, 0xd1, 0xb8, 0x04, 0x7a, 0x87, 0xdd, 0x62, 0x6c, 0x5a, 0xba, 0x69, - 0xc8, 0x71, 0xf2, 0x9c, 0xde, 0x35, 0xd0, 0x13, 0xa8, 0x76, 0x6c, 0xcb, 0x23, 0x96, 0x37, 0xf4, - 0x74, 0x11, 0x1e, 0xa4, 0x03, 0x9e, 0x76, 0xb3, 0x76, 0x7c, 0xf6, 0x7d, 0xce, 0xad, 0xad, 0x74, - 0xe2, 0x1d, 0xe8, 0x21, 0xc0, 0x09, 0xee, 0x9b, 0x06, 0xa6, 0xb6, 0xeb, 0xd5, 0xb2, 0x17, 0x33, - 0x33, 0x94, 0x3d, 0xf5, 0x19, 0x8f, 0x1c, 0x03, 0x53, 0xd2, 0xc8, 0xb2, 0x99, 0x6b, 0x11, 0x79, - 0x74, 0x05, 0x56, 0xb0, 0xe3, 0xe8, 0x1e, 0xc5, 0x94, 0xe8, 0xed, 0x11, 0x25, 0x1e, 0x77, 0xd2, - 0xcb, 0x5a, 0x19, 0x3b, 0xce, 0x01, 0xeb, 0x6d, 0xb0, 0x4e, 0xd5, 0x08, 0x76, 0x9b, 0xfb, 0x43, - 0x84, 0x20, 0x6b, 0x60, 0x8a, 0xb9, 0xb5, 0x96, 0x35, 0xde, 0x66, 0x7d, 0x0e, 0xa6, 0x3d, 0x69, - 0x03, 0xde, 0x46, 0x17, 0x20, 0xd7, 0x23, 0x66, 0xb7, 0x47, 0xf9, 0xb2, 0x33, 0x9a, 0xa4, 0xd8, - 0xc6, 0x38, 0xae, 0x7d, 0x42, 0x78, 0x48, 0x29, 0x68, 0x82, 0x50, 0x7f, 0x9f, 0x86, 0xd5, 0x33, - 0x3e, 0x93, 0xe9, 0xed, 0x61, 0xaf, 0xe7, 0x8f, 0xc5, 0xda, 0xe8, 0x2e, 0xd3, 0x8b, 0x0d, 0xe2, - 0xca, 0x50, 0xb8, 0x16, 0xb5, 0x00, 0xdf, 0x33, 0x69, 0x82, 0x16, 0xe7, 0x92, 0x2b, 0x97, 0x32, - 0xe8, 0x08, 0xaa, 0x7d, 0xec, 0x51, 0x5d, 0x78, 0x1c, 0x9d, 0xc7, 0xb6, 0xcc, 0x4c, 0xff, 0xfb, - 0x10, 0xfb, 0x9e, 0x8a, 0x9d, 0x6e, 0xa9, 0xae, 0xd2, 0x8f, 0xf5, 0xa2, 0x67, 0x70, 0xbe, 0x3d, - 0xfa, 0x05, 0xb6, 0xa8, 0x69, 0x11, 0xfd, 0xcc, 0x26, 0xad, 0x4f, 0x51, 0xdd, 0x3c, 0x31, 0x0d, - 0x62, 0x75, 0xfc, 0xdd, 0x39, 0x17, 0xa8, 0x08, 0x76, 0xcf, 0x53, 0x9f, 0x41, 0x25, 0x1e, 0x01, - 0x50, 0x05, 0xd2, 0xf4, 0x54, 0x9a, 0x24, 0x4d, 0x4f, 0xd1, 0x77, 0x21, 0xcb, 0xd4, 0x71, 0x73, - 0x54, 0xa6, 0x86, 0x68, 0x29, 0x7d, 0x38, 0x72, 0x88, 0xc6, 0xf9, 0x55, 0x35, 0xb8, 0x0a, 0x41, - 0x54, 0x18, 0xd7, 0xad, 0x5e, 0x87, 0x95, 0x31, 0x87, 0x1f, 0xd9, 0x57, 0x25, 0xba, 0xaf, 0xea, - 0x0a, 0x94, 0x63, 0x7e, 0x5d, 0xbd, 0x00, 0xe7, 0x27, 0x39, 0x68, 0xd5, 0x0a, 0xfa, 0x63, 0x2e, - 0x16, 0xdd, 0x81, 0x42, 0xe0, 0xa1, 0xc5, 0x55, 0x9c, 0x66, 0x37, 0x5f, 0x44, 0x0b, 0x04, 0xd8, - 0x4d, 0x64, 0xa7, 0x99, 0x9f, 0x96, 0x34, 0x9f, 0x7e, 0x1e, 0x3b, 0x4e, 0x0b, 0x7b, 0x3d, 0xf5, - 0xe7, 0x50, 0x9b, 0xe6, 0x77, 0xc7, 0x16, 0x93, 0x0d, 0x0e, 0xe9, 0x05, 0xc8, 0x1d, 0xdb, 0xee, - 0x00, 0x53, 0xae, 0xac, 0xac, 0x49, 0x8a, 0x1d, 0x5e, 0xe1, 0x83, 0x33, 0xbc, 0x5b, 0x10, 0xaa, - 0x0e, 0xef, 0x4c, 0xf5, 0xba, 0x4c, 0xc4, 0xb4, 0x0c, 0x22, 0xac, 0x5a, 0xd6, 0x04, 0x11, 0x2a, - 0x12, 0x93, 0x15, 0x04, 0x1b, 0xd6, 0xe3, 0x2b, 0xe6, 0xfa, 0x8b, 0x9a, 0xa4, 0xd4, 0xbf, 0x14, - 0xa1, 0xa0, 0x11, 0xcf, 0x61, 0x0e, 0x01, 0xb5, 0xa0, 0x48, 0x4e, 0x3b, 0x44, 0xe0, 0x2a, 0x65, - 0x0e, 0x0a, 0x11, 0x32, 0x4d, 0x9f, 0x9f, 0x85, 0xfd, 0x40, 0x18, 0xdd, 0x8e, 0x61, 0xca, 0x4b, - 0xf3, 0x94, 0x44, 0x41, 0xe5, 0xdd, 0x38, 0xa8, 0x7c, 0x7f, 0x8e, 0xec, 0x18, 0xaa, 0xbc, 0x1d, - 0x43, 0x95, 0xf3, 0x06, 0x8e, 0xc1, 0xca, 0xdd, 0x09, 0xb0, 0x72, 0xde, 0xf2, 0xa7, 0xe0, 0xca, - 0xdd, 0x09, 0xb8, 0xf2, 0xda, 0xdc, 0xb9, 0x4c, 0x04, 0x96, 0x77, 0xe3, 0xc0, 0x72, 0x9e, 0x39, - 0xc6, 0x90, 0xe5, 0xc3, 0x49, 0xc8, 0xf2, 0xfa, 0x1c, 0x1d, 0x53, 0xa1, 0xe5, 0xce, 0x19, 0x68, - 0x79, 0x65, 0x8e, 0xaa, 0x09, 0xd8, 0x72, 0x37, 0x86, 0x2d, 0x21, 0x91, 0x6d, 0xa6, 0x80, 0xcb, - 0xfb, 0x67, 0xc1, 0xe5, 0xd5, 0x79, 0x47, 0x6d, 0x12, 0xba, 0xfc, 0xe1, 0x18, 0xba, 0xbc, 0x3c, - 0x6f, 0x55, 0xe3, 0xf0, 0xf2, 0x68, 0x0a, 0xbc, 0xbc, 0x31, 0x47, 0xd1, 0x1c, 0x7c, 0x79, 0x34, - 0x05, 0x5f, 0xce, 0x53, 0x3b, 0x07, 0x60, 0xb6, 0x67, 0x01, 0xcc, 0x9b, 0xf3, 0xa6, 0x9c, 0x0c, - 0x61, 0x92, 0x99, 0x08, 0xf3, 0xa3, 0x39, 0x83, 0x2c, 0x0e, 0x31, 0xaf, 0xb3, 0x20, 0x3f, 0xe6, - 0x92, 0x98, 0x2b, 0x24, 0xae, 0x6b, 0xbb, 0x12, 0xbd, 0x09, 0x42, 0xbd, 0xc6, 0x60, 0x47, 0xe8, - 0x78, 0x66, 0xc0, 0x51, 0x1e, 0x78, 0x22, 0x6e, 0x46, 0xfd, 0xb3, 0x12, 0xca, 0xf2, 0xe8, 0x1c, - 0x85, 0x2c, 0x45, 0x09, 0x59, 0x22, 0x28, 0x35, 0x1d, 0x47, 0xa9, 0xeb, 0x50, 0x62, 0xa1, 0x64, - 0x0c, 0x80, 0x62, 0xc7, 0x07, 0xa0, 0xe8, 0x03, 0x58, 0xe5, 0x18, 0x42, 0x60, 0x59, 0x19, 0x3f, - 0xb2, 0x3c, 0x18, 0xae, 0xb0, 0x0f, 0xe2, 0xe8, 0x8a, 0x40, 0xf2, 0x6d, 0x38, 0x17, 0xe1, 0x0d, - 0x42, 0x94, 0x40, 0x5a, 0xd5, 0x80, 0x7b, 0x5b, 0xc6, 0xaa, 0x47, 0xa1, 0x81, 0x42, 0x70, 0x8b, - 0x20, 0xdb, 0xb1, 0x0d, 0x22, 0x03, 0x08, 0x6f, 0x33, 0xc0, 0xdb, 0xb7, 0xbb, 0x32, 0x4c, 0xb0, - 0x26, 0xe3, 0x0a, 0x7c, 0x6a, 0x51, 0x38, 0x4b, 0xf5, 0x4f, 0x4a, 0xa8, 0x2f, 0xc4, 0xbb, 0x93, - 0xa0, 0xa9, 0xf2, 0x26, 0xa1, 0x69, 0xfa, 0x7f, 0x83, 0xa6, 0xea, 0x7f, 0x94, 0x70, 0x4b, 0x03, - 0xd0, 0xf9, 0xcd, 0x4c, 0x10, 0x86, 0xdf, 0x25, 0xbe, 0x41, 0x32, 0xfc, 0xca, 0x7c, 0x21, 0xc7, - 0xb7, 0x21, 0x9e, 0x2f, 0xe4, 0x45, 0x40, 0xe6, 0x04, 0xfa, 0x0e, 0x07, 0xab, 0xf6, 0xb1, 0xf4, - 0xc9, 0x31, 0x40, 0x22, 0x8a, 0x46, 0x1b, 0xb2, 0x5a, 0xb4, 0xcf, 0xd8, 0x34, 0xc1, 0x1d, 0x81, - 0x15, 0xc5, 0x18, 0xf6, 0x7d, 0x17, 0x8a, 0x6c, 0xea, 0x9e, 0x83, 0x3b, 0x84, 0x3b, 0xd5, 0xa2, - 0x16, 0x76, 0xa8, 0x06, 0xa0, 0xb3, 0xce, 0x1d, 0x3d, 0x86, 0x1c, 0x39, 0x21, 0x16, 0x65, 0x7b, - 0xc4, 0xcc, 0xfa, 0xee, 0x54, 0x30, 0x49, 0x2c, 0xda, 0xa8, 0x31, 0x63, 0xfe, 0xeb, 0xeb, 0xf5, - 0xaa, 0x90, 0xb9, 0x61, 0x0f, 0x4c, 0x4a, 0x06, 0x0e, 0x1d, 0x69, 0x52, 0x8b, 0xfa, 0x9b, 0x34, - 0xc3, 0x74, 0x31, 0xc7, 0x3f, 0xd1, 0xbc, 0xfe, 0xa5, 0x49, 0x47, 0x70, 0x7e, 0x32, 0x93, 0xbf, - 0x07, 0xd0, 0xc5, 0x9e, 0xfe, 0x02, 0x5b, 0x94, 0x18, 0xd2, 0xee, 0xc5, 0x2e, 0xf6, 0x7e, 0xc2, - 0x3b, 0x18, 0x54, 0x63, 0x9f, 0x87, 0x1e, 0x31, 0xf8, 0x06, 0x64, 0xb4, 0x7c, 0x17, 0x7b, 0x47, - 0x1e, 0x31, 0x22, 0x6b, 0xcd, 0xbf, 0x89, 0xb5, 0xc6, 0xed, 0x5d, 0x18, 0xb7, 0xf7, 0x6f, 0xd3, - 0xe1, 0xed, 0x08, 0x21, 0xf0, 0xff, 0xa7, 0x2d, 0xfe, 0xc0, 0x13, 0xe3, 0x78, 0xf4, 0x45, 0x9f, - 0xc0, 0x6a, 0x70, 0x2b, 0xf5, 0x21, 0xbf, 0xad, 0xfe, 0x29, 0x5c, 0xec, 0x72, 0x57, 0x4f, 0xe2, - 0xdd, 0x1e, 0xfa, 0x14, 0xde, 0x1e, 0xf3, 0x41, 0xc1, 0x00, 0xe9, 0x85, 0x5c, 0xd1, 0x5b, 0x71, - 0x57, 0xe4, 0xeb, 0x0f, 0xad, 0x97, 0x79, 0x23, 0xb7, 0x66, 0x97, 0xa5, 0x61, 0x51, 0x5c, 0x31, - 0xf1, 0x4c, 0x5c, 0x82, 0xb2, 0x4b, 0x28, 0x36, 0x2d, 0x3d, 0x96, 0xfa, 0x2e, 0x8b, 0x4e, 0x11, - 0x12, 0xd4, 0xa7, 0xf0, 0xd6, 0x44, 0x64, 0x81, 0xbe, 0x0f, 0xc5, 0x10, 0x9a, 0x28, 0x33, 0x33, - 0xc7, 0x20, 0x03, 0x0a, 0x25, 0xd4, 0x2f, 0x94, 0x50, 0x71, 0x3c, 0xb3, 0x7a, 0x00, 0x39, 0x97, - 0x78, 0xc3, 0xbe, 0xc8, 0x72, 0x2a, 0x5b, 0x1f, 0x2f, 0x82, 0x4c, 0x58, 0xef, 0xb0, 0x4f, 0x35, - 0xa9, 0x42, 0x7d, 0x02, 0x39, 0xd1, 0x83, 0x00, 0x72, 0xdb, 0x3b, 0x3b, 0xcd, 0xfd, 0xc3, 0x6a, - 0x0a, 0x15, 0x61, 0x69, 0xbb, 0xb1, 0xa7, 0x1d, 0x56, 0x15, 0xd6, 0xad, 0x35, 0x7f, 0xdc, 0xdc, - 0x39, 0xac, 0xa6, 0xd1, 0x2a, 0x94, 0x45, 0x5b, 0xbf, 0xbf, 0xa7, 0x3d, 0xda, 0x3e, 0xac, 0x66, - 0x22, 0x5d, 0x07, 0xcd, 0xc7, 0xf7, 0x9a, 0x5a, 0x35, 0xab, 0x7e, 0xc4, 0xf2, 0xa7, 0x29, 0xc0, - 0x25, 0xcc, 0x94, 0x94, 0x48, 0xa6, 0xa4, 0xfe, 0x2e, 0x0d, 0xf5, 0xe9, 0x38, 0x04, 0xed, 0x8f, - 0xad, 0xf8, 0xd6, 0xc2, 0x50, 0x66, 0x6c, 0xd9, 0xe8, 0x32, 0x54, 0x5c, 0x72, 0x4c, 0x68, 0xa7, - 0x27, 0x30, 0x92, 0x88, 0x72, 0x65, 0xad, 0x2c, 0x7b, 0xb9, 0x90, 0x27, 0xd8, 0x3e, 0x23, 0x1d, - 0xaa, 0x8b, 0xd4, 0x4d, 0x9c, 0xbf, 0x22, 0x63, 0x63, 0xbd, 0x07, 0xa2, 0x53, 0x3d, 0x98, 0x67, - 0xc4, 0x22, 0x2c, 0x69, 0xcd, 0x43, 0xed, 0x93, 0x6a, 0x1a, 0x21, 0xa8, 0xf0, 0xa6, 0x7e, 0xf0, - 0x78, 0x7b, 0xff, 0xa0, 0xb5, 0xc7, 0x8c, 0x78, 0x0e, 0x56, 0x7c, 0x23, 0xfa, 0x9d, 0x59, 0xf5, - 0xaf, 0x0a, 0xac, 0x8c, 0x5d, 0x0f, 0x74, 0x0b, 0x96, 0x04, 0xf0, 0x56, 0x66, 0x16, 0xf0, 0xf9, - 0x7d, 0x97, 0x37, 0x4a, 0x08, 0xa0, 0x06, 0x14, 0x88, 0xac, 0x4f, 0x4c, 0xba, 0x92, 0xd1, 0x4a, - 0x8b, 0x5f, 0xc7, 0x90, 0x0a, 0x02, 0x39, 0xd4, 0x84, 0x62, 0x70, 0xf3, 0x65, 0xa6, 0x78, 0x75, - 0x9a, 0x92, 0xc0, 0x73, 0x48, 0x2d, 0xa1, 0xa4, 0xba, 0x03, 0xa5, 0xc8, 0x04, 0xd1, 0xb7, 0xa0, - 0x38, 0xc0, 0xa7, 0xb2, 0x66, 0x25, 0x8a, 0x10, 0x85, 0x01, 0x3e, 0xe5, 0xe5, 0x2a, 0xf4, 0x36, - 0xe4, 0xd9, 0xc7, 0x2e, 0x16, 0x8e, 0x24, 0xa3, 0xe5, 0x06, 0xf8, 0xf4, 0x47, 0xd8, 0x53, 0x3b, - 0x50, 0x89, 0x97, 0x72, 0xd8, 0xc9, 0x72, 0xed, 0xa1, 0x65, 0x70, 0x1d, 0x4b, 0x9a, 0x20, 0xd0, - 0x1d, 0x58, 0x3a, 0xb1, 0x85, 0x1f, 0x9a, 0x75, 0x03, 0x9f, 0xda, 0x94, 0x44, 0x0a, 0x42, 0x42, - 0x46, 0x7d, 0x0c, 0x15, 0xee, 0x51, 0xb6, 0x29, 0x75, 0xcd, 0xf6, 0x90, 0x92, 0x68, 0x65, 0x72, - 0x79, 0x42, 0x65, 0x32, 0x40, 0x1a, 0x01, 0x4e, 0xc9, 0x88, 0xb2, 0x18, 0x27, 0xd4, 0x5f, 0x29, - 0xb0, 0xc4, 0x15, 0x32, 0x77, 0xc3, 0xab, 0x3c, 0x12, 0xc3, 0xb2, 0x36, 0xea, 0x00, 0x60, 0x7f, - 0x20, 0x7f, 0xbe, 0x97, 0x67, 0x39, 0xba, 0x60, 0x5a, 0x8d, 0x77, 0xa5, 0xc7, 0x3b, 0x1f, 0x2a, - 0x88, 0x78, 0xbd, 0x88, 0x5a, 0xf5, 0xa5, 0x02, 0x85, 0xc3, 0x53, 0x79, 0x5a, 0xa7, 0x14, 0x7f, - 0xd8, 0xec, 0x77, 0xf9, 0xec, 0x45, 0xb9, 0x44, 0x10, 0xb2, 0x9a, 0x94, 0x09, 0x2a, 0x55, 0xf7, - 0x83, 0x5b, 0x99, 0x5d, 0x2c, 0xa1, 0xf4, 0x8b, 0x78, 0xd2, 0x05, 0xf5, 0x21, 0xcf, 0xcf, 0xc3, - 0xee, 0xbd, 0x89, 0x15, 0xc2, 0x47, 0xb0, 0xec, 0x60, 0x97, 0x7a, 0x7a, 0xac, 0x4e, 0x38, 0x2d, - 0x27, 0xdf, 0xc7, 0x2e, 0x3d, 0x20, 0x34, 0x56, 0x2d, 0x2c, 0x71, 0x79, 0xd1, 0xa5, 0xde, 0x86, - 0x72, 0x8c, 0x87, 0x2d, 0x96, 0xda, 0x14, 0xf7, 0xfd, 0x73, 0xc3, 0x89, 0x60, 0x26, 0xe9, 0x70, - 0x26, 0xea, 0x1d, 0x28, 0x06, 0xc7, 0x9a, 0x65, 0x1c, 0xd8, 0x30, 0x5c, 0xe2, 0x79, 0x72, 0xb6, - 0x3e, 0xc9, 0x4b, 0xa2, 0xf6, 0x0b, 0x59, 0xf5, 0xc9, 0x68, 0x82, 0x50, 0x09, 0xac, 0x8c, 0x45, - 0x53, 0x74, 0x17, 0xf2, 0xce, 0xb0, 0xad, 0xfb, 0x07, 0xaa, 0xb4, 0xf5, 0xde, 0xb4, 0x45, 0x0d, - 0xdb, 0x0f, 0xc8, 0xc8, 0x37, 0x9b, 0xc3, 0xa9, 0x70, 0x98, 0x74, 0x74, 0x98, 0x5f, 0x42, 0xc1, - 0x3f, 0xcb, 0xe8, 0x5e, 0xf4, 0xbe, 0x8a, 0x11, 0x2e, 0xce, 0x0b, 0xf4, 0x72, 0x90, 0x50, 0x90, - 0xe5, 0x47, 0x9e, 0xd9, 0xb5, 0x88, 0xa1, 0x87, 0xa9, 0x0f, 0x1f, 0xb3, 0xa0, 0xad, 0x88, 0x0f, - 0x0f, 0xfd, 0xbc, 0x47, 0xbd, 0x09, 0x39, 0x31, 0xd7, 0x89, 0x07, 0x7c, 0x42, 0x8c, 0x55, 0xff, - 0xa9, 0x40, 0xc1, 0x77, 0x38, 0x13, 0x85, 0x62, 0x8b, 0x48, 0x7f, 0xd3, 0x45, 0x4c, 0x2b, 0x5f, - 0xfb, 0x8f, 0x05, 0xd9, 0x85, 0x1f, 0x0b, 0x6e, 0x00, 0xe2, 0x27, 0x45, 0x3f, 0xb1, 0xa9, 0x69, - 0x75, 0x75, 0xb1, 0x17, 0x02, 0x12, 0x56, 0xf9, 0x97, 0xa7, 0xfc, 0xc3, 0x3e, 0xdf, 0x96, 0x5f, - 0x2b, 0x50, 0x08, 0x02, 0xf8, 0xa2, 0x65, 0xca, 0x0b, 0x90, 0x93, 0x41, 0x4a, 0xd4, 0x29, 0x25, - 0x15, 0x9c, 0xd1, 0x6c, 0xe4, 0xb6, 0xd4, 0xa1, 0x30, 0x20, 0x14, 0x73, 0x3b, 0x8b, 0xb4, 0x34, - 0xa0, 0x3f, 0xb8, 0x04, 0xa5, 0x48, 0xdd, 0x18, 0xe5, 0x21, 0xf3, 0x98, 0xbc, 0xa8, 0xa6, 0x50, - 0x09, 0xf2, 0x1a, 0xe1, 0xa5, 0xa2, 0xaa, 0xb2, 0xf5, 0x45, 0x09, 0x56, 0xb6, 0x1b, 0x3b, 0xbb, - 0x2c, 0x86, 0x9a, 0x1d, 0xcc, 0x53, 0xd6, 0x3d, 0xc8, 0xf2, 0xac, 0x3d, 0xc1, 0x3b, 0x75, 0x3d, - 0x49, 0xdd, 0x11, 0x69, 0xb0, 0xc4, 0x93, 0x7b, 0x94, 0xe4, 0xf9, 0xba, 0x9e, 0xa8, 0x1c, 0xc9, - 0x26, 0xc9, 0x4f, 0x7d, 0x82, 0x57, 0xed, 0x7a, 0x92, 0x1a, 0x25, 0xfa, 0x14, 0x8a, 0x61, 0xd6, - 0x9e, 0xf4, 0xad, 0xbb, 0x9e, 0xb8, 0x7a, 0xc9, 0xf4, 0x87, 0x79, 0x4a, 0xd2, 0x97, 0xde, 0x7a, - 0x62, 0x2f, 0x8b, 0x9e, 0x41, 0xde, 0xcf, 0x08, 0x93, 0xbd, 0x46, 0xd7, 0x13, 0x56, 0x16, 0xd9, - 0xf6, 0x89, 0x44, 0x3e, 0xc9, 0x93, 0x7b, 0x3d, 0x51, 0xf9, 0x14, 0x1d, 0x41, 0x4e, 0x42, 0xf1, - 0x44, 0xef, 0xcc, 0xf5, 0x64, 0xf5, 0x42, 0x66, 0xe4, 0xb0, 0x54, 0x92, 0xf4, 0x67, 0x06, 0xf5, - 0xc4, 0x75, 0x63, 0x84, 0x01, 0x22, 0xd9, 0x7d, 0xe2, 0xdf, 0x0f, 0xd4, 0x93, 0xd7, 0x83, 0xd1, - 0xcf, 0xa0, 0x10, 0xe4, 0x70, 0x09, 0xdf, 0xf1, 0xeb, 0x49, 0x4b, 0xb2, 0xe8, 0x33, 0x28, 0xc7, - 0xd3, 0x96, 0x45, 0x5e, 0xe7, 0xeb, 0x0b, 0xd5, 0x5a, 0xd9, 0x58, 0xf1, 0x4c, 0x66, 0x91, 0x37, - 0xfb, 0xfa, 0x42, 0x05, 0x58, 0x74, 0x02, 0xab, 0x67, 0x93, 0x8f, 0x45, 0x1f, 0xf2, 0xeb, 0x0b, - 0x17, 0x66, 0xd1, 0x08, 0xd0, 0x84, 0x04, 0x66, 0xe1, 0xd7, 0xfd, 0xfa, 0xe2, 0xd5, 0xda, 0x46, - 0xf3, 0xcb, 0x57, 0x6b, 0xca, 0x57, 0xaf, 0xd6, 0x94, 0x7f, 0xbc, 0x5a, 0x53, 0x5e, 0xbe, 0x5e, - 0x4b, 0x7d, 0xf5, 0x7a, 0x2d, 0xf5, 0xb7, 0xd7, 0x6b, 0xa9, 0x9f, 0x7e, 0xd8, 0x35, 0x69, 0x6f, - 0xd8, 0xde, 0xe8, 0xd8, 0x83, 0xcd, 0x50, 0x6d, 0xb4, 0x19, 0xfe, 0xc2, 0xaa, 0x9d, 0xe3, 0xc1, - 0xef, 0xe3, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x31, 0x8d, 0x36, 0x76, 0x25, 0x00, 0x00, + // 2699 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x6f, 0x1b, 0xc9, + 0xf1, 0xe7, 0x90, 0x14, 0x1f, 0x45, 0x91, 0xa2, 0xda, 0x5e, 0x2f, 0x97, 0xff, 0x5d, 0xc9, 0x18, + 0xaf, 0x1f, 0xfb, 0xf8, 0x4b, 0xbb, 0x5a, 0x20, 0xb0, 0x63, 0x27, 0x81, 0x28, 0xcb, 0xa1, 0xe2, + 0x87, 0xe4, 0x91, 0xe4, 0x78, 0x13, 0x60, 0x27, 0xcd, 0x99, 0x16, 0x39, 0x6b, 0x72, 0x66, 0x76, + 0xa6, 0x29, 0x8b, 0x41, 0x0e, 0x41, 0x10, 0x20, 0xc8, 0xcd, 0xb9, 0xe4, 0x96, 0xef, 0x90, 0x43, + 0x80, 0xcd, 0x17, 0x08, 0xb0, 0xc7, 0x3d, 0x05, 0x39, 0x6d, 0x02, 0x3b, 0xa7, 0xe4, 0x4b, 0x04, + 0xfd, 0x98, 0x17, 0xc5, 0xc7, 0x70, 0xe3, 0x5b, 0x2e, 0x44, 0x57, 0x4f, 0x55, 0x75, 0x77, 0x75, + 0x77, 0xd5, 0xaf, 0xaa, 0x09, 0x97, 0x70, 0xc7, 0xb0, 0x36, 0xe9, 0xc8, 0x25, 0xbe, 0xf8, 0xdd, + 0x70, 0x3d, 0x87, 0x3a, 0xe8, 0x0d, 0x4a, 0x6c, 0x93, 0x78, 0x03, 0xcb, 0xa6, 0x1b, 0x8c, 0x65, + 0x83, 0x7f, 0x6c, 0xae, 0xf3, 0xaf, 0x9b, 0x86, 0x37, 0x72, 0xa9, 0xb3, 0x39, 0x20, 0xde, 0xb3, + 0x3e, 0x89, 0xcb, 0x35, 0xdf, 0x14, 0x0c, 0xe7, 0x14, 0x36, 0x1b, 0xf1, 0x0f, 0x2e, 0xf6, 0xf0, + 0x20, 0xf8, 0xb2, 0xde, 0x75, 0x9c, 0x6e, 0x9f, 0x6c, 0x72, 0xaa, 0x33, 0x3c, 0xd9, 0xa4, 0xd6, + 0x80, 0xf8, 0x14, 0x0f, 0x5c, 0xc9, 0x70, 0x8d, 0xf6, 0x2c, 0xcf, 0xd4, 0x5d, 0xec, 0xd1, 0x91, + 0xe0, 0xda, 0xec, 0x3a, 0x5d, 0x27, 0x6a, 0x09, 0x3e, 0xf5, 0xdf, 0x25, 0x28, 0x6a, 0xe4, 0x8b, + 0x21, 0xf1, 0x29, 0xba, 0x09, 0x79, 0x62, 0xf4, 0x9c, 0x46, 0xf6, 0xb2, 0x72, 0xa3, 0xb2, 0xa5, + 0x6e, 0x4c, 0x5c, 0xce, 0x86, 0xe4, 0xde, 0x35, 0x7a, 0x4e, 0x3b, 0xa3, 0x71, 0x09, 0x74, 0x1b, + 0x96, 0x4e, 0xfa, 0x43, 0xbf, 0xd7, 0xc8, 0x71, 0xd1, 0x2b, 0xb3, 0x45, 0xef, 0x31, 0xd6, 0x76, + 0x46, 0x13, 0x32, 0x6c, 0x58, 0xcb, 0x3e, 0x71, 0x1a, 0xf9, 0x34, 0xc3, 0xee, 0xd9, 0x27, 0x7c, + 0x58, 0x26, 0x81, 0xda, 0x00, 0x3e, 0xa1, 0xba, 0xe3, 0x52, 0xcb, 0xb1, 0x1b, 0x4b, 0x5c, 0xfe, + 0xfa, 0x6c, 0xf9, 0x43, 0x42, 0xf7, 0x39, 0x7b, 0x3b, 0xa3, 0x95, 0xfd, 0x80, 0x60, 0x9a, 0x2c, + 0xdb, 0xa2, 0xba, 0xd1, 0xc3, 0x96, 0xdd, 0x28, 0xa4, 0xd1, 0xb4, 0x67, 0x5b, 0x74, 0x87, 0xb1, + 0x33, 0x4d, 0x56, 0x40, 0x30, 0x53, 0x7c, 0x31, 0x24, 0xde, 0xa8, 0x51, 0x4c, 0x63, 0x8a, 0xc7, + 0x8c, 0x95, 0x99, 0x82, 0xcb, 0xa0, 0xfb, 0x50, 0xe9, 0x90, 0xae, 0x65, 0xeb, 0x9d, 0xbe, 0x63, + 0x3c, 0x6b, 0x94, 0xb8, 0x8a, 0x1b, 0xb3, 0x55, 0xb4, 0x98, 0x40, 0x8b, 0xf1, 0xb7, 0x33, 0x1a, + 0x74, 0x42, 0x0a, 0xb5, 0xa0, 0x64, 0xf4, 0x88, 0xf1, 0x4c, 0xa7, 0x67, 0x8d, 0x32, 0xd7, 0x74, + 0x75, 0xb6, 0xa6, 0x1d, 0xc6, 0x7d, 0x74, 0xd6, 0xce, 0x68, 0x45, 0x43, 0x34, 0x99, 0x5d, 0x4c, + 0xd2, 0xb7, 0x4e, 0x89, 0xc7, 0xb4, 0x5c, 0x48, 0x63, 0x97, 0xbb, 0x82, 0x9f, 0xeb, 0x29, 0x9b, + 0x01, 0x81, 0x76, 0xa1, 0x4c, 0x6c, 0x53, 0x2e, 0xac, 0xc2, 0x15, 0x5d, 0x9b, 0x73, 0xc2, 0x6c, + 0x33, 0x58, 0x56, 0x89, 0xc8, 0x36, 0xfa, 0x3e, 0x14, 0x0c, 0x67, 0x30, 0xb0, 0x68, 0x63, 0x99, + 0xeb, 0x78, 0x77, 0xce, 0x92, 0x38, 0x6f, 0x3b, 0xa3, 0x49, 0x29, 0x74, 0x04, 0xb5, 0xbe, 0xe5, + 0x53, 0xdd, 0xb7, 0xb1, 0xeb, 0xf7, 0x1c, 0xea, 0x37, 0xaa, 0x5c, 0xcf, 0x07, 0xb3, 0xf5, 0x3c, + 0xb0, 0x7c, 0x7a, 0x18, 0x88, 0xb4, 0x33, 0x5a, 0xb5, 0x1f, 0xef, 0x60, 0x5a, 0x9d, 0x93, 0x13, + 0xe2, 0x85, 0x6a, 0x1b, 0xb5, 0x34, 0x5a, 0xf7, 0x99, 0x4c, 0xa0, 0x85, 0x69, 0x75, 0xe2, 0x1d, + 0x08, 0xc3, 0x85, 0xbe, 0x83, 0xcd, 0x50, 0xa9, 0x6e, 0xf4, 0x86, 0xf6, 0xb3, 0xc6, 0x0a, 0x57, + 0xbd, 0x39, 0x67, 0xc2, 0x0e, 0x36, 0x03, 0x45, 0x3b, 0x4c, 0xac, 0x9d, 0xd1, 0x56, 0xfb, 0xe3, + 0x9d, 0xc8, 0x84, 0x8b, 0xd8, 0x75, 0xfb, 0xa3, 0xf1, 0x31, 0xea, 0x7c, 0x8c, 0x8f, 0x66, 0x8f, + 0xb1, 0xcd, 0x24, 0xc7, 0x07, 0x41, 0xf8, 0x5c, 0x6f, 0xab, 0x08, 0x4b, 0xa7, 0xb8, 0x3f, 0x24, + 0xea, 0x75, 0xa8, 0xc4, 0xdc, 0x07, 0x6a, 0x40, 0x71, 0x40, 0x7c, 0x1f, 0x77, 0x49, 0x43, 0xb9, + 0xac, 0xdc, 0x28, 0x6b, 0x01, 0xa9, 0xd6, 0x60, 0x39, 0xee, 0x2c, 0xd4, 0x41, 0x28, 0xc8, 0x1c, + 0x00, 0x13, 0x3c, 0x25, 0x9e, 0xcf, 0x6e, 0xbd, 0x14, 0x94, 0x24, 0xba, 0x02, 0x55, 0x7e, 0xc4, + 0xf4, 0xe0, 0x3b, 0x73, 0x66, 0x79, 0x6d, 0x99, 0x77, 0x3e, 0x91, 0x4c, 0xeb, 0x50, 0x71, 0xb7, + 0xdc, 0x90, 0x25, 0xc7, 0x59, 0xc0, 0xdd, 0x72, 0x25, 0x83, 0xfa, 0x5d, 0xa8, 0x8f, 0xfb, 0x0b, + 0x54, 0x87, 0xdc, 0x33, 0x32, 0x92, 0xe3, 0xb1, 0x26, 0xba, 0x28, 0x97, 0xc5, 0xc7, 0x28, 0x6b, + 0x72, 0x8d, 0x7f, 0xcc, 0x86, 0xc2, 0xa1, 0x8b, 0x60, 0x3e, 0x8e, 0x79, 0x68, 0x2e, 0x5d, 0xd9, + 0x6a, 0x6e, 0x08, 0xf7, 0xbd, 0x11, 0xb8, 0xef, 0x8d, 0xa3, 0xc0, 0x7d, 0xb7, 0x4a, 0x5f, 0x7d, + 0xb3, 0x9e, 0x79, 0xf1, 0xf7, 0x75, 0x45, 0xe3, 0x12, 0xe8, 0x2d, 0x76, 0x8b, 0xb1, 0x65, 0xeb, + 0x96, 0x29, 0xc7, 0x29, 0x72, 0x7a, 0xcf, 0x44, 0x8f, 0xa1, 0x6e, 0x38, 0xb6, 0x4f, 0x6c, 0x7f, + 0xe8, 0xeb, 0x22, 0x3c, 0x48, 0x07, 0x3c, 0xed, 0x66, 0xed, 0x04, 0xec, 0x07, 0x9c, 0x5b, 0x5b, + 0x31, 0x92, 0x1d, 0xe8, 0x01, 0xc0, 0x29, 0xee, 0x5b, 0x26, 0xa6, 0x8e, 0xe7, 0x37, 0xf2, 0x97, + 0x73, 0x33, 0x94, 0x3d, 0x09, 0x18, 0x8f, 0x5d, 0x13, 0x53, 0xd2, 0xca, 0xb3, 0x99, 0x6b, 0x31, + 0x79, 0x74, 0x0d, 0x56, 0xb0, 0xeb, 0xea, 0x3e, 0xc5, 0x94, 0xe8, 0x9d, 0x11, 0x25, 0x3e, 0x77, + 0xd2, 0xcb, 0x5a, 0x15, 0xbb, 0xee, 0x21, 0xeb, 0x6d, 0xb1, 0x4e, 0xd5, 0x0c, 0x77, 0x9b, 0xfb, + 0x43, 0x84, 0x20, 0x6f, 0x62, 0x8a, 0xb9, 0xb5, 0x96, 0x35, 0xde, 0x66, 0x7d, 0x2e, 0xa6, 0x3d, + 0x69, 0x03, 0xde, 0x46, 0x97, 0xa0, 0xd0, 0x23, 0x56, 0xb7, 0x47, 0xf9, 0xb2, 0x73, 0x9a, 0xa4, + 0xd8, 0xc6, 0xb8, 0x9e, 0x73, 0x4a, 0x78, 0x48, 0x29, 0x69, 0x82, 0x50, 0x7f, 0x9f, 0x85, 0xd5, + 0x73, 0x3e, 0x93, 0xe9, 0xed, 0x61, 0xbf, 0x17, 0x8c, 0xc5, 0xda, 0xe8, 0x0e, 0xd3, 0x8b, 0x4d, + 0xe2, 0xc9, 0x50, 0xb8, 0x16, 0xb7, 0x00, 0xdf, 0x33, 0x69, 0x82, 0x36, 0xe7, 0x92, 0x2b, 0x97, + 0x32, 0xe8, 0x18, 0xea, 0x7d, 0xec, 0x53, 0x5d, 0x78, 0x1c, 0x9d, 0xc7, 0xb6, 0xdc, 0x4c, 0xff, + 0xfb, 0x00, 0x07, 0x9e, 0x8a, 0x9d, 0x6e, 0xa9, 0xae, 0xd6, 0x4f, 0xf4, 0xa2, 0xa7, 0x70, 0xb1, + 0x33, 0xfa, 0x39, 0xb6, 0xa9, 0x65, 0x13, 0xfd, 0xdc, 0x26, 0xad, 0x4f, 0x51, 0xbd, 0x7b, 0x6a, + 0x99, 0xc4, 0x36, 0x82, 0xdd, 0xb9, 0x10, 0xaa, 0x08, 0x77, 0xcf, 0x57, 0x9f, 0x42, 0x2d, 0x19, + 0x01, 0x50, 0x0d, 0xb2, 0xf4, 0x4c, 0x9a, 0x24, 0x4b, 0xcf, 0xd0, 0x77, 0x20, 0xcf, 0xd4, 0x71, + 0x73, 0xd4, 0xa6, 0x86, 0x68, 0x29, 0x7d, 0x34, 0x72, 0x89, 0xc6, 0xf9, 0x55, 0x35, 0xbc, 0x0a, + 0x61, 0x54, 0x18, 0xd7, 0xad, 0xbe, 0x07, 0x2b, 0x63, 0x0e, 0x3f, 0xb6, 0xaf, 0x4a, 0x7c, 0x5f, + 0xd5, 0x15, 0xa8, 0x26, 0xfc, 0xba, 0x7a, 0x09, 0x2e, 0x4e, 0x72, 0xd0, 0xaa, 0x1d, 0xf6, 0x27, + 0x5c, 0x2c, 0xba, 0x0d, 0xa5, 0xd0, 0x43, 0x8b, 0xab, 0x38, 0xcd, 0x6e, 0x81, 0x88, 0x16, 0x0a, + 0xb0, 0x9b, 0xc8, 0x4e, 0x33, 0x3f, 0x2d, 0x59, 0x3e, 0xfd, 0x22, 0x76, 0xdd, 0x36, 0xf6, 0x7b, + 0xea, 0xcf, 0xa0, 0x31, 0xcd, 0xef, 0x8e, 0x2d, 0x26, 0x1f, 0x1e, 0xd2, 0x4b, 0x50, 0x38, 0x71, + 0xbc, 0x01, 0xa6, 0x5c, 0x59, 0x55, 0x93, 0x14, 0x3b, 0xbc, 0xc2, 0x07, 0xe7, 0x78, 0xb7, 0x20, + 0x54, 0x1d, 0xde, 0x9a, 0xea, 0x75, 0x99, 0x88, 0x65, 0x9b, 0x44, 0x58, 0xb5, 0xaa, 0x09, 0x22, + 0x52, 0x24, 0x26, 0x2b, 0x08, 0x36, 0xac, 0xcf, 0x57, 0xcc, 0xf5, 0x97, 0x35, 0x49, 0xa9, 0x7f, + 0x29, 0x43, 0x49, 0x23, 0xbe, 0xcb, 0x1c, 0x02, 0x6a, 0x43, 0x99, 0x9c, 0x19, 0x44, 0xe0, 0x2a, + 0x65, 0x0e, 0x0a, 0x11, 0x32, 0xbb, 0x01, 0x3f, 0x0b, 0xfb, 0xa1, 0x30, 0xba, 0x95, 0xc0, 0x94, + 0x57, 0xe6, 0x29, 0x89, 0x83, 0xca, 0x3b, 0x49, 0x50, 0xf9, 0xee, 0x1c, 0xd9, 0x31, 0x54, 0x79, + 0x2b, 0x81, 0x2a, 0xe7, 0x0d, 0x9c, 0x80, 0x95, 0x7b, 0x13, 0x60, 0xe5, 0xbc, 0xe5, 0x4f, 0xc1, + 0x95, 0x7b, 0x13, 0x70, 0xe5, 0x8d, 0xb9, 0x73, 0x99, 0x08, 0x2c, 0xef, 0x24, 0x81, 0xe5, 0x3c, + 0x73, 0x8c, 0x21, 0xcb, 0x07, 0x93, 0x90, 0xe5, 0x7b, 0x73, 0x74, 0x4c, 0x85, 0x96, 0x3b, 0xe7, + 0xa0, 0xe5, 0xb5, 0x39, 0xaa, 0x26, 0x60, 0xcb, 0xbd, 0x04, 0xb6, 0x84, 0x54, 0xb6, 0x99, 0x02, + 0x2e, 0xef, 0x9d, 0x07, 0x97, 0xd7, 0xe7, 0x1d, 0xb5, 0x49, 0xe8, 0xf2, 0x07, 0x63, 0xe8, 0xf2, + 0xea, 0xbc, 0x55, 0x8d, 0xc3, 0xcb, 0xe3, 0x29, 0xf0, 0xf2, 0xc3, 0x39, 0x8a, 0xe6, 0xe0, 0xcb, + 0xe3, 0x29, 0xf8, 0x72, 0x9e, 0xda, 0x39, 0x00, 0xb3, 0x33, 0x0b, 0x60, 0x7e, 0x34, 0x6f, 0xca, + 0xe9, 0x10, 0x26, 0x99, 0x89, 0x30, 0x3f, 0x9e, 0x33, 0xc8, 0xe2, 0x10, 0xf3, 0x3d, 0x16, 0xe4, + 0xc7, 0x5c, 0x12, 0x73, 0x85, 0xc4, 0xf3, 0x1c, 0x4f, 0xa2, 0x37, 0x41, 0xa8, 0x37, 0x18, 0xec, + 0x88, 0x1c, 0xcf, 0x0c, 0x38, 0xca, 0x03, 0x4f, 0xcc, 0xcd, 0xa8, 0x7f, 0x56, 0x22, 0x59, 0x1e, + 0x9d, 0xe3, 0x90, 0xa5, 0x2c, 0x21, 0x4b, 0x0c, 0xa5, 0x66, 0x93, 0x28, 0x75, 0x1d, 0x2a, 0x2c, + 0x94, 0x8c, 0x01, 0x50, 0xec, 0x06, 0x00, 0x14, 0xbd, 0x0f, 0xab, 0x1c, 0x43, 0x08, 0x2c, 0x2b, + 0xe3, 0x47, 0x9e, 0x07, 0xc3, 0x15, 0xf6, 0x41, 0x1c, 0x5d, 0x11, 0x48, 0xfe, 0x1f, 0x2e, 0xc4, + 0x78, 0xc3, 0x10, 0x25, 0x90, 0x56, 0x3d, 0xe4, 0xde, 0x96, 0xb1, 0xea, 0x61, 0x64, 0xa0, 0x08, + 0xdc, 0x22, 0xc8, 0x1b, 0x8e, 0x49, 0x64, 0x00, 0xe1, 0x6d, 0x06, 0x78, 0xfb, 0x4e, 0x57, 0x86, + 0x09, 0xd6, 0x64, 0x5c, 0xa1, 0x4f, 0x2d, 0x0b, 0x67, 0xa9, 0xfe, 0x49, 0x89, 0xf4, 0x45, 0x78, + 0x77, 0x12, 0x34, 0x55, 0x5e, 0x27, 0x34, 0xcd, 0xfe, 0x77, 0xd0, 0x54, 0xfd, 0x75, 0x36, 0xda, + 0xd2, 0x10, 0x74, 0x7e, 0x3b, 0x13, 0x44, 0xe1, 0x77, 0x89, 0x6f, 0x90, 0x0c, 0xbf, 0x32, 0x5f, + 0x28, 0xf0, 0x6d, 0x48, 0xe6, 0x0b, 0x45, 0x11, 0x90, 0x39, 0xc1, 0x12, 0x63, 0xd7, 0x73, 0x9c, + 0x13, 0xdd, 0x71, 0xfd, 0x49, 0x19, 0xbf, 0xc0, 0x9b, 0xa2, 0x7a, 0xb4, 0x21, 0xaa, 0x47, 0x1b, + 0x07, 0x4c, 0x60, 0xdf, 0xf5, 0xb5, 0x92, 0x2b, 0x5b, 0x31, 0x98, 0x51, 0x4e, 0x60, 0xe1, 0xb7, + 0xa1, 0xcc, 0x96, 0xe2, 0xbb, 0xd8, 0x20, 0xdc, 0xc9, 0x96, 0xb5, 0xa8, 0x43, 0x35, 0x01, 0x9d, + 0x77, 0xf6, 0xe8, 0x11, 0x14, 0xc8, 0x29, 0xb1, 0x29, 0xdb, 0x33, 0x66, 0xe6, 0xb7, 0xa7, 0x82, + 0x4b, 0x62, 0xd3, 0x56, 0x83, 0x19, 0xf7, 0x5f, 0xdf, 0xac, 0xd7, 0x85, 0xcc, 0x87, 0xce, 0xc0, + 0xa2, 0x64, 0xe0, 0xd2, 0x91, 0x26, 0xb5, 0xa8, 0xbf, 0xc9, 0x32, 0x8c, 0x97, 0x08, 0x04, 0x13, + 0xcd, 0x1d, 0x5c, 0xa2, 0x6c, 0x0c, 0xf7, 0xa7, 0xdb, 0x82, 0x77, 0x00, 0xba, 0xd8, 0xd7, 0x9f, + 0x63, 0x9b, 0x12, 0x53, 0xee, 0x43, 0xb9, 0x8b, 0xfd, 0x1f, 0xf3, 0x0e, 0x06, 0xdd, 0xd8, 0xe7, + 0xa1, 0x4f, 0x4c, 0xbe, 0x21, 0x39, 0xad, 0xd8, 0xc5, 0xfe, 0xb1, 0x4f, 0xcc, 0xd8, 0x5a, 0x8b, + 0xaf, 0x63, 0xad, 0x49, 0x7b, 0x97, 0xc6, 0xed, 0xfd, 0xdb, 0x6c, 0x74, 0x5b, 0x22, 0x48, 0xfc, + 0xbf, 0x69, 0x8b, 0x3f, 0xf0, 0x44, 0x39, 0x19, 0x8d, 0xd1, 0xa7, 0xb0, 0x1a, 0xde, 0x52, 0x7d, + 0xc8, 0x6f, 0x6f, 0x70, 0x0a, 0x17, 0xbb, 0xec, 0xf5, 0xd3, 0x64, 0xb7, 0x8f, 0x3e, 0x83, 0x37, + 0xc7, 0x7c, 0x52, 0x38, 0x40, 0x76, 0x21, 0xd7, 0xf4, 0x46, 0xd2, 0x35, 0x05, 0xfa, 0x23, 0xeb, + 0xe5, 0x5e, 0xcb, 0xad, 0xd9, 0x63, 0x69, 0x59, 0x1c, 0x67, 0x4c, 0x3c, 0x13, 0x57, 0xa0, 0xea, + 0x11, 0x8a, 0x2d, 0x5b, 0x4f, 0xa4, 0xc2, 0xcb, 0xa2, 0x53, 0x84, 0x08, 0xf5, 0x09, 0xbc, 0x31, + 0x11, 0x69, 0xa0, 0xef, 0x41, 0x39, 0x82, 0x2a, 0xca, 0xcc, 0x4c, 0x32, 0xcc, 0x88, 0x22, 0x09, + 0xf5, 0x4b, 0x25, 0x52, 0x9c, 0xcc, 0xb4, 0xee, 0x43, 0xc1, 0x23, 0xfe, 0xb0, 0x2f, 0xb2, 0x9e, + 0xda, 0xd6, 0x27, 0x8b, 0x20, 0x15, 0xd6, 0x3b, 0xec, 0x53, 0x4d, 0xaa, 0x50, 0x1f, 0x43, 0x41, + 0xf4, 0x20, 0x80, 0xc2, 0xf6, 0xce, 0xce, 0xee, 0xc1, 0x51, 0x3d, 0x83, 0xca, 0xb0, 0xb4, 0xdd, + 0xda, 0xd7, 0x8e, 0xea, 0x0a, 0xeb, 0xd6, 0x76, 0x7f, 0xb4, 0xbb, 0x73, 0x54, 0xcf, 0xa2, 0x55, + 0xa8, 0x8a, 0xb6, 0x7e, 0x6f, 0x5f, 0x7b, 0xb8, 0x7d, 0x54, 0xcf, 0xc5, 0xba, 0x0e, 0x77, 0x1f, + 0xdd, 0xdd, 0xd5, 0xea, 0x79, 0xf5, 0x63, 0x96, 0x4f, 0x4d, 0x01, 0x32, 0x51, 0xe6, 0xa4, 0xc4, + 0x32, 0x27, 0xf5, 0x77, 0x59, 0x68, 0x4e, 0xc7, 0x25, 0xe8, 0x60, 0x6c, 0xc5, 0x37, 0x17, 0x86, + 0x36, 0x63, 0xcb, 0x46, 0x57, 0xa1, 0xe6, 0x91, 0x13, 0x42, 0x8d, 0x9e, 0xc0, 0x4c, 0x22, 0xea, + 0x55, 0xb5, 0xaa, 0xec, 0xe5, 0x42, 0xbe, 0x60, 0xfb, 0x9c, 0x18, 0x54, 0x17, 0xa9, 0x9c, 0x38, + 0x7f, 0x65, 0xc6, 0xc6, 0x7a, 0x0f, 0x45, 0xa7, 0x7a, 0x38, 0xcf, 0x88, 0x65, 0x58, 0xd2, 0x76, + 0x8f, 0xb4, 0x4f, 0xeb, 0x59, 0x84, 0xa0, 0xc6, 0x9b, 0xfa, 0xe1, 0xa3, 0xed, 0x83, 0xc3, 0xf6, + 0x3e, 0x33, 0xe2, 0x05, 0x58, 0x09, 0x8c, 0x18, 0x74, 0xe6, 0xd5, 0xbf, 0x2a, 0xb0, 0x32, 0x76, + 0x3d, 0xd0, 0x4d, 0x58, 0x12, 0x40, 0x5c, 0x99, 0x59, 0xd0, 0xe7, 0xf7, 0x5d, 0xde, 0x28, 0x21, + 0x80, 0x5a, 0x50, 0x22, 0xb2, 0x5e, 0x31, 0xe9, 0x4a, 0xc6, 0x2b, 0x2f, 0x41, 0x5d, 0x43, 0x2a, + 0x08, 0xe5, 0x58, 0x38, 0x0d, 0x6f, 0xbe, 0xcc, 0x1c, 0xaf, 0x4f, 0x53, 0x12, 0x7a, 0x0e, 0xa9, + 0x25, 0x92, 0x54, 0x77, 0xa0, 0x12, 0x9b, 0x20, 0xfa, 0x3f, 0x28, 0x0f, 0xf0, 0x99, 0xac, 0x61, + 0x89, 0xa2, 0x44, 0x69, 0x80, 0xcf, 0x78, 0xf9, 0x0a, 0xbd, 0x09, 0x45, 0xf6, 0xb1, 0x8b, 0x85, + 0x23, 0xc9, 0x69, 0x85, 0x01, 0x3e, 0xfb, 0x21, 0xf6, 0x55, 0x03, 0x6a, 0xc9, 0xd2, 0x0e, 0x3b, + 0x59, 0x9e, 0x33, 0xb4, 0x4d, 0xae, 0x63, 0x49, 0x13, 0x04, 0xba, 0x0d, 0x4b, 0xa7, 0x8e, 0xf0, + 0x43, 0xb3, 0x6e, 0xe0, 0x13, 0x87, 0x92, 0x58, 0x81, 0x48, 0xc8, 0xa8, 0x8f, 0xa0, 0xc6, 0x3d, + 0xca, 0x36, 0xa5, 0x9e, 0xd5, 0x19, 0x52, 0x12, 0xaf, 0x54, 0x2e, 0x4f, 0xa8, 0x54, 0x86, 0xc8, + 0x23, 0xc4, 0x2d, 0x39, 0x51, 0x26, 0xe3, 0x84, 0xfa, 0x4b, 0x05, 0x96, 0xb8, 0x42, 0xe6, 0x6e, + 0x78, 0xd5, 0x47, 0x62, 0x5a, 0xd6, 0x46, 0x06, 0x00, 0x0e, 0x06, 0x0a, 0xe6, 0x7b, 0x75, 0x96, + 0xa3, 0x0b, 0xa7, 0xd5, 0x7a, 0x5b, 0x7a, 0xbc, 0x8b, 0x91, 0x82, 0x98, 0xd7, 0x8b, 0xa9, 0x55, + 0x5f, 0x28, 0x50, 0x3a, 0x3a, 0x93, 0xa7, 0x75, 0x4a, 0x31, 0x88, 0xcd, 0x7e, 0x8f, 0xcf, 0x5e, + 0x94, 0x4f, 0x04, 0x21, 0xab, 0x4b, 0xb9, 0xb0, 0x72, 0x75, 0x2f, 0xbc, 0x95, 0xf9, 0xc5, 0x12, + 0xcc, 0xa0, 0xa8, 0x27, 0x5d, 0x50, 0x1f, 0x8a, 0xfc, 0x3c, 0xec, 0xdd, 0x9d, 0x58, 0x31, 0x7c, + 0x08, 0xcb, 0x2e, 0xf6, 0xa8, 0xaf, 0x27, 0xea, 0x86, 0xd3, 0x72, 0xf4, 0x03, 0xec, 0xd1, 0x43, + 0x42, 0x13, 0xd5, 0xc3, 0x0a, 0x97, 0x17, 0x5d, 0xea, 0x2d, 0xa8, 0x26, 0x78, 0xd8, 0x62, 0xa9, + 0x43, 0x71, 0x3f, 0x38, 0x37, 0x9c, 0x08, 0x67, 0x92, 0x8d, 0x66, 0xa2, 0xde, 0x86, 0x72, 0x78, + 0xac, 0x59, 0x06, 0x82, 0x4d, 0xd3, 0x23, 0xbe, 0x2f, 0x67, 0x1b, 0x90, 0xbc, 0x44, 0xea, 0x3c, + 0x97, 0x55, 0xa0, 0x9c, 0x26, 0x08, 0x95, 0xc0, 0xca, 0x58, 0x34, 0x45, 0x77, 0xa0, 0xe8, 0x0e, + 0x3b, 0x7a, 0x70, 0xa0, 0x2a, 0x5b, 0xef, 0x4c, 0x5b, 0xd4, 0xb0, 0x73, 0x9f, 0x8c, 0x02, 0xb3, + 0xb9, 0x9c, 0x8a, 0x86, 0xc9, 0xc6, 0x87, 0xf9, 0x05, 0x94, 0x82, 0xb3, 0x8c, 0xee, 0xc6, 0xef, + 0xab, 0x18, 0xe1, 0xf2, 0xbc, 0x40, 0x2f, 0x07, 0x89, 0x04, 0x59, 0xbe, 0xe4, 0x5b, 0x5d, 0x9b, + 0x98, 0x7a, 0x94, 0x0a, 0xf1, 0x31, 0x4b, 0xda, 0x8a, 0xf8, 0xf0, 0x20, 0xc8, 0x83, 0xd4, 0x8f, + 0xa0, 0x20, 0xe6, 0x3a, 0xf1, 0x80, 0x4f, 0x88, 0xb1, 0xea, 0x3f, 0x15, 0x28, 0x05, 0x0e, 0x67, + 0xa2, 0x50, 0x62, 0x11, 0xd9, 0x6f, 0xbb, 0x88, 0x69, 0xe5, 0xec, 0xe0, 0xf1, 0x20, 0xbf, 0xf0, + 0xe3, 0xc1, 0x87, 0x80, 0xf8, 0x49, 0xd1, 0x4f, 0x1d, 0x6a, 0xd9, 0x5d, 0x5d, 0xec, 0x85, 0x80, + 0x84, 0x75, 0xfe, 0xe5, 0x09, 0xff, 0x70, 0xc0, 0xb7, 0xe5, 0x57, 0x0a, 0x94, 0xc2, 0x00, 0xbe, + 0x68, 0xd9, 0xf2, 0x12, 0x14, 0x64, 0x90, 0x12, 0x75, 0x4b, 0x49, 0x85, 0x67, 0x34, 0x1f, 0xbb, + 0x2d, 0x4d, 0x28, 0x0d, 0x08, 0xc5, 0xdc, 0xce, 0x22, 0x4d, 0x0d, 0xe9, 0xf7, 0xaf, 0x40, 0x25, + 0x56, 0x47, 0x46, 0x45, 0xc8, 0x3d, 0x22, 0xcf, 0xeb, 0x19, 0x54, 0x81, 0xa2, 0x46, 0x78, 0xe9, + 0xa8, 0xae, 0x6c, 0x7d, 0x59, 0x81, 0x95, 0xed, 0xd6, 0xce, 0x1e, 0x8b, 0xa1, 0x96, 0x81, 0x79, + 0x0a, 0xbb, 0x0f, 0x79, 0x9e, 0xc5, 0xa7, 0x78, 0xb7, 0x6e, 0xa6, 0xa9, 0x43, 0x22, 0x0d, 0x96, + 0x78, 0xb2, 0x8f, 0xd2, 0x3c, 0x67, 0x37, 0x53, 0x95, 0x27, 0xd9, 0x24, 0xf9, 0xa9, 0x4f, 0xf1, + 0xca, 0xdd, 0x4c, 0x53, 0xb3, 0x44, 0x9f, 0x41, 0x39, 0xca, 0xe2, 0xd3, 0xbe, 0x7d, 0x37, 0x53, + 0x57, 0x33, 0x99, 0xfe, 0x28, 0x4f, 0x49, 0xfb, 0xf2, 0xdb, 0x4c, 0xed, 0x65, 0xd1, 0x53, 0x28, + 0x06, 0x19, 0x61, 0xba, 0xd7, 0xe9, 0x66, 0xca, 0x4a, 0x23, 0xdb, 0x3e, 0x91, 0xd8, 0xa7, 0x79, + 0x82, 0x6f, 0xa6, 0x2a, 0xa7, 0xa2, 0x63, 0x28, 0x48, 0x28, 0x9e, 0xea, 0xdd, 0xb9, 0x99, 0xae, + 0x7e, 0xc8, 0x8c, 0x1c, 0x95, 0x4e, 0xd2, 0xfe, 0xed, 0xa0, 0x99, 0xba, 0x8e, 0x8c, 0x30, 0x40, + 0x2c, 0xbb, 0x4f, 0xfd, 0x7f, 0x82, 0x66, 0xfa, 0xfa, 0x30, 0xfa, 0x29, 0x94, 0xc2, 0x1c, 0x2e, + 0xe5, 0xbb, 0x7e, 0x33, 0x6d, 0x89, 0x16, 0x7d, 0x0e, 0xd5, 0x64, 0xda, 0xb2, 0xc8, 0x6b, 0x7d, + 0x73, 0xa1, 0xda, 0x2b, 0x1b, 0x2b, 0x99, 0xc9, 0x2c, 0xf2, 0x86, 0xdf, 0x5c, 0xa8, 0x20, 0x8b, + 0x4e, 0x61, 0xf5, 0x7c, 0xf2, 0xb1, 0xe8, 0xc3, 0x7e, 0x73, 0xe1, 0x42, 0x2d, 0x1a, 0x01, 0x9a, + 0x90, 0xc0, 0x2c, 0xfc, 0xda, 0xdf, 0x5c, 0xbc, 0x7a, 0xdb, 0xda, 0xfd, 0xea, 0xe5, 0x9a, 0xf2, + 0xf5, 0xcb, 0x35, 0xe5, 0x1f, 0x2f, 0xd7, 0x94, 0x17, 0xaf, 0xd6, 0x32, 0x5f, 0xbf, 0x5a, 0xcb, + 0xfc, 0xed, 0xd5, 0x5a, 0xe6, 0x27, 0x1f, 0x74, 0x2d, 0xda, 0x1b, 0x76, 0x36, 0x0c, 0x67, 0xb0, + 0x19, 0xa9, 0x8d, 0x37, 0xa3, 0xbf, 0x5d, 0x75, 0x0a, 0x3c, 0xf8, 0x7d, 0xf2, 0x9f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x33, 0x72, 0x48, 0xac, 0x8b, 0x25, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -5604,9 +5605,9 @@ func (m *ResponseQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x48 } - if m.Proof != nil { + if m.ProofOps != nil { { - size, err := m.Proof.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ProofOps.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -7498,8 +7499,8 @@ func (m *ResponseQuery) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - if m.Proof != nil { - l = m.Proof.Size() + if m.ProofOps != nil { + l = m.ProofOps.Size() n += 1 + l + sovTypes(uint64(l)) } if m.Height != 0 { @@ -11724,7 +11725,7 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 8: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ProofOps", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -11751,10 +11752,10 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Proof == nil { - m.Proof = &merkle.Proof{} + if m.ProofOps == nil { + m.ProofOps = &merkle.ProofOps{} } - if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ProofOps.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/abci/types/types.proto b/abci/types/types.proto index d8dfa1b2c..2a9d0927d 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -4,7 +4,7 @@ option go_package = "github.com/tendermint/tendermint/abci/types"; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md -import "crypto/merkle/merkle.proto"; +import "proto/crypto/merkle/types.proto"; import "proto/types/types.proto"; import "proto/types/params.proto"; import "google/protobuf/timestamp.proto"; @@ -56,12 +56,12 @@ message RequestSetOption { } message RequestInitChain { - google.protobuf.Timestamp time = 1 - [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - string chain_id = 2; - ConsensusParams consensus_params = 3; - repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; - bytes app_state_bytes = 5; + google.protobuf.Timestamp time = 1 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; } message RequestQuery { @@ -72,10 +72,10 @@ message RequestQuery { } message RequestBeginBlock { - bytes hash = 1; - tendermint.proto.types.Header header = 2 [(gogoproto.nullable) = false]; - LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; - repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; + bytes hash = 1; + tendermint.proto.types.Header header = 2 [(gogoproto.nullable) = false]; + LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; } enum CheckTxType { @@ -183,19 +183,19 @@ message ResponseInitChain { message ResponseQuery { uint32 code = 1; // bytes data = 2; // use "value" instead. - string log = 3; // nondeterministic - string info = 4; // nondeterministic - int64 index = 5; - bytes key = 6; - bytes value = 7; - tendermint.crypto.merkle.Proof proof = 8; - int64 height = 9; - string codespace = 10; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 index = 5; + bytes key = 6; + bytes value = 7; + tendermint.proto.crypto.merkle.ProofOps proof_ops = 8; + int64 height = 9; + string codespace = 10; } message ResponseBeginBlock { repeated Event events = 1 - [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCheckTx { @@ -206,7 +206,7 @@ message ResponseCheckTx { int64 gas_wanted = 5; int64 gas_used = 6; repeated Event events = 7 - [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; string codespace = 8; } @@ -218,16 +218,16 @@ message ResponseDeliverTx { int64 gas_wanted = 5; int64 gas_used = 6; repeated Event events = 7 - [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; string codespace = 8; } message ResponseEndBlock { - repeated ValidatorUpdate validator_updates = 1 - [(gogoproto.nullable) = false]; - ConsensusParams consensus_param_updates = 2; - repeated Event events = 3 - [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + repeated ValidatorUpdate validator_updates = 1 + [(gogoproto.nullable) = false]; + ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } message ResponseCommit { @@ -276,7 +276,7 @@ message ResponseApplySnapshotChunk { // ConsensusParams contains all consensus-relevant parameters // that can be adjusted by the abci app message ConsensusParams { - BlockParams block = 1; + BlockParams block = 1; tendermint.proto.types.EvidenceParams evidence = 2; tendermint.proto.types.ValidatorParams validator = 3; } @@ -294,19 +294,19 @@ message LastCommitInfo { repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; } - // EventAttribute represents an event to the indexing service. message EventAttribute { - bytes key = 1; + bytes key = 1; bytes value = 2; - bool index = 3; + bool index = 3; } message Event { - string type = 1; + string type = 1; repeated EventAttribute attributes = 2 [ (gogoproto.nullable) = false, - (gogoproto.jsontag) = "attributes,omitempty"]; + (gogoproto.jsontag) = "attributes,omitempty" + ]; } // TxResult contains results of executing the transaction. @@ -360,10 +360,11 @@ message Evidence { string type = 1; Validator validator = 2 [(gogoproto.nullable) = false]; int64 height = 3; - google.protobuf.Timestamp time = 4 [ + google.protobuf.Timestamp time = 4 [ (gogoproto.nullable) = false, - (gogoproto.stdtime) = true]; - int64 total_voting_power = 5; + (gogoproto.stdtime) = true + ]; + int64 total_voting_power = 5; } //---------------------------------------- diff --git a/consensus/msgs_test.go b/consensus/msgs_test.go index c652a82a9..b4cfbcd89 100644 --- a/consensus/msgs_test.go +++ b/consensus/msgs_test.go @@ -33,7 +33,7 @@ func TestMsgToProto(t *testing.T) { parts := types.Part{ Index: 1, Bytes: []byte("test"), - Proof: merkle.SimpleProof{ + Proof: merkle.Proof{ Total: 1, Index: 1, LeafHash: tmrand.Bytes(32), @@ -211,7 +211,7 @@ func TestWALMsgProto(t *testing.T) { parts := types.Part{ Index: 1, Bytes: []byte("test"), - Proof: merkle.SimpleProof{ + Proof: merkle.Proof{ Total: 1, Index: 1, LeafHash: tmrand.Bytes(32), diff --git a/consensus/wal_test.go b/consensus/wal_test.go index 044ea2ddf..f2551558f 100644 --- a/consensus/wal_test.go +++ b/consensus/wal_test.go @@ -128,7 +128,7 @@ func TestWALWrite(t *testing.T) { Part: &tmtypes.Part{ Index: 1, Bytes: make([]byte, 1), - Proof: merkle.SimpleProof{ + Proof: merkle.Proof{ Total: 1, Index: 1, LeafHash: make([]byte, maxMsgSizeBytes-30), diff --git a/crypto/armor/armor_test.go b/crypto/armor/armor_test.go index 4aa23b211..8ecfaa0e1 100644 --- a/crypto/armor/armor_test.go +++ b/crypto/armor/armor_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestSimpleArmor(t *testing.T) { +func TestArmor(t *testing.T) { blockType := "MINT TEST" data := []byte("somedata") armorStr := EncodeArmor(blockType, nil, data) diff --git a/crypto/merkle/merkle.pb.go b/crypto/merkle/merkle.pb.go deleted file mode 100644 index 071e47b2c..000000000 --- a/crypto/merkle/merkle.pb.go +++ /dev/null @@ -1,617 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: crypto/merkle/merkle.proto - -package merkle - -import ( - fmt "fmt" - _ "github.com/gogo/protobuf/gogoproto" - proto "github.com/gogo/protobuf/proto" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// ProofOp defines an operation used for calculating Merkle root -// The data could be arbitrary format, providing nessecary data -// for example neighbouring node hash -type ProofOp struct { - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` -} - -func (m *ProofOp) Reset() { *m = ProofOp{} } -func (m *ProofOp) String() string { return proto.CompactTextString(m) } -func (*ProofOp) ProtoMessage() {} -func (*ProofOp) Descriptor() ([]byte, []int) { - return fileDescriptor_9c1c2162d560d38e, []int{0} -} -func (m *ProofOp) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ProofOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ProofOp.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ProofOp) XXX_Merge(src proto.Message) { - xxx_messageInfo_ProofOp.Merge(m, src) -} -func (m *ProofOp) XXX_Size() int { - return m.Size() -} -func (m *ProofOp) XXX_DiscardUnknown() { - xxx_messageInfo_ProofOp.DiscardUnknown(m) -} - -var xxx_messageInfo_ProofOp proto.InternalMessageInfo - -func (m *ProofOp) GetType() string { - if m != nil { - return m.Type - } - return "" -} - -func (m *ProofOp) GetKey() []byte { - if m != nil { - return m.Key - } - return nil -} - -func (m *ProofOp) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - -// Proof is Merkle proof defined by the list of ProofOps -type Proof struct { - Ops []ProofOp `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops"` -} - -func (m *Proof) Reset() { *m = Proof{} } -func (m *Proof) String() string { return proto.CompactTextString(m) } -func (*Proof) ProtoMessage() {} -func (*Proof) Descriptor() ([]byte, []int) { - return fileDescriptor_9c1c2162d560d38e, []int{1} -} -func (m *Proof) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Proof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Proof.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Proof) XXX_Merge(src proto.Message) { - xxx_messageInfo_Proof.Merge(m, src) -} -func (m *Proof) XXX_Size() int { - return m.Size() -} -func (m *Proof) XXX_DiscardUnknown() { - xxx_messageInfo_Proof.DiscardUnknown(m) -} - -var xxx_messageInfo_Proof proto.InternalMessageInfo - -func (m *Proof) GetOps() []ProofOp { - if m != nil { - return m.Ops - } - return nil -} - -func init() { - proto.RegisterType((*ProofOp)(nil), "tendermint.crypto.merkle.ProofOp") - proto.RegisterType((*Proof)(nil), "tendermint.crypto.merkle.Proof") -} - -func init() { proto.RegisterFile("crypto/merkle/merkle.proto", fileDescriptor_9c1c2162d560d38e) } - -var fileDescriptor_9c1c2162d560d38e = []byte{ - // 234 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0x2e, 0xaa, 0x2c, - 0x28, 0xc9, 0xd7, 0xcf, 0x4d, 0x2d, 0xca, 0xce, 0x49, 0x85, 0x52, 0x7a, 0x05, 0x45, 0xf9, 0x25, - 0xf9, 0x42, 0x12, 0x25, 0xa9, 0x79, 0x29, 0xa9, 0x45, 0xb9, 0x99, 0x79, 0x25, 0x7a, 0x10, 0x65, - 0x7a, 0x10, 0x79, 0x29, 0xb5, 0x92, 0x8c, 0xcc, 0xa2, 0x94, 0xf8, 0x82, 0xc4, 0xa2, 0x92, 0x4a, - 0x7d, 0xb0, 0x62, 0xfd, 0xf4, 0xfc, 0xf4, 0x7c, 0x04, 0x0b, 0x62, 0x82, 0x92, 0x33, 0x17, 0x7b, - 0x40, 0x51, 0x7e, 0x7e, 0x9a, 0x7f, 0x81, 0x90, 0x10, 0x17, 0x4b, 0x49, 0x65, 0x41, 0xaa, 0x04, - 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x98, 0x2d, 0x24, 0xc0, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, 0xc1, - 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0x62, 0x82, 0x54, 0xa5, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x83, - 0x85, 0xc0, 0x6c, 0x25, 0x27, 0x2e, 0x56, 0xb0, 0x21, 0x42, 0x96, 0x5c, 0xcc, 0xf9, 0x05, 0xc5, - 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x8a, 0x7a, 0xb8, 0x5c, 0xa7, 0x07, 0xb5, 0xd2, 0x89, - 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0x90, 0x1e, 0x27, 0x8f, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, - 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, - 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, - 0x47, 0x98, 0x88, 0xcc, 0x44, 0x09, 0xa1, 0x24, 0x36, 0xb0, 0xcf, 0x8c, 0x01, 0x01, 0x00, 0x00, - 0xff, 0xff, 0x39, 0xc0, 0xa3, 0x13, 0x39, 0x01, 0x00, 0x00, -} - -func (m *ProofOp) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ProofOp) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ProofOp) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintMerkle(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x1a - } - if len(m.Key) > 0 { - i -= len(m.Key) - copy(dAtA[i:], m.Key) - i = encodeVarintMerkle(dAtA, i, uint64(len(m.Key))) - i-- - dAtA[i] = 0x12 - } - if len(m.Type) > 0 { - i -= len(m.Type) - copy(dAtA[i:], m.Type) - i = encodeVarintMerkle(dAtA, i, uint64(len(m.Type))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Proof) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Proof) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Proof) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Ops) > 0 { - for iNdEx := len(m.Ops) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Ops[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintMerkle(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func encodeVarintMerkle(dAtA []byte, offset int, v uint64) int { - offset -= sovMerkle(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ProofOp) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Type) - if l > 0 { - n += 1 + l + sovMerkle(uint64(l)) - } - l = len(m.Key) - if l > 0 { - n += 1 + l + sovMerkle(uint64(l)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovMerkle(uint64(l)) - } - return n -} - -func (m *Proof) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Ops) > 0 { - for _, e := range m.Ops { - l = e.Size() - n += 1 + l + sovMerkle(uint64(l)) - } - } - return n -} - -func sovMerkle(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozMerkle(x uint64) (n int) { - return sovMerkle(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ProofOp) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ProofOp: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ProofOp: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthMerkle - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthMerkle - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Type = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthMerkle - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthMerkle - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) - if m.Key == nil { - m.Key = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthMerkle - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthMerkle - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipMerkle(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthMerkle - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthMerkle - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Proof) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Proof: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Proof: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Ops", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowMerkle - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthMerkle - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthMerkle - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Ops = append(m.Ops, ProofOp{}) - if err := m.Ops[len(m.Ops)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipMerkle(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthMerkle - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthMerkle - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipMerkle(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowMerkle - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowMerkle - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowMerkle - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthMerkle - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupMerkle - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthMerkle - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthMerkle = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowMerkle = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupMerkle = fmt.Errorf("proto: unexpected end of group") -) diff --git a/crypto/merkle/merkle.proto b/crypto/merkle/merkle.proto deleted file mode 100644 index ccf032d57..000000000 --- a/crypto/merkle/merkle.proto +++ /dev/null @@ -1,28 +0,0 @@ -syntax = "proto3"; -package tendermint.crypto.merkle; -option go_package = "github.com/tendermint/tendermint/crypto/merkle"; - -// For more information on gogo.proto, see: -// https://github.com/gogo/protobuf/blob/master/extensions.md -import "third_party/proto/gogoproto/gogo.proto"; - -option (gogoproto.marshaler_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; - -//---------------------------------------- -// Message types - -// ProofOp defines an operation used for calculating Merkle root -// The data could be arbitrary format, providing nessecary data -// for example neighbouring node hash -message ProofOp { - string type = 1; - bytes key = 2; - bytes data = 3; -} - -// Proof is Merkle proof defined by the list of ProofOps -message Proof { - repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; -} diff --git a/crypto/merkle/proof.go b/crypto/merkle/proof.go index 84c9bbc18..ae463e83c 100644 --- a/crypto/merkle/proof.go +++ b/crypto/merkle/proof.go @@ -4,135 +4,232 @@ import ( "bytes" "errors" "fmt" + + "github.com/tendermint/tendermint/crypto/tmhash" + tmmerkle "github.com/tendermint/tendermint/proto/crypto/merkle" ) -//---------------------------------------- -// ProofOp gets converted to an instance of ProofOperator: +const ( + // MaxAunts is the maximum number of aunts that can be included in a Proof. + // This corresponds to a tree of size 2^100, which should be sufficient for all conceivable purposes. + // This maximum helps prevent Denial-of-Service attacks by limitting the size of the proofs. + MaxAunts = 100 +) -// ProofOperator is a layer for calculating intermediate Merkle roots -// when a series of Merkle trees are chained together. -// Run() takes leaf values from a tree and returns the Merkle -// root for the corresponding tree. It takes and returns a list of bytes -// to allow multiple leaves to be part of a single proof, for instance in a range proof. -// ProofOp() encodes the ProofOperator in a generic way so it can later be -// decoded with OpDecoder. -type ProofOperator interface { - Run([][]byte) ([][]byte, error) - GetKey() []byte - ProofOp() ProofOp +// Proof represents a Merkle proof. +// NOTE: The convention for proofs is to include leaf hashes but to +// exclude the root hash. +// This convention is implemented across IAVL range proofs as well. +// Keep this consistent unless there's a very good reason to change +// everything. This also affects the generalized proof system as +// well. +type Proof struct { + Total int64 `json:"total"` // Total number of items. + Index int64 `json:"index"` // Index of item to prove. + LeafHash []byte `json:"leaf_hash"` // Hash of item value. + Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. } -//---------------------------------------- -// Operations on a list of ProofOperators - -// ProofOperators is a slice of ProofOperator(s). -// Each operator will be applied to the input value sequentially -// and the last Merkle root will be verified with already known data -type ProofOperators []ProofOperator - -func (poz ProofOperators) VerifyValue(root []byte, keypath string, value []byte) (err error) { - return poz.Verify(root, keypath, [][]byte{value}) +// ProofsFromByteSlices computes inclusion proof for given items. +// proofs[0] is the proof for items[0]. +func ProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*Proof) { + trails, rootSPN := trailsFromByteSlices(items) + rootHash = rootSPN.Hash + proofs = make([]*Proof, len(items)) + for i, trail := range trails { + proofs[i] = &Proof{ + Total: int64(len(items)), + Index: int64(i), + LeafHash: trail.Hash, + Aunts: trail.FlattenAunts(), + } + } + return } -func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (err error) { - keys, err := KeyPathToKeys(keypath) - if err != nil { - return +// Verify that the Proof proves the root hash. +// Check sp.Index/sp.Total manually if needed +func (sp *Proof) Verify(rootHash []byte, leaf []byte) error { + leafHash := leafHash(leaf) + if sp.Total < 0 { + return errors.New("proof total must be positive") } - - for i, op := range poz { - key := op.GetKey() - if len(key) != 0 { - if len(keys) == 0 { - return fmt.Errorf("key path has insufficient # of parts: expected no more keys but got %+v", string(key)) - } - lastKey := keys[len(keys)-1] - if !bytes.Equal(lastKey, key) { - return fmt.Errorf("key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)) - } - keys = keys[:len(keys)-1] - } - args, err = op.Run(args) - if err != nil { - return - } + if sp.Index < 0 { + return errors.New("proof index cannot be negative") } - if !bytes.Equal(root, args[0]) { - return fmt.Errorf("calculated root hash is invalid: expected %+v but got %+v", root, args[0]) + if !bytes.Equal(sp.LeafHash, leafHash) { + return fmt.Errorf("invalid leaf hash: wanted %X got %X", leafHash, sp.LeafHash) } - if len(keys) != 0 { - return errors.New("keypath not consumed all") + computedHash := sp.ComputeRootHash() + if !bytes.Equal(computedHash, rootHash) { + return fmt.Errorf("invalid root hash: wanted %X got %X", rootHash, computedHash) } return nil } -//---------------------------------------- -// ProofRuntime - main entrypoint - -type OpDecoder func(ProofOp) (ProofOperator, error) - -type ProofRuntime struct { - decoders map[string]OpDecoder +// Compute the root hash given a leaf hash. Does not verify the result. +func (sp *Proof) ComputeRootHash() []byte { + return computeHashFromAunts( + sp.Index, + sp.Total, + sp.LeafHash, + sp.Aunts, + ) } -func NewProofRuntime() *ProofRuntime { - return &ProofRuntime{ - decoders: make(map[string]OpDecoder), +// String implements the stringer interface for Proof. +// It is a wrapper around StringIndented. +func (sp *Proof) String() string { + return sp.StringIndented("") +} + +// StringIndented generates a canonical string representation of a Proof. +func (sp *Proof) StringIndented(indent string) string { + return fmt.Sprintf(`Proof{ +%s Aunts: %X +%s}`, + indent, sp.Aunts, + indent) +} + +// ValidateBasic performs basic validation. +// NOTE: it expects the LeafHash and the elements of Aunts to be of size tmhash.Size, +// and it expects at most MaxAunts elements in Aunts. +func (sp *Proof) ValidateBasic() error { + if sp.Total < 0 { + return errors.New("negative Total") } -} - -func (prt *ProofRuntime) RegisterOpDecoder(typ string, dec OpDecoder) { - _, ok := prt.decoders[typ] - if ok { - panic("already registered for type " + typ) + if sp.Index < 0 { + return errors.New("negative Index") } - prt.decoders[typ] = dec -} - -func (prt *ProofRuntime) Decode(pop ProofOp) (ProofOperator, error) { - decoder := prt.decoders[pop.Type] - if decoder == nil { - return nil, fmt.Errorf("unrecognized proof type %v", pop.Type) + if len(sp.LeafHash) != tmhash.Size { + return fmt.Errorf("expected LeafHash size to be %d, got %d", tmhash.Size, len(sp.LeafHash)) } - return decoder(pop) -} - -func (prt *ProofRuntime) DecodeProof(proof *Proof) (ProofOperators, error) { - poz := make(ProofOperators, 0, len(proof.Ops)) - for _, pop := range proof.Ops { - operator, err := prt.Decode(pop) - if err != nil { - return nil, fmt.Errorf("decoding a proof operator: %w", err) + if len(sp.Aunts) > MaxAunts { + return fmt.Errorf("expected no more than %d aunts, got %d", MaxAunts, len(sp.Aunts)) + } + for i, auntHash := range sp.Aunts { + if len(auntHash) != tmhash.Size { + return fmt.Errorf("expected Aunts#%d size to be %d, got %d", i, tmhash.Size, len(auntHash)) } - poz = append(poz, operator) } - return poz, nil + return nil } -func (prt *ProofRuntime) VerifyValue(proof *Proof, root []byte, keypath string, value []byte) (err error) { - return prt.Verify(proof, root, keypath, [][]byte{value}) -} - -// TODO In the long run we'll need a method of classifcation of ops, -// whether existence or absence or perhaps a third? -func (prt *ProofRuntime) VerifyAbsence(proof *Proof, root []byte, keypath string) (err error) { - return prt.Verify(proof, root, keypath, nil) -} - -func (prt *ProofRuntime) Verify(proof *Proof, root []byte, keypath string, args [][]byte) (err error) { - poz, err := prt.DecodeProof(proof) - if err != nil { - return fmt.Errorf("decoding proof: %w", err) +func (sp *Proof) ToProto() *tmmerkle.Proof { + if sp == nil { + return nil } - return poz.Verify(root, keypath, args) + pb := new(tmmerkle.Proof) + + pb.Total = sp.Total + pb.Index = sp.Index + pb.LeafHash = sp.LeafHash + pb.Aunts = sp.Aunts + + return pb } -// DefaultProofRuntime only knows about Simple value -// proofs. -// To use e.g. IAVL proofs, register op-decoders as -// defined in the IAVL package. -func DefaultProofRuntime() (prt *ProofRuntime) { - prt = NewProofRuntime() - prt.RegisterOpDecoder(ProofOpSimpleValue, SimpleValueOpDecoder) - return +func ProofFromProto(pb *tmmerkle.Proof) (*Proof, error) { + if pb == nil { + return nil, errors.New("nil proof") + } + sp := new(Proof) + + sp.Total = pb.Total + sp.Index = pb.Index + sp.LeafHash = pb.LeafHash + sp.Aunts = pb.Aunts + + return sp, sp.ValidateBasic() +} + +// Use the leafHash and innerHashes to get the root merkle hash. +// If the length of the innerHashes slice isn't exactly correct, the result is nil. +// Recursive impl. +func computeHashFromAunts(index, total int64, leafHash []byte, innerHashes [][]byte) []byte { + if index >= total || index < 0 || total <= 0 { + return nil + } + switch total { + case 0: + panic("Cannot call computeHashFromAunts() with 0 total") + case 1: + if len(innerHashes) != 0 { + return nil + } + return leafHash + default: + if len(innerHashes) == 0 { + return nil + } + numLeft := getSplitPoint(total) + if index < numLeft { + leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if leftHash == nil { + return nil + } + return innerHash(leftHash, innerHashes[len(innerHashes)-1]) + } + rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if rightHash == nil { + return nil + } + return innerHash(innerHashes[len(innerHashes)-1], rightHash) + } +} + +// ProofNode is a helper structure to construct merkle proof. +// The node and the tree is thrown away afterwards. +// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. +// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or +// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. +type ProofNode struct { + Hash []byte + Parent *ProofNode + Left *ProofNode // Left sibling (only one of Left,Right is set) + Right *ProofNode // Right sibling (only one of Left,Right is set) +} + +// FlattenAunts will return the inner hashes for the item corresponding to the leaf, +// starting from a leaf ProofNode. +func (spn *ProofNode) FlattenAunts() [][]byte { + // Nonrecursive impl. + innerHashes := [][]byte{} + for spn != nil { + switch { + case spn.Left != nil: + innerHashes = append(innerHashes, spn.Left.Hash) + case spn.Right != nil: + innerHashes = append(innerHashes, spn.Right.Hash) + default: + break + } + spn = spn.Parent + } + return innerHashes +} + +// trails[0].Hash is the leaf hash for items[0]. +// trails[i].Parent.Parent....Parent == root for all i. +func trailsFromByteSlices(items [][]byte) (trails []*ProofNode, root *ProofNode) { + // Recursive impl. + switch len(items) { + case 0: + return nil, nil + case 1: + trail := &ProofNode{leafHash(items[0]), nil, nil, nil} + return []*ProofNode{trail}, trail + default: + k := getSplitPoint(int64(len(items))) + lefts, leftRoot := trailsFromByteSlices(items[:k]) + rights, rightRoot := trailsFromByteSlices(items[k:]) + rootHash := innerHash(leftRoot.Hash, rightRoot.Hash) + root := &ProofNode{rootHash, nil, nil, nil} + leftRoot.Parent = root + leftRoot.Right = rightRoot + rightRoot.Parent = root + rightRoot.Left = leftRoot + return append(lefts, rights...), root + } } diff --git a/crypto/merkle/proof_key_path.go b/crypto/merkle/proof_key_path.go index beafc4f1c..ca8b5f052 100644 --- a/crypto/merkle/proof_key_path.go +++ b/crypto/merkle/proof_key_path.go @@ -17,7 +17,7 @@ import ( /32:) For example, for a Cosmos-SDK application where the first two proof layers - are SimpleValueOps, and the third proof layer is an IAVLValueOp, the keys + are ValueOps, and the third proof layer is an IAVLValueOp, the keys might look like: 0: []byte("App") diff --git a/crypto/merkle/proof_op.go b/crypto/merkle/proof_op.go new file mode 100644 index 000000000..8994a2926 --- /dev/null +++ b/crypto/merkle/proof_op.go @@ -0,0 +1,139 @@ +package merkle + +import ( + "bytes" + "errors" + "fmt" + + tmmerkle "github.com/tendermint/tendermint/proto/crypto/merkle" +) + +//---------------------------------------- +// ProofOp gets converted to an instance of ProofOperator: + +// ProofOperator is a layer for calculating intermediate Merkle roots +// when a series of Merkle trees are chained together. +// Run() takes leaf values from a tree and returns the Merkle +// root for the corresponding tree. It takes and returns a list of bytes +// to allow multiple leaves to be part of a single proof, for instance in a range proof. +// ProofOp() encodes the ProofOperator in a generic way so it can later be +// decoded with OpDecoder. +type ProofOperator interface { + Run([][]byte) ([][]byte, error) + GetKey() []byte + ProofOp() tmmerkle.ProofOp +} + +//---------------------------------------- +// Operations on a list of ProofOperators + +// ProofOperators is a slice of ProofOperator(s). +// Each operator will be applied to the input value sequentially +// and the last Merkle root will be verified with already known data +type ProofOperators []ProofOperator + +func (poz ProofOperators) VerifyValue(root []byte, keypath string, value []byte) (err error) { + return poz.Verify(root, keypath, [][]byte{value}) +} + +func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (err error) { + keys, err := KeyPathToKeys(keypath) + if err != nil { + return + } + + for i, op := range poz { + key := op.GetKey() + if len(key) != 0 { + if len(keys) == 0 { + return fmt.Errorf("key path has insufficient # of parts: expected no more keys but got %+v", string(key)) + } + lastKey := keys[len(keys)-1] + if !bytes.Equal(lastKey, key) { + return fmt.Errorf("key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)) + } + keys = keys[:len(keys)-1] + } + args, err = op.Run(args) + if err != nil { + return + } + } + if !bytes.Equal(root, args[0]) { + return fmt.Errorf("calculated root hash is invalid: expected %+v but got %+v", root, args[0]) + } + if len(keys) != 0 { + return errors.New("keypath not consumed all") + } + return nil +} + +//---------------------------------------- +// ProofRuntime - main entrypoint + +type OpDecoder func(tmmerkle.ProofOp) (ProofOperator, error) + +type ProofRuntime struct { + decoders map[string]OpDecoder +} + +func NewProofRuntime() *ProofRuntime { + return &ProofRuntime{ + decoders: make(map[string]OpDecoder), + } +} + +func (prt *ProofRuntime) RegisterOpDecoder(typ string, dec OpDecoder) { + _, ok := prt.decoders[typ] + if ok { + panic("already registered for type " + typ) + } + prt.decoders[typ] = dec +} + +func (prt *ProofRuntime) Decode(pop tmmerkle.ProofOp) (ProofOperator, error) { + decoder := prt.decoders[pop.Type] + if decoder == nil { + return nil, fmt.Errorf("unrecognized proof type %v", pop.Type) + } + return decoder(pop) +} + +func (prt *ProofRuntime) DecodeProof(proof *tmmerkle.ProofOps) (ProofOperators, error) { + poz := make(ProofOperators, 0, len(proof.Ops)) + for _, pop := range proof.Ops { + operator, err := prt.Decode(pop) + if err != nil { + return nil, fmt.Errorf("decoding a proof operator: %w", err) + } + poz = append(poz, operator) + } + return poz, nil +} + +func (prt *ProofRuntime) VerifyValue(proof *tmmerkle.ProofOps, root []byte, keypath string, value []byte) (err error) { + return prt.Verify(proof, root, keypath, [][]byte{value}) +} + +// TODO In the long run we'll need a method of classifcation of ops, +// whether existence or absence or perhaps a third? +func (prt *ProofRuntime) VerifyAbsence(proof *tmmerkle.ProofOps, root []byte, keypath string) (err error) { + return prt.Verify(proof, root, keypath, nil) +} + +func (prt *ProofRuntime) Verify(proof *tmmerkle.ProofOps, root []byte, keypath string, args [][]byte) (err error) { + poz, err := prt.DecodeProof(proof) + if err != nil { + return fmt.Errorf("decoding proof: %w", err) + } + return poz.Verify(root, keypath, args) +} + +// DefaultProofRuntime only knows about value proofs. +// To use e.g. IAVL proofs, register op-decoders as +// defined in the IAVL package. +func DefaultProofRuntime() (prt *ProofRuntime) { + prt = NewProofRuntime() + prt.RegisterOpDecoder(ProofOpValue, ValueOpDecoder) + return +} diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index ca9a982e1..398cb3e29 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" amino "github.com/tendermint/go-amino" + tmmerkle "github.com/tendermint/tendermint/proto/crypto/merkle" ) const ProofOpDomino = "test:domino" @@ -28,21 +29,21 @@ func NewDominoOp(key, input, output string) DominoOp { } //nolint:unused -func DominoOpDecoder(pop ProofOp) (ProofOperator, error) { +func DominoOpDecoder(pop tmmerkle.ProofOp) (ProofOperator, error) { if pop.Type != ProofOpDomino { panic("unexpected proof op type") } var op DominoOp // a bit strange as we'll discard this, but it works. err := amino.UnmarshalBinaryLengthPrefixed(pop.Data, &op) if err != nil { - return nil, fmt.Errorf("decoding ProofOp.Data into SimpleValueOp: %w", err) + return nil, fmt.Errorf("decoding ProofOp.Data into ValueOp: %w", err) } return NewDominoOp(string(pop.Key), op.Input, op.Output), nil } -func (dop DominoOp) ProofOp() ProofOp { +func (dop DominoOp) ProofOp() tmmerkle.ProofOp { bz := amino.MustMarshalBinaryLengthPrefixed(dop) - return ProofOp{ + return tmmerkle.ProofOp{ Type: ProofOpDomino, Key: []byte(dop.key), Data: bz, @@ -140,3 +141,37 @@ func TestProofOperators(t *testing.T) { func bz(s string) []byte { return []byte(s) } + +func TestProofValidateBasic(t *testing.T) { + testCases := []struct { + testName string + malleateProof func(*Proof) + errStr string + }{ + {"Good", func(sp *Proof) {}, ""}, + {"Negative Total", func(sp *Proof) { sp.Total = -1 }, "negative Total"}, + {"Negative Index", func(sp *Proof) { sp.Index = -1 }, "negative Index"}, + {"Invalid LeafHash", func(sp *Proof) { sp.LeafHash = make([]byte, 10) }, + "expected LeafHash size to be 32, got 10"}, + {"Too many Aunts", func(sp *Proof) { sp.Aunts = make([][]byte, MaxAunts+1) }, + "expected no more than 100 aunts, got 101"}, + {"Invalid Aunt", func(sp *Proof) { sp.Aunts[0] = make([]byte, 10) }, + "expected Aunts#0 size to be 32, got 10"}, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + _, proofs := ProofsFromByteSlices([][]byte{ + []byte("apple"), + []byte("watermelon"), + []byte("kiwi"), + }) + tc.malleateProof(proofs[0]) + err := proofs[0].ValidateBasic() + if tc.errStr != "" { + assert.Contains(t, err.Error(), tc.errStr) + } + }) + } +} diff --git a/crypto/merkle/proof_simple_value.go b/crypto/merkle/proof_value.go similarity index 58% rename from crypto/merkle/proof_simple_value.go rename to crypto/merkle/proof_value.go index d1a0426aa..b9be68ca7 100644 --- a/crypto/merkle/proof_simple_value.go +++ b/crypto/merkle/proof_value.go @@ -5,63 +5,64 @@ import ( "fmt" "github.com/tendermint/tendermint/crypto/tmhash" + tmmerkle "github.com/tendermint/tendermint/proto/crypto/merkle" ) -const ProofOpSimpleValue = "simple:v" +const ProofOpValue = "simple:v" -// SimpleValueOp takes a key and a single value as argument and +// ValueOp takes a key and a single value as argument and // produces the root hash. The corresponding tree structure is // the SimpleMap tree. SimpleMap takes a Hasher, and currently -// Tendermint uses aminoHasher. SimpleValueOp should support +// Tendermint uses aminoHasher. ValueOp should support // the hash function as used in aminoHasher. TODO support // additional hash functions here as options/args to this // operator. // // If the produced root hash matches the expected hash, the // proof is good. -type SimpleValueOp struct { +type ValueOp struct { // Encoded in ProofOp.Key. key []byte // To encode in ProofOp.Data - Proof *SimpleProof `json:"simple_proof"` + Proof *Proof `json:"proof"` } -var _ ProofOperator = SimpleValueOp{} +var _ ProofOperator = ValueOp{} -func NewSimpleValueOp(key []byte, proof *SimpleProof) SimpleValueOp { - return SimpleValueOp{ +func NewValueOp(key []byte, proof *Proof) ValueOp { + return ValueOp{ key: key, Proof: proof, } } -func SimpleValueOpDecoder(pop ProofOp) (ProofOperator, error) { - if pop.Type != ProofOpSimpleValue { - return nil, fmt.Errorf("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpSimpleValue) +func ValueOpDecoder(pop tmmerkle.ProofOp) (ProofOperator, error) { + if pop.Type != ProofOpValue { + return nil, fmt.Errorf("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpValue) } - var op SimpleValueOp // a bit strange as we'll discard this, but it works. + var op ValueOp // a bit strange as we'll discard this, but it works. err := cdc.UnmarshalBinaryLengthPrefixed(pop.Data, &op) if err != nil { - return nil, fmt.Errorf("decoding ProofOp.Data into SimpleValueOp: %w", err) + return nil, fmt.Errorf("decoding ProofOp.Data into ValueOp: %w", err) } - return NewSimpleValueOp(pop.Key, op.Proof), nil + return NewValueOp(pop.Key, op.Proof), nil } -func (op SimpleValueOp) ProofOp() ProofOp { +func (op ValueOp) ProofOp() tmmerkle.ProofOp { bz := cdc.MustMarshalBinaryLengthPrefixed(op) - return ProofOp{ - Type: ProofOpSimpleValue, + return tmmerkle.ProofOp{ + Type: ProofOpValue, Key: op.key, Data: bz, } } -func (op SimpleValueOp) String() string { - return fmt.Sprintf("SimpleValueOp{%v}", op.GetKey()) +func (op ValueOp) String() string { + return fmt.Sprintf("ValueOp{%v}", op.GetKey()) } -func (op SimpleValueOp) Run(args [][]byte) ([][]byte, error) { +func (op ValueOp) Run(args [][]byte) ([][]byte, error) { if len(args) != 1 { return nil, fmt.Errorf("expected 1 arg, got %v", len(args)) } @@ -85,6 +86,6 @@ func (op SimpleValueOp) Run(args [][]byte) ([][]byte, error) { }, nil } -func (op SimpleValueOp) GetKey() []byte { +func (op ValueOp) GetKey() []byte { return op.key } diff --git a/crypto/merkle/result.go b/crypto/merkle/result.go deleted file mode 100644 index a17e38e1f..000000000 --- a/crypto/merkle/result.go +++ /dev/null @@ -1,52 +0,0 @@ -package merkle - -import ( - "bytes" - "encoding/json" - - "github.com/gogo/protobuf/jsonpb" -) - -//--------------------------------------------------------------------------- -// override JSON marshalling so we emit defaults (ie. disable omitempty) - -var ( - jsonpbMarshaller = jsonpb.Marshaler{ - EnumsAsInts: true, - EmitDefaults: true, - } - jsonpbUnmarshaller = jsonpb.Unmarshaler{} -) - -func (r *ProofOp) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} - -func (r *ProofOp) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} - -func (r *Proof) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} - -func (r *Proof) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} - -// Some compile time assertions to ensure we don't -// have accidental runtime surprises later on. -// jsonEncodingRoundTripper ensures that asserted -// interfaces implement both MarshalJSON and UnmarshalJSON - -type jsonRoundTripper interface { - json.Marshaler - json.Unmarshaler -} - -var _ jsonRoundTripper = (*ProofOp)(nil) -var _ jsonRoundTripper = (*Proof)(nil) diff --git a/crypto/merkle/simple_proof.go b/crypto/merkle/simple_proof.go deleted file mode 100644 index 7c262e3f6..000000000 --- a/crypto/merkle/simple_proof.go +++ /dev/null @@ -1,235 +0,0 @@ -package merkle - -import ( - "bytes" - "errors" - "fmt" - - "github.com/tendermint/tendermint/crypto/tmhash" - tmmerkle "github.com/tendermint/tendermint/proto/crypto/merkle" -) - -const ( - // MaxAunts is the maximum number of aunts that can be included in a SimpleProof. - // This corresponds to a tree of size 2^100, which should be sufficient for all conceivable purposes. - // This maximum helps prevent Denial-of-Service attacks by limitting the size of the proofs. - MaxAunts = 100 -) - -// SimpleProof represents a simple Merkle proof. -// NOTE: The convention for proofs is to include leaf hashes but to -// exclude the root hash. -// This convention is implemented across IAVL range proofs as well. -// Keep this consistent unless there's a very good reason to change -// everything. This also affects the generalized proof system as -// well. -type SimpleProof struct { - Total int64 `json:"total"` // Total number of items. - Index int64 `json:"index"` // Index of item to prove. - LeafHash []byte `json:"leaf_hash"` // Hash of item value. - Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. -} - -// SimpleProofsFromByteSlices computes inclusion proof for given items. -// proofs[0] is the proof for items[0]. -func SimpleProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*SimpleProof) { - trails, rootSPN := trailsFromByteSlices(items) - rootHash = rootSPN.Hash - proofs = make([]*SimpleProof, len(items)) - for i, trail := range trails { - proofs[i] = &SimpleProof{ - Total: int64(len(items)), - Index: int64(i), - LeafHash: trail.Hash, - Aunts: trail.FlattenAunts(), - } - } - return -} - -// Verify that the SimpleProof proves the root hash. -// Check sp.Index/sp.Total manually if needed -func (sp *SimpleProof) Verify(rootHash []byte, leaf []byte) error { - leafHash := leafHash(leaf) - if sp.Total < 0 { - return errors.New("proof total must be positive") - } - if sp.Index < 0 { - return errors.New("proof index cannot be negative") - } - if !bytes.Equal(sp.LeafHash, leafHash) { - return fmt.Errorf("invalid leaf hash: wanted %X got %X", leafHash, sp.LeafHash) - } - computedHash := sp.ComputeRootHash() - if !bytes.Equal(computedHash, rootHash) { - return fmt.Errorf("invalid root hash: wanted %X got %X", rootHash, computedHash) - } - return nil -} - -// Compute the root hash given a leaf hash. Does not verify the result. -func (sp *SimpleProof) ComputeRootHash() []byte { - return computeHashFromAunts( - sp.Index, - sp.Total, - sp.LeafHash, - sp.Aunts, - ) -} - -// String implements the stringer interface for SimpleProof. -// It is a wrapper around StringIndented. -func (sp *SimpleProof) String() string { - return sp.StringIndented("") -} - -// StringIndented generates a canonical string representation of a SimpleProof. -func (sp *SimpleProof) StringIndented(indent string) string { - return fmt.Sprintf(`SimpleProof{ -%s Aunts: %X -%s}`, - indent, sp.Aunts, - indent) -} - -// ValidateBasic performs basic validation. -// NOTE: it expects the LeafHash and the elements of Aunts to be of size tmhash.Size, -// and it expects at most MaxAunts elements in Aunts. -func (sp *SimpleProof) ValidateBasic() error { - if sp.Total < 0 { - return errors.New("negative Total") - } - if sp.Index < 0 { - return errors.New("negative Index") - } - if len(sp.LeafHash) != tmhash.Size { - return fmt.Errorf("expected LeafHash size to be %d, got %d", tmhash.Size, len(sp.LeafHash)) - } - if len(sp.Aunts) > MaxAunts { - return fmt.Errorf("expected no more than %d aunts, got %d", MaxAunts, len(sp.Aunts)) - } - for i, auntHash := range sp.Aunts { - if len(auntHash) != tmhash.Size { - return fmt.Errorf("expected Aunts#%d size to be %d, got %d", i, tmhash.Size, len(auntHash)) - } - } - return nil -} - -func (sp *SimpleProof) ToProto() *tmmerkle.SimpleProof { - if sp == nil { - return nil - } - pb := new(tmmerkle.SimpleProof) - - pb.Total = sp.Total - pb.Index = sp.Index - pb.LeafHash = sp.LeafHash - pb.Aunts = sp.Aunts - - return pb -} - -func SimpleProofFromProto(pb *tmmerkle.SimpleProof) (*SimpleProof, error) { - if pb == nil { - return nil, errors.New("nil proof") - } - sp := new(SimpleProof) - - sp.Total = pb.Total - sp.Index = pb.Index - sp.LeafHash = pb.LeafHash - sp.Aunts = pb.Aunts - - return sp, sp.ValidateBasic() -} - -// Use the leafHash and innerHashes to get the root merkle hash. -// If the length of the innerHashes slice isn't exactly correct, the result is nil. -// Recursive impl. -func computeHashFromAunts(index, total int64, leafHash []byte, innerHashes [][]byte) []byte { - if index >= total || index < 0 || total <= 0 { - return nil - } - switch total { - case 0: - panic("Cannot call computeHashFromAunts() with 0 total") - case 1: - if len(innerHashes) != 0 { - return nil - } - return leafHash - default: - if len(innerHashes) == 0 { - return nil - } - numLeft := getSplitPoint(total) - if index < numLeft { - leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if leftHash == nil { - return nil - } - return innerHash(leftHash, innerHashes[len(innerHashes)-1]) - } - rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if rightHash == nil { - return nil - } - return innerHash(innerHashes[len(innerHashes)-1], rightHash) - } -} - -// SimpleProofNode is a helper structure to construct merkle proof. -// The node and the tree is thrown away afterwards. -// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. -// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or -// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. -type SimpleProofNode struct { - Hash []byte - Parent *SimpleProofNode - Left *SimpleProofNode // Left sibling (only one of Left,Right is set) - Right *SimpleProofNode // Right sibling (only one of Left,Right is set) -} - -// FlattenAunts will return the inner hashes for the item corresponding to the leaf, -// starting from a leaf SimpleProofNode. -func (spn *SimpleProofNode) FlattenAunts() [][]byte { - // Nonrecursive impl. - innerHashes := [][]byte{} - for spn != nil { - switch { - case spn.Left != nil: - innerHashes = append(innerHashes, spn.Left.Hash) - case spn.Right != nil: - innerHashes = append(innerHashes, spn.Right.Hash) - default: - break - } - spn = spn.Parent - } - return innerHashes -} - -// trails[0].Hash is the leaf hash for items[0]. -// trails[i].Parent.Parent....Parent == root for all i. -func trailsFromByteSlices(items [][]byte) (trails []*SimpleProofNode, root *SimpleProofNode) { - // Recursive impl. - switch len(items) { - case 0: - return nil, nil - case 1: - trail := &SimpleProofNode{leafHash(items[0]), nil, nil, nil} - return []*SimpleProofNode{trail}, trail - default: - k := getSplitPoint(int64(len(items))) - lefts, leftRoot := trailsFromByteSlices(items[:k]) - rights, rightRoot := trailsFromByteSlices(items[k:]) - rootHash := innerHash(leftRoot.Hash, rightRoot.Hash) - root := &SimpleProofNode{rootHash, nil, nil, nil} - leftRoot.Parent = root - leftRoot.Right = rightRoot - rightRoot.Parent = root - rightRoot.Left = leftRoot - return append(lefts, rights...), root - } -} diff --git a/crypto/merkle/simple_proof_test.go b/crypto/merkle/simple_proof_test.go deleted file mode 100644 index 2dd8b7eb0..000000000 --- a/crypto/merkle/simple_proof_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package merkle - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - tmrand "github.com/tendermint/tendermint/libs/rand" -) - -func TestSimpleProofValidateBasic(t *testing.T) { - testCases := []struct { - testName string - malleateProof func(*SimpleProof) - errStr string - }{ - {"Good", func(sp *SimpleProof) {}, ""}, - {"Negative Total", func(sp *SimpleProof) { sp.Total = -1 }, "negative Total"}, - {"Negative Index", func(sp *SimpleProof) { sp.Index = -1 }, "negative Index"}, - {"Invalid LeafHash", func(sp *SimpleProof) { sp.LeafHash = make([]byte, 10) }, - "expected LeafHash size to be 32, got 10"}, - {"Too many Aunts", func(sp *SimpleProof) { sp.Aunts = make([][]byte, MaxAunts+1) }, - "expected no more than 100 aunts, got 101"}, - {"Invalid Aunt", func(sp *SimpleProof) { sp.Aunts[0] = make([]byte, 10) }, - "expected Aunts#0 size to be 32, got 10"}, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.testName, func(t *testing.T) { - _, proofs := SimpleProofsFromByteSlices([][]byte{ - []byte("apple"), - []byte("watermelon"), - []byte("kiwi"), - }) - tc.malleateProof(proofs[0]) - err := proofs[0].ValidateBasic() - if tc.errStr != "" { - assert.Contains(t, err.Error(), tc.errStr) - } - }) - } -} - -func TestSimpleProofProtoBuf(t *testing.T) { - testCases := []struct { - testName string - ps1 *SimpleProof - expPass bool - }{ - {"failure empty", &SimpleProof{}, false}, - {"failure nil", nil, false}, - {"success", - &SimpleProof{ - Total: 1, - Index: 1, - LeafHash: tmrand.Bytes(32), - Aunts: [][]byte{tmrand.Bytes(32), tmrand.Bytes(32), tmrand.Bytes(32)}, - }, true}, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.testName, func(t *testing.T) { - proto := tc.ps1.ToProto() - p, err := SimpleProofFromProto(proto) - if tc.expPass { - require.NoError(t, err) - require.Equal(t, tc.ps1, p, tc.testName) - } else { - require.Error(t, err, tc.testName) - } - }) - } -} diff --git a/crypto/merkle/simple_tree.go b/crypto/merkle/tree.go similarity index 73% rename from crypto/merkle/simple_tree.go rename to crypto/merkle/tree.go index c9c478406..cbd51ca3a 100644 --- a/crypto/merkle/simple_tree.go +++ b/crypto/merkle/tree.go @@ -4,9 +4,9 @@ import ( "math/bits" ) -// SimpleHashFromByteSlices computes a Merkle tree where the leaves are the byte slice, +// HashFromByteSlices computes a Merkle tree where the leaves are the byte slice, // in the provided order. -func SimpleHashFromByteSlices(items [][]byte) []byte { +func HashFromByteSlices(items [][]byte) []byte { switch len(items) { case 0: return nil @@ -14,27 +14,27 @@ func SimpleHashFromByteSlices(items [][]byte) []byte { return leafHash(items[0]) default: k := getSplitPoint(int64(len(items))) - left := SimpleHashFromByteSlices(items[:k]) - right := SimpleHashFromByteSlices(items[k:]) + left := HashFromByteSlices(items[:k]) + right := HashFromByteSlices(items[k:]) return innerHash(left, right) } } -// SimpleHashFromByteSliceIterative is an iterative alternative to -// SimpleHashFromByteSlice motivated by potential performance improvements. +// HashFromByteSliceIterative is an iterative alternative to +// HashFromByteSlice motivated by potential performance improvements. // (#2611) had suggested that an iterative version of -// SimpleHashFromByteSlice would be faster, presumably because +// HashFromByteSlice would be faster, presumably because // we can envision some overhead accumulating from stack // frames and function calls. Additionally, a recursive algorithm risks // hitting the stack limit and causing a stack overflow should the tree // be too large. // -// Provided here is an iterative alternative, a simple test to assert +// Provided here is an iterative alternative, a test to assert // correctness and a benchmark. On the performance side, there appears to // be no overall difference: // -// BenchmarkSimpleHashAlternatives/recursive-4 20000 77677 ns/op -// BenchmarkSimpleHashAlternatives/iterative-4 20000 76802 ns/op +// BenchmarkHashAlternatives/recursive-4 20000 77677 ns/op +// BenchmarkHashAlternatives/iterative-4 20000 76802 ns/op // // On the surface it might seem that the additional overhead is due to // the different allocation patterns of the implementations. The recursive @@ -47,9 +47,9 @@ func SimpleHashFromByteSlices(items [][]byte) []byte { // // These preliminary results suggest: // -// 1. The performance of the SimpleHashFromByteSlice is pretty good +// 1. The performance of the HashFromByteSlice is pretty good // 2. Go has low overhead for recursive functions -// 3. The performance of the SimpleHashFromByteSlice routine is dominated +// 3. The performance of the HashFromByteSlice routine is dominated // by the actual hashing of data // // Although this work is in no way exhaustive, point #3 suggests that @@ -59,7 +59,7 @@ func SimpleHashFromByteSlices(items [][]byte) []byte { // Finally, considering that the recursive implementation is easier to // read, it might not be worthwhile to switch to a less intuitive // implementation for so little benefit. -func SimpleHashFromByteSlicesIterative(input [][]byte) []byte { +func HashFromByteSlicesIterative(input [][]byte) []byte { items := make([][]byte, len(input)) for i, leaf := range input { diff --git a/crypto/merkle/simple_tree_test.go b/crypto/merkle/tree_test.go similarity index 86% rename from crypto/merkle/simple_tree_test.go rename to crypto/merkle/tree_test.go index 01d6058c3..b8679256c 100644 --- a/crypto/merkle/simple_tree_test.go +++ b/crypto/merkle/tree_test.go @@ -17,7 +17,7 @@ func (tI testItem) Hash() []byte { return []byte(tI) } -func TestSimpleProof(t *testing.T) { +func TestProof(t *testing.T) { total := 100 @@ -26,9 +26,9 @@ func TestSimpleProof(t *testing.T) { items[i] = testItem(tmrand.Bytes(tmhash.Size)) } - rootHash := SimpleHashFromByteSlices(items) + rootHash := HashFromByteSlices(items) - rootHash2, proofs := SimpleProofsFromByteSlices(items) + rootHash2, proofs := ProofsFromByteSlices(items) require.Equal(t, rootHash, rootHash2, "Unmatched root hashes: %X vs %X", rootHash, rootHash2) @@ -70,7 +70,7 @@ func TestSimpleProof(t *testing.T) { } } -func TestSimpleHashAlternatives(t *testing.T) { +func TestHashAlternatives(t *testing.T) { total := 100 @@ -79,12 +79,12 @@ func TestSimpleHashAlternatives(t *testing.T) { items[i] = testItem(tmrand.Bytes(tmhash.Size)) } - rootHash1 := SimpleHashFromByteSlicesIterative(items) - rootHash2 := SimpleHashFromByteSlices(items) + rootHash1 := HashFromByteSlicesIterative(items) + rootHash2 := HashFromByteSlices(items) require.Equal(t, rootHash1, rootHash2, "Unmatched root hashes: %X vs %X", rootHash1, rootHash2) } -func BenchmarkSimpleHashAlternatives(b *testing.B) { +func BenchmarkHashAlternatives(b *testing.B) { total := 100 items := make([][]byte, total) @@ -95,13 +95,13 @@ func BenchmarkSimpleHashAlternatives(b *testing.B) { b.ResetTimer() b.Run("recursive", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = SimpleHashFromByteSlices(items) + _ = HashFromByteSlices(items) } }) b.Run("iterative", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = SimpleHashFromByteSlicesIterative(items) + _ = HashFromByteSlicesIterative(items) } }) } diff --git a/go.sum b/go.sum index a64356153..a01c6ab24 100644 --- a/go.sum +++ b/go.sum @@ -438,8 +438,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho= -github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= diff --git a/light/rpc/client.go b/light/rpc/client.go index 847f1e468..59d2a3d62 100644 --- a/light/rpc/client.go +++ b/light/rpc/client.go @@ -83,7 +83,7 @@ func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes, if resp.IsErr() { return nil, fmt.Errorf("err response code: %v", resp.Code) } - if len(resp.Key) == 0 || resp.Proof == nil { + if len(resp.Key) == 0 || resp.ProofOps == nil { return nil, errors.New("empty tree") } if resp.Height <= 0 { @@ -108,7 +108,7 @@ func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes, kp := merkle.KeyPath{} kp = kp.AppendKey([]byte(storeName), merkle.KeyEncodingURL) kp = kp.AppendKey(resp.Key, merkle.KeyEncodingURL) - err = c.prt.VerifyValue(resp.Proof, h.AppHash, kp.String(), resp.Value) + err = c.prt.VerifyValue(resp.ProofOps, h.AppHash, kp.String(), resp.Value) if err != nil { return nil, fmt.Errorf("verify value proof: %w", err) } @@ -117,7 +117,7 @@ func (c *Client) ABCIQueryWithOptions(path string, data tmbytes.HexBytes, // OR validate the ansence proof against the trusted header. // XXX How do we encode the key into a string... - err = c.prt.VerifyAbsence(resp.Proof, h.AppHash, string(resp.Key)) + err = c.prt.VerifyAbsence(resp.ProofOps, h.AppHash, string(resp.Key)) if err != nil { return nil, fmt.Errorf("verify absence proof: %w", err) } diff --git a/light/rpc/proof.go b/light/rpc/proof.go index 51e835f7a..fc349c172 100644 --- a/light/rpc/proof.go +++ b/light/rpc/proof.go @@ -7,8 +7,8 @@ import ( func defaultProofRuntime() *merkle.ProofRuntime { prt := merkle.NewProofRuntime() prt.RegisterOpDecoder( - merkle.ProofOpSimpleValue, - merkle.SimpleValueOpDecoder, + merkle.ProofOpValue, + merkle.ValueOpDecoder, ) return prt } diff --git a/proto/crypto/merkle/types.pb.go b/proto/crypto/merkle/types.pb.go index fdc4493f8..06835cc3b 100644 --- a/proto/crypto/merkle/types.pb.go +++ b/proto/crypto/merkle/types.pb.go @@ -5,6 +5,7 @@ package merkle import ( fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" math "math" @@ -22,25 +23,25 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -type SimpleProof struct { +type Proof struct { Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` LeafHash []byte `protobuf:"bytes,3,opt,name=leaf_hash,json=leafHash,proto3" json:"leaf_hash,omitempty"` Aunts [][]byte `protobuf:"bytes,4,rep,name=aunts,proto3" json:"aunts,omitempty"` } -func (m *SimpleProof) Reset() { *m = SimpleProof{} } -func (m *SimpleProof) String() string { return proto.CompactTextString(m) } -func (*SimpleProof) ProtoMessage() {} -func (*SimpleProof) Descriptor() ([]byte, []int) { +func (m *Proof) Reset() { *m = Proof{} } +func (m *Proof) String() string { return proto.CompactTextString(m) } +func (*Proof) ProtoMessage() {} +func (*Proof) Descriptor() ([]byte, []int) { return fileDescriptor_57e39eefdaf7ae96, []int{0} } -func (m *SimpleProof) XXX_Unmarshal(b []byte) error { +func (m *Proof) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *SimpleProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *Proof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_SimpleProof.Marshal(b, m, deterministic) + return xxx_messageInfo_Proof.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -50,71 +51,186 @@ func (m *SimpleProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *SimpleProof) XXX_Merge(src proto.Message) { - xxx_messageInfo_SimpleProof.Merge(m, src) +func (m *Proof) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proof.Merge(m, src) } -func (m *SimpleProof) XXX_Size() int { +func (m *Proof) XXX_Size() int { return m.Size() } -func (m *SimpleProof) XXX_DiscardUnknown() { - xxx_messageInfo_SimpleProof.DiscardUnknown(m) +func (m *Proof) XXX_DiscardUnknown() { + xxx_messageInfo_Proof.DiscardUnknown(m) } -var xxx_messageInfo_SimpleProof proto.InternalMessageInfo +var xxx_messageInfo_Proof proto.InternalMessageInfo -func (m *SimpleProof) GetTotal() int64 { +func (m *Proof) GetTotal() int64 { if m != nil { return m.Total } return 0 } -func (m *SimpleProof) GetIndex() int64 { +func (m *Proof) GetIndex() int64 { if m != nil { return m.Index } return 0 } -func (m *SimpleProof) GetLeafHash() []byte { +func (m *Proof) GetLeafHash() []byte { if m != nil { return m.LeafHash } return nil } -func (m *SimpleProof) GetAunts() [][]byte { +func (m *Proof) GetAunts() [][]byte { if m != nil { return m.Aunts } return nil } +// ProofOp defines an operation used for calculating Merkle root +// The data could be arbitrary format, providing nessecary data +// for example neighbouring node hash +type ProofOp struct { + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *ProofOp) Reset() { *m = ProofOp{} } +func (m *ProofOp) String() string { return proto.CompactTextString(m) } +func (*ProofOp) ProtoMessage() {} +func (*ProofOp) Descriptor() ([]byte, []int) { + return fileDescriptor_57e39eefdaf7ae96, []int{1} +} +func (m *ProofOp) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProofOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProofOp.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProofOp) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProofOp.Merge(m, src) +} +func (m *ProofOp) XXX_Size() int { + return m.Size() +} +func (m *ProofOp) XXX_DiscardUnknown() { + xxx_messageInfo_ProofOp.DiscardUnknown(m) +} + +var xxx_messageInfo_ProofOp proto.InternalMessageInfo + +func (m *ProofOp) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *ProofOp) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *ProofOp) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +// Proof is Merkle proof defined by the list of ProofOps +type ProofOps struct { + Ops []ProofOp `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops"` +} + +func (m *ProofOps) Reset() { *m = ProofOps{} } +func (m *ProofOps) String() string { return proto.CompactTextString(m) } +func (*ProofOps) ProtoMessage() {} +func (*ProofOps) Descriptor() ([]byte, []int) { + return fileDescriptor_57e39eefdaf7ae96, []int{2} +} +func (m *ProofOps) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProofOps) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProofOps.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProofOps) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProofOps.Merge(m, src) +} +func (m *ProofOps) XXX_Size() int { + return m.Size() +} +func (m *ProofOps) XXX_DiscardUnknown() { + xxx_messageInfo_ProofOps.DiscardUnknown(m) +} + +var xxx_messageInfo_ProofOps proto.InternalMessageInfo + +func (m *ProofOps) GetOps() []ProofOp { + if m != nil { + return m.Ops + } + return nil +} + func init() { - proto.RegisterType((*SimpleProof)(nil), "tendermint.proto.crypto.merkle.SimpleProof") + proto.RegisterType((*Proof)(nil), "tendermint.proto.crypto.merkle.Proof") + proto.RegisterType((*ProofOp)(nil), "tendermint.proto.crypto.merkle.ProofOp") + proto.RegisterType((*ProofOps)(nil), "tendermint.proto.crypto.merkle.ProofOps") } func init() { proto.RegisterFile("proto/crypto/merkle/types.proto", fileDescriptor_57e39eefdaf7ae96) } var fileDescriptor_57e39eefdaf7ae96 = []byte{ - // 214 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2f, 0x28, 0xca, 0x2f, - 0xc9, 0xd7, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4d, 0x2d, 0xca, 0xce, 0x49, 0xd5, - 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x03, 0xcb, 0x08, 0xc9, 0x95, 0xa4, 0xe6, 0xa5, 0xa4, 0x16, - 0xe5, 0x66, 0xe6, 0x95, 0x40, 0x44, 0xf4, 0x20, 0x6a, 0xf5, 0x20, 0x6a, 0x95, 0x72, 0xb8, 0xb8, - 0x83, 0x33, 0x73, 0x0b, 0x72, 0x52, 0x03, 0x8a, 0xf2, 0xf3, 0xd3, 0x84, 0x44, 0xb8, 0x58, 0x4b, - 0xf2, 0x4b, 0x12, 0x73, 0x24, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0x20, 0x1c, 0x90, 0x68, 0x66, - 0x5e, 0x4a, 0x6a, 0x85, 0x04, 0x13, 0x44, 0x14, 0xcc, 0x11, 0x92, 0xe6, 0xe2, 0xcc, 0x49, 0x4d, - 0x4c, 0x8b, 0xcf, 0x48, 0x2c, 0xce, 0x90, 0x60, 0x56, 0x60, 0xd4, 0xe0, 0x09, 0xe2, 0x00, 0x09, - 0x78, 0x24, 0x16, 0x67, 0x80, 0xb4, 0x24, 0x96, 0xe6, 0x95, 0x14, 0x4b, 0xb0, 0x28, 0x30, 0x6b, - 0xf0, 0x04, 0x41, 0x38, 0x4e, 0x7e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, - 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, - 0x65, 0x92, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x8f, 0x70, 0x32, 0x32, - 0x13, 0x8b, 0x4f, 0x93, 0xd8, 0xc0, 0x82, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x91, 0x57, - 0x16, 0x46, 0x07, 0x01, 0x00, 0x00, + // 303 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x51, 0x3f, 0x4b, 0x03, 0x31, + 0x1c, 0xbd, 0x78, 0xad, 0xb6, 0xb1, 0x83, 0x04, 0x87, 0x43, 0x21, 0x3d, 0x3a, 0xe8, 0x4d, 0x39, + 0x50, 0x77, 0xa1, 0x2e, 0x82, 0xa0, 0x92, 0xd1, 0xa5, 0xa4, 0xbd, 0xb4, 0x77, 0xb4, 0xbd, 0x84, + 0xe4, 0x57, 0xf0, 0xbe, 0x85, 0x1f, 0xab, 0x63, 0x47, 0x27, 0x91, 0xf6, 0x8b, 0x48, 0x92, 0x42, + 0x1d, 0xc4, 0xed, 0xbd, 0x97, 0xf7, 0x87, 0x24, 0xb8, 0xaf, 0x8d, 0x02, 0x95, 0x4f, 0x4c, 0xa3, + 0x41, 0xe5, 0x4b, 0x69, 0xe6, 0x0b, 0x99, 0x43, 0xa3, 0xa5, 0x65, 0xfe, 0x84, 0x50, 0x90, 0x75, + 0x21, 0xcd, 0xb2, 0xaa, 0x21, 0x28, 0x2c, 0x78, 0x59, 0xf0, 0x5e, 0x5c, 0x41, 0x59, 0x99, 0x62, + 0xa4, 0x85, 0x81, 0x26, 0x0f, 0x65, 0x33, 0x35, 0x53, 0x07, 0x14, 0x52, 0x83, 0x29, 0x6e, 0xbf, + 0x1a, 0xa5, 0xa6, 0xe4, 0x1c, 0xb7, 0x41, 0x81, 0x58, 0x24, 0x28, 0x45, 0x59, 0xcc, 0x03, 0x71, + 0x6a, 0x55, 0x17, 0xf2, 0x3d, 0x39, 0x0a, 0xaa, 0x27, 0xe4, 0x12, 0x77, 0x17, 0x52, 0x4c, 0x47, + 0xa5, 0xb0, 0x65, 0x12, 0xa7, 0x28, 0xeb, 0xf1, 0x8e, 0x13, 0x1e, 0x85, 0x2d, 0x5d, 0x44, 0xac, + 0x6a, 0xb0, 0x49, 0x2b, 0x8d, 0xb3, 0x1e, 0x0f, 0x64, 0xf0, 0x80, 0x4f, 0xfc, 0xce, 0x8b, 0x26, + 0x04, 0xb7, 0xdc, 0x4d, 0xfc, 0x50, 0x97, 0x7b, 0x4c, 0xce, 0x70, 0x3c, 0x97, 0x8d, 0x5f, 0xe9, + 0x71, 0x07, 0x9d, 0xab, 0x10, 0x20, 0xf6, 0xf5, 0x1e, 0x0f, 0x9e, 0x70, 0x67, 0x5f, 0x62, 0xc9, + 0x3d, 0x8e, 0x95, 0xb6, 0x09, 0x4a, 0xe3, 0xec, 0xf4, 0xe6, 0x9a, 0xfd, 0xff, 0x1c, 0x6c, 0x1f, + 0x1b, 0xb6, 0xd6, 0x5f, 0xfd, 0x88, 0xbb, 0xe4, 0xf0, 0x79, 0xbd, 0xa5, 0x68, 0xb3, 0xa5, 0xe8, + 0x7b, 0x4b, 0xd1, 0xc7, 0x8e, 0x46, 0x9b, 0x1d, 0x8d, 0x3e, 0x77, 0x34, 0x7a, 0xbb, 0x9b, 0x55, + 0x50, 0xae, 0xc6, 0x6c, 0xa2, 0x96, 0xf9, 0xa1, 0xf7, 0x37, 0xfc, 0xe3, 0x77, 0xc6, 0xc7, 0x5e, + 0xbc, 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0x3b, 0x62, 0x4b, 0x7e, 0xbb, 0x01, 0x00, 0x00, } -func (m *SimpleProof) Marshal() (dAtA []byte, err error) { +func (m *Proof) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -124,12 +240,12 @@ func (m *SimpleProof) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *SimpleProof) MarshalTo(dAtA []byte) (int, error) { +func (m *Proof) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *SimpleProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *Proof) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -163,6 +279,87 @@ func (m *SimpleProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ProofOp) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProofOp) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProofOp) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x1a + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x12 + } + if len(m.Type) > 0 { + i -= len(m.Type) + copy(dAtA[i:], m.Type) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ProofOps) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProofOps) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProofOps) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Ops) > 0 { + for iNdEx := len(m.Ops) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Ops[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -174,7 +371,7 @@ func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *SimpleProof) Size() (n int) { +func (m *Proof) Size() (n int) { if m == nil { return 0 } @@ -199,13 +396,49 @@ func (m *SimpleProof) Size() (n int) { return n } +func (m *ProofOp) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ProofOps) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Ops) > 0 { + for _, e := range m.Ops { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } func sozTypes(x uint64) (n int) { return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *SimpleProof) Unmarshal(dAtA []byte) error { +func (m *Proof) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -228,10 +461,10 @@ func (m *SimpleProof) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: SimpleProof: wiretype end group for non-group") + return fmt.Errorf("proto: Proof: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: SimpleProof: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Proof: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -362,6 +595,246 @@ func (m *SimpleProof) Unmarshal(dAtA []byte) error { } return nil } +func (m *ProofOp) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProofOp: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProofOp: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ProofOps) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProofOps: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProofOps: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ops", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ops = append(m.Ops, ProofOp{}) + if err := m.Ops[len(m.Ops)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTypes(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/proto/crypto/merkle/types.proto b/proto/crypto/merkle/types.proto index c7dc355a5..905ef80c8 100644 --- a/proto/crypto/merkle/types.proto +++ b/proto/crypto/merkle/types.proto @@ -3,9 +3,25 @@ package tendermint.proto.crypto.merkle; option go_package = "github.com/tendermint/tendermint/proto/crypto/merkle"; -message SimpleProof { +import "third_party/proto/gogoproto/gogo.proto"; + +message Proof { int64 total = 1; int64 index = 2; bytes leaf_hash = 3; repeated bytes aunts = 4; } + +// ProofOp defines an operation used for calculating Merkle root +// The data could be arbitrary format, providing nessecary data +// for example neighbouring node hash +message ProofOp { + string type = 1; + bytes key = 2; + bytes data = 3; +} + +// ProofOps is Merkle proof defined by the list of ProofOps +message ProofOps { + repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/types/types.pb.go b/proto/types/types.pb.go index f0b6afd81..68d7d927e 100644 --- a/proto/types/types.pb.go +++ b/proto/types/types.pb.go @@ -140,9 +140,9 @@ func (m *PartSetHeader) GetHash() []byte { } type Part struct { - Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` - Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` - Proof merkle.SimpleProof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof"` + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` + Proof merkle.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof"` } func (m *Part) Reset() { *m = Part{} } @@ -192,11 +192,11 @@ func (m *Part) GetBytes() []byte { return nil } -func (m *Part) GetProof() merkle.SimpleProof { +func (m *Part) GetProof() merkle.Proof { if m != nil { return m.Proof } - return merkle.SimpleProof{} + return merkle.Proof{} } // BlockID @@ -950,88 +950,87 @@ func init() { func init() { proto.RegisterFile("proto/types/types.proto", fileDescriptor_ff06f8095857fb18) } var fileDescriptor_ff06f8095857fb18 = []byte{ - // 1283 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1a, 0x47, - 0x18, 0x66, 0x61, 0x31, 0xf0, 0x02, 0x36, 0x5e, 0xb9, 0x09, 0xc5, 0x2d, 0x26, 0xb8, 0x49, 0x9d, - 0x0f, 0x2d, 0x95, 0x2b, 0x55, 0x8d, 0xd4, 0x0b, 0xd8, 0x8e, 0x83, 0x62, 0x63, 0xb4, 0xd0, 0x54, - 0xed, 0x65, 0x35, 0xb0, 0x93, 0x65, 0x95, 0x65, 0x77, 0xb5, 0x3b, 0x58, 0x26, 0x95, 0x7a, 0xae, - 0x7c, 0xca, 0x1f, 0xf0, 0x29, 0xad, 0xd4, 0x7f, 0xd1, 0x1e, 0x73, 0xaa, 0x72, 0xec, 0x29, 0xad, - 0xec, 0x7f, 0x50, 0xf5, 0x07, 0x54, 0xf3, 0xb1, 0x0b, 0x04, 0xd3, 0x5a, 0x4d, 0xd4, 0x8b, 0xbd, - 0xf3, 0xbe, 0xcf, 0xf3, 0xce, 0xbc, 0xcf, 0x3c, 0x33, 0x23, 0xe0, 0xba, 0xe7, 0xbb, 0xc4, 0xad, - 0x91, 0xb1, 0x87, 0x03, 0xfe, 0x57, 0x65, 0x11, 0xe5, 0x1a, 0xc1, 0x8e, 0x81, 0xfd, 0xa1, 0xe5, - 0x10, 0x1e, 0x51, 0x59, 0xb6, 0x74, 0x8b, 0x0c, 0x2c, 0xdf, 0xd0, 0x3d, 0xe4, 0x93, 0x71, 0x8d, - 0x93, 0x4d, 0xd7, 0x74, 0x27, 0x5f, 0x1c, 0x5d, 0xda, 0x30, 0x5d, 0xd7, 0xb4, 0x31, 0x87, 0xf4, - 0x46, 0x4f, 0x6a, 0xc4, 0x1a, 0xe2, 0x80, 0xa0, 0xa1, 0x27, 0x00, 0xeb, 0x9c, 0x62, 0x5b, 0xbd, - 0xa0, 0xd6, 0xb3, 0xc8, 0xcc, 0xec, 0xa5, 0x0d, 0x9e, 0xec, 0xfb, 0x63, 0x8f, 0xb8, 0xb5, 0x21, - 0xf6, 0x9f, 0xda, 0x78, 0x06, 0x20, 0xd8, 0xc7, 0xd8, 0x0f, 0x2c, 0xd7, 0x09, 0xff, 0xf3, 0x64, - 0xf5, 0x3e, 0xe4, 0xdb, 0xc8, 0x27, 0x1d, 0x4c, 0x1e, 0x62, 0x64, 0x60, 0x5f, 0x59, 0x83, 0x24, - 0x71, 0x09, 0xb2, 0x8b, 0x52, 0x45, 0xda, 0xca, 0x6b, 0x7c, 0xa0, 0x28, 0x20, 0x0f, 0x50, 0x30, - 0x28, 0xc6, 0x2b, 0xd2, 0x56, 0x4e, 0x63, 0xdf, 0xd5, 0x6f, 0x41, 0xa6, 0x54, 0xca, 0xb0, 0x1c, - 0x03, 0x9f, 0x84, 0x0c, 0x36, 0xa0, 0xd1, 0xde, 0x98, 0xe0, 0x40, 0x50, 0xf8, 0x40, 0xd9, 0x87, - 0xa4, 0xe7, 0xbb, 0xee, 0x93, 0x62, 0xa2, 0x22, 0x6d, 0x65, 0xb7, 0xef, 0xaa, 0x73, 0xd2, 0xf1, - 0x3e, 0x54, 0xde, 0x87, 0xda, 0xb1, 0x86, 0x9e, 0x8d, 0xdb, 0x94, 0xd2, 0x90, 0x5f, 0xbe, 0xde, - 0x88, 0x69, 0x9c, 0x5f, 0x1d, 0x42, 0xaa, 0x61, 0xbb, 0xfd, 0xa7, 0xcd, 0xdd, 0x68, 0x6d, 0xd2, - 0x64, 0x6d, 0x4a, 0x0b, 0x72, 0x54, 0xf6, 0x40, 0x1f, 0xb0, 0xae, 0xd8, 0x22, 0xb2, 0xdb, 0x37, - 0xd5, 0xcb, 0x77, 0x4a, 0x9d, 0x91, 0x40, 0x4c, 0x94, 0x65, 0x05, 0x78, 0xa8, 0xfa, 0xa7, 0x0c, - 0x4b, 0x42, 0xa0, 0x1d, 0x48, 0x09, 0x09, 0xd9, 0x8c, 0xd9, 0xed, 0xcd, 0xf9, 0xaa, 0xa1, 0xc6, - 0x3b, 0xae, 0x13, 0x60, 0x27, 0x18, 0x05, 0xa2, 0x66, 0xc8, 0x54, 0x6e, 0x41, 0xba, 0x3f, 0x40, - 0x96, 0xa3, 0x5b, 0x06, 0x5b, 0x5b, 0xa6, 0x91, 0x3d, 0x7f, 0xbd, 0x91, 0xda, 0xa1, 0xb1, 0xe6, - 0xae, 0x96, 0x62, 0xc9, 0xa6, 0xa1, 0x5c, 0x83, 0xa5, 0x01, 0xb6, 0xcc, 0x01, 0x61, 0x82, 0x25, - 0x34, 0x31, 0x52, 0x3e, 0x07, 0x99, 0x9a, 0xa4, 0x28, 0xb3, 0x15, 0x94, 0x54, 0xee, 0x20, 0x35, - 0x74, 0x90, 0xda, 0x0d, 0x1d, 0xd4, 0x48, 0xd3, 0x89, 0x9f, 0xff, 0xbe, 0x21, 0x69, 0x8c, 0xa1, - 0x34, 0x21, 0x6f, 0xa3, 0x80, 0xe8, 0x3d, 0xaa, 0x1e, 0x9d, 0x3e, 0xc9, 0x4a, 0x6c, 0x2c, 0x92, - 0x46, 0xa8, 0x1c, 0x8a, 0x42, 0xb9, 0x3c, 0x64, 0x28, 0x5b, 0x50, 0x60, 0xa5, 0xfa, 0xee, 0x70, - 0x68, 0x11, 0x9d, 0x6d, 0xc2, 0x12, 0xdb, 0x84, 0x65, 0x1a, 0xdf, 0x61, 0xe1, 0x87, 0x74, 0x3b, - 0xd6, 0x21, 0x63, 0x20, 0x82, 0x38, 0x24, 0xc5, 0x20, 0x69, 0x1a, 0x60, 0xc9, 0x8f, 0x61, 0xe5, - 0x18, 0xd9, 0x96, 0x81, 0x88, 0xeb, 0x07, 0x1c, 0x92, 0xe6, 0x55, 0x26, 0x61, 0x06, 0xfc, 0x04, - 0xd6, 0x1c, 0x7c, 0x42, 0xf4, 0x37, 0xd1, 0x19, 0x86, 0x56, 0x68, 0xee, 0xf1, 0x2c, 0xe3, 0x26, - 0x2c, 0xf7, 0xc3, 0x2d, 0xe0, 0x58, 0x60, 0xd8, 0x7c, 0x14, 0x65, 0xb0, 0xf7, 0x21, 0x8d, 0x3c, - 0x8f, 0x03, 0xb2, 0x0c, 0x90, 0x42, 0x9e, 0xc7, 0x52, 0x77, 0x60, 0x95, 0xf5, 0xe8, 0xe3, 0x60, - 0x64, 0x13, 0x51, 0x24, 0xc7, 0x30, 0x2b, 0x34, 0xa1, 0xf1, 0x38, 0xc3, 0x6e, 0x42, 0x1e, 0x1f, - 0x5b, 0x06, 0x76, 0xfa, 0x98, 0xe3, 0xf2, 0x0c, 0x97, 0x0b, 0x83, 0x0c, 0x74, 0x1b, 0x0a, 0x9e, - 0xef, 0x7a, 0x6e, 0x80, 0x7d, 0x1d, 0x19, 0x86, 0x8f, 0x83, 0xa0, 0xb8, 0xcc, 0xeb, 0x85, 0xf1, - 0x3a, 0x0f, 0x57, 0xef, 0x81, 0xbc, 0x8b, 0x08, 0x52, 0x0a, 0x90, 0x20, 0x27, 0x41, 0x51, 0xaa, - 0x24, 0xb6, 0x72, 0x1a, 0xfd, 0xbc, 0xf4, 0x38, 0xfe, 0x15, 0x07, 0xf9, 0xb1, 0x4b, 0xb0, 0x72, - 0x1f, 0x64, 0xba, 0x75, 0xcc, 0x9d, 0xcb, 0x8b, 0x3d, 0xdf, 0xb1, 0x4c, 0x07, 0x1b, 0x87, 0x81, - 0xd9, 0x1d, 0x7b, 0x58, 0x63, 0x94, 0x29, 0xbb, 0xc5, 0x67, 0xec, 0xb6, 0x06, 0x49, 0xdf, 0x1d, - 0x39, 0x06, 0x73, 0x61, 0x52, 0xe3, 0x03, 0xe5, 0x11, 0xa4, 0x23, 0x17, 0xc9, 0x57, 0x73, 0xd1, - 0x0a, 0x75, 0x11, 0x75, 0xba, 0x08, 0x68, 0xa9, 0x9e, 0x30, 0x53, 0x03, 0x32, 0xd1, 0xb5, 0x27, - 0x3c, 0x79, 0x35, 0x5b, 0x4f, 0x68, 0xca, 0x5d, 0x58, 0x8d, 0xbc, 0x11, 0x89, 0xcb, 0x1d, 0x59, - 0x88, 0x12, 0x42, 0xdd, 0x19, 0xdb, 0xe9, 0xfc, 0x02, 0x4b, 0xb1, 0xee, 0x26, 0xb6, 0x6b, 0xb2, - 0x9b, 0xec, 0x03, 0xc8, 0x04, 0x96, 0xe9, 0x20, 0x32, 0xf2, 0xb1, 0x70, 0xe6, 0x24, 0x50, 0x7d, - 0x11, 0x87, 0x25, 0xee, 0xf4, 0x29, 0xf5, 0xa4, 0xcb, 0xd5, 0x8b, 0x2f, 0x52, 0x2f, 0xf1, 0xb6, - 0xea, 0xed, 0x03, 0x44, 0x4b, 0x0a, 0x8a, 0x72, 0x25, 0xb1, 0x95, 0xdd, 0xbe, 0xb1, 0xa8, 0x1c, - 0x5f, 0x6e, 0xc7, 0x32, 0xc5, 0xa1, 0x9e, 0xa2, 0x46, 0xce, 0x4a, 0x4e, 0x5d, 0xa6, 0x75, 0xc8, - 0xf4, 0x2c, 0xa2, 0x23, 0xdf, 0x47, 0x63, 0x26, 0x67, 0x76, 0xfb, 0xa3, 0xf9, 0xda, 0xf4, 0x75, - 0x52, 0xe9, 0xeb, 0xa4, 0x36, 0x2c, 0x52, 0xa7, 0x58, 0x2d, 0xdd, 0x13, 0x5f, 0xd5, 0x0b, 0x09, - 0x32, 0xd1, 0xb4, 0xca, 0x3e, 0xe4, 0xc3, 0xd6, 0xf5, 0x27, 0x36, 0x32, 0x85, 0x55, 0x37, 0xff, - 0xa5, 0xff, 0x07, 0x36, 0x32, 0xb5, 0xac, 0x68, 0x99, 0x0e, 0x2e, 0xdf, 0xf0, 0xf8, 0x82, 0x0d, - 0x9f, 0x71, 0x58, 0xe2, 0xbf, 0x39, 0x6c, 0xc6, 0x0b, 0xf2, 0x9b, 0x5e, 0xf8, 0x39, 0x0e, 0xe9, - 0x36, 0x3b, 0xc4, 0xc8, 0xfe, 0xff, 0x8e, 0xe1, 0x3a, 0x64, 0x3c, 0xd7, 0xd6, 0x79, 0x46, 0x66, - 0x99, 0xb4, 0xe7, 0xda, 0xda, 0x9c, 0xcb, 0x92, 0xef, 0xf4, 0x8c, 0x2e, 0xbd, 0x03, 0x05, 0x53, - 0x6f, 0x2a, 0xf8, 0x1d, 0xe4, 0xb8, 0x20, 0xe2, 0xb1, 0xfd, 0x8c, 0x2a, 0xc1, 0x5e, 0x70, 0xfe, - 0xd6, 0x96, 0x17, 0x2d, 0x9e, 0xe3, 0x35, 0x81, 0xa6, 0x3c, 0xfe, 0x2a, 0x89, 0x97, 0xbf, 0xfc, - 0xcf, 0x67, 0x41, 0x13, 0xe8, 0xea, 0xaf, 0x12, 0x64, 0x58, 0xdb, 0x87, 0x98, 0xa0, 0x19, 0xf1, - 0xa4, 0xb7, 0x15, 0xef, 0x43, 0x00, 0x5e, 0x2c, 0xb0, 0x9e, 0x61, 0xb1, 0xb1, 0x19, 0x16, 0xe9, - 0x58, 0xcf, 0xb0, 0xf2, 0x45, 0xd4, 0x69, 0xe2, 0x2a, 0x9d, 0x8a, 0xa3, 0x1b, 0xf6, 0x7b, 0x1d, - 0x52, 0xce, 0x68, 0xa8, 0xd3, 0x67, 0x42, 0xe6, 0x96, 0x71, 0x46, 0xc3, 0xee, 0x49, 0x70, 0xe7, - 0x17, 0x09, 0xb2, 0x53, 0xc7, 0x47, 0x29, 0xc1, 0xb5, 0xc6, 0xc1, 0xd1, 0xce, 0xa3, 0x5d, 0xbd, - 0xb9, 0xab, 0x3f, 0x38, 0xa8, 0xef, 0xeb, 0x5f, 0xb6, 0x1e, 0xb5, 0x8e, 0xbe, 0x6a, 0x15, 0x62, - 0x4a, 0x0d, 0xd6, 0x58, 0x2e, 0x4a, 0xd5, 0x1b, 0x9d, 0xbd, 0x56, 0xb7, 0x20, 0x95, 0xde, 0x3b, - 0x3d, 0xab, 0xac, 0x4e, 0x95, 0xa9, 0xf7, 0x02, 0xec, 0x90, 0x79, 0xc2, 0xce, 0xd1, 0xe1, 0x61, - 0xb3, 0x5b, 0x88, 0xcf, 0x11, 0xc4, 0x0d, 0x79, 0x1b, 0x56, 0x67, 0x09, 0xad, 0xe6, 0x41, 0x21, - 0x51, 0x52, 0x4e, 0xcf, 0x2a, 0xcb, 0x53, 0xe8, 0x96, 0x65, 0x97, 0xd2, 0xdf, 0xbf, 0x28, 0xc7, - 0x7e, 0xfa, 0xa1, 0x1c, 0xbb, 0xf3, 0xa3, 0x04, 0xf9, 0x99, 0x53, 0xa2, 0xac, 0xc3, 0xf5, 0x4e, - 0x73, 0xbf, 0xb5, 0xb7, 0xab, 0x1f, 0x76, 0xf6, 0xf5, 0xee, 0xd7, 0xed, 0xbd, 0xa9, 0x2e, 0x6e, - 0x40, 0xae, 0xad, 0xed, 0x3d, 0x3e, 0xea, 0xee, 0xb1, 0x4c, 0x41, 0x2a, 0xad, 0x9c, 0x9e, 0x55, - 0xb2, 0x6d, 0x1f, 0x1f, 0xbb, 0x04, 0x33, 0xfe, 0x4d, 0x58, 0x6e, 0x6b, 0x7b, 0x7c, 0xb1, 0x1c, - 0x14, 0x2f, 0xad, 0x9e, 0x9e, 0x55, 0xf2, 0x6d, 0x1f, 0x73, 0x23, 0x30, 0xd8, 0x26, 0xe4, 0xdb, - 0xda, 0x51, 0xfb, 0xa8, 0x53, 0x3f, 0xe0, 0xa8, 0x44, 0xa9, 0x70, 0x7a, 0x56, 0xc9, 0x85, 0x47, - 0x9c, 0x82, 0x26, 0xeb, 0x6c, 0x3c, 0x78, 0x79, 0x5e, 0x96, 0x5e, 0x9d, 0x97, 0xa5, 0x3f, 0xce, - 0xcb, 0xd2, 0xf3, 0x8b, 0x72, 0xec, 0xd5, 0x45, 0x39, 0xf6, 0xdb, 0x45, 0x39, 0xf6, 0xcd, 0x3d, - 0xd3, 0x22, 0x83, 0x51, 0x4f, 0xed, 0xbb, 0xc3, 0xda, 0x64, 0x57, 0xa7, 0x3f, 0xa7, 0x7e, 0x5a, - 0xf4, 0x96, 0xd8, 0xe0, 0xd3, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb2, 0xd1, 0x12, 0x04, 0x70, - 0x0c, 0x00, 0x00, + // 1274 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4f, 0x6f, 0x1a, 0x47, + 0x14, 0x67, 0x61, 0x31, 0xf0, 0x00, 0x1b, 0xaf, 0xdc, 0x84, 0xe2, 0x16, 0x13, 0xdc, 0xa4, 0x4e, + 0x1a, 0x41, 0xe5, 0x4a, 0x55, 0x23, 0xf5, 0x02, 0x86, 0x38, 0x28, 0x36, 0xa0, 0x85, 0xa6, 0x6a, + 0x2f, 0xab, 0x81, 0x9d, 0x2c, 0xab, 0x2c, 0xbb, 0xab, 0xdd, 0xc1, 0x32, 0x39, 0xf4, 0x5c, 0xf9, + 0x94, 0x2f, 0xe0, 0x53, 0x5a, 0xa9, 0xdf, 0xa2, 0x3d, 0xe6, 0x54, 0xe5, 0xd8, 0x53, 0x5a, 0xd9, + 0xdf, 0xa0, 0xea, 0x07, 0xa8, 0xe6, 0xcf, 0x2e, 0x10, 0x4c, 0x1b, 0x35, 0x51, 0x2f, 0xf6, 0xce, + 0x7b, 0xbf, 0xdf, 0x9b, 0x79, 0xbf, 0xf9, 0xcd, 0x8c, 0x80, 0xeb, 0xae, 0xe7, 0x10, 0xa7, 0x4a, + 0xa6, 0x2e, 0xf6, 0xf9, 0xdf, 0x0a, 0x8b, 0x28, 0xd7, 0x08, 0xb6, 0x75, 0xec, 0x8d, 0x4d, 0x9b, + 0xf0, 0x48, 0x85, 0x65, 0x0b, 0xb7, 0xc8, 0xc8, 0xf4, 0x74, 0xcd, 0x45, 0x1e, 0x99, 0x56, 0x39, + 0xd9, 0x70, 0x0c, 0x67, 0xf6, 0xc5, 0xd1, 0x85, 0x1d, 0xc3, 0x71, 0x0c, 0x0b, 0x73, 0xc8, 0x60, + 0xf2, 0xb8, 0x4a, 0xcc, 0x31, 0xf6, 0x09, 0x1a, 0xbb, 0x02, 0xb0, 0xcd, 0x29, 0x96, 0x39, 0xf0, + 0xab, 0x03, 0x93, 0x2c, 0xcc, 0x5e, 0xd8, 0xe1, 0xc9, 0xa1, 0x37, 0x75, 0x89, 0x53, 0x1d, 0x63, + 0xef, 0x89, 0x85, 0x17, 0x00, 0x82, 0x7d, 0x82, 0x3d, 0xdf, 0x74, 0xec, 0xe0, 0x3f, 0x4f, 0x96, + 0xef, 0x41, 0xb6, 0x8b, 0x3c, 0xd2, 0xc3, 0xe4, 0x01, 0x46, 0x3a, 0xf6, 0x94, 0x2d, 0x88, 0x13, + 0x87, 0x20, 0x2b, 0x2f, 0x95, 0xa4, 0xbd, 0xac, 0xca, 0x07, 0x8a, 0x02, 0xf2, 0x08, 0xf9, 0xa3, + 0x7c, 0xb4, 0x24, 0xed, 0x65, 0x54, 0xf6, 0x5d, 0x9e, 0x80, 0x4c, 0xa9, 0x94, 0x61, 0xda, 0x3a, + 0x3e, 0x0d, 0x18, 0x6c, 0x40, 0xa3, 0x83, 0x29, 0xc1, 0xbe, 0xa0, 0xf0, 0x81, 0x52, 0x83, 0xb8, + 0xeb, 0x39, 0xce, 0xe3, 0x7c, 0xac, 0x24, 0xed, 0xa5, 0xf7, 0x6f, 0x56, 0x96, 0xa4, 0xe3, 0x7d, + 0x54, 0x78, 0x1f, 0x95, 0x2e, 0x05, 0xd7, 0xe5, 0x17, 0xaf, 0x76, 0x22, 0x2a, 0x67, 0x96, 0xc7, + 0x90, 0xa8, 0x5b, 0xce, 0xf0, 0x49, 0xab, 0x11, 0xae, 0x4a, 0x9a, 0xad, 0x4a, 0x69, 0x43, 0x86, + 0x0a, 0xee, 0x6b, 0x23, 0xd6, 0x0f, 0x9b, 0xfe, 0xca, 0x89, 0xb8, 0x44, 0x0b, 0xcd, 0x8b, 0x89, + 0xd2, 0xac, 0x00, 0x0f, 0x95, 0xff, 0x94, 0x61, 0x4d, 0x48, 0x73, 0x00, 0x09, 0x21, 0x1e, 0x9b, + 0x31, 0xbd, 0xbf, 0xbb, 0x5c, 0x35, 0x50, 0xf7, 0xc0, 0xb1, 0x7d, 0x6c, 0xfb, 0x13, 0x5f, 0xd4, + 0x0c, 0x98, 0xca, 0x2d, 0x48, 0x0e, 0x47, 0xc8, 0xb4, 0x35, 0x53, 0x67, 0x6b, 0x4b, 0xd5, 0xd3, + 0x17, 0xaf, 0x76, 0x12, 0x07, 0x34, 0xd6, 0x6a, 0xa8, 0x09, 0x96, 0x6c, 0xe9, 0xca, 0x35, 0x58, + 0x1b, 0x61, 0xd3, 0x18, 0x11, 0x26, 0x55, 0x4c, 0x15, 0x23, 0xe5, 0x0b, 0x90, 0xa9, 0x3d, 0xf2, + 0x32, 0x5b, 0x41, 0xa1, 0xc2, 0xbd, 0x53, 0x09, 0xbc, 0x53, 0xe9, 0x07, 0xde, 0xa9, 0x27, 0xe9, + 0xc4, 0xcf, 0x7e, 0xdf, 0x91, 0x54, 0xc6, 0x50, 0x5a, 0x90, 0xb5, 0x90, 0x4f, 0xb4, 0x01, 0x55, + 0x8f, 0x4e, 0x1f, 0x67, 0x25, 0x76, 0x56, 0x49, 0x23, 0x54, 0x0e, 0x44, 0xa1, 0x5c, 0x1e, 0xd2, + 0x95, 0x3d, 0xc8, 0xb1, 0x52, 0x43, 0x67, 0x3c, 0x36, 0x89, 0xc6, 0x36, 0x61, 0x8d, 0x6d, 0xc2, + 0x3a, 0x8d, 0x1f, 0xb0, 0xf0, 0x03, 0xba, 0x1d, 0xdb, 0x90, 0xd2, 0x11, 0x41, 0x1c, 0x92, 0x60, + 0x90, 0x24, 0x0d, 0xb0, 0xe4, 0xc7, 0xb0, 0x71, 0x82, 0x2c, 0x53, 0x47, 0xc4, 0xf1, 0x7c, 0x0e, + 0x49, 0xf2, 0x2a, 0xb3, 0x30, 0x03, 0x7e, 0x0a, 0x5b, 0x36, 0x3e, 0x25, 0xda, 0xeb, 0xe8, 0x14, + 0x43, 0x2b, 0x34, 0xf7, 0x68, 0x91, 0x71, 0x13, 0xd6, 0x87, 0xc1, 0x16, 0x70, 0x2c, 0x30, 0x6c, + 0x36, 0x8c, 0x32, 0xd8, 0xfb, 0x90, 0x44, 0xae, 0xcb, 0x01, 0x69, 0x06, 0x48, 0x20, 0xd7, 0x65, + 0xa9, 0x3b, 0xb0, 0xc9, 0x7a, 0xf4, 0xb0, 0x3f, 0xb1, 0x88, 0x28, 0x92, 0x61, 0x98, 0x0d, 0x9a, + 0x50, 0x79, 0x9c, 0x61, 0x77, 0x21, 0x8b, 0x4f, 0x4c, 0x1d, 0xdb, 0x43, 0xcc, 0x71, 0x59, 0x86, + 0xcb, 0x04, 0x41, 0x06, 0xba, 0x0d, 0x39, 0xd7, 0x73, 0x5c, 0xc7, 0xc7, 0x9e, 0x86, 0x74, 0xdd, + 0xc3, 0xbe, 0x9f, 0x5f, 0xe7, 0xf5, 0x82, 0x78, 0x8d, 0x87, 0xcb, 0x77, 0x41, 0x6e, 0x20, 0x82, + 0x94, 0x1c, 0xc4, 0xc8, 0xa9, 0x9f, 0x97, 0x4a, 0xb1, 0xbd, 0x8c, 0x4a, 0x3f, 0xaf, 0x3c, 0x88, + 0x7f, 0x45, 0x41, 0x7e, 0xe4, 0x10, 0xac, 0xdc, 0x03, 0x99, 0x6e, 0x1d, 0x73, 0xe7, 0xfa, 0x6a, + 0xcf, 0xf7, 0x4c, 0xc3, 0xc6, 0xfa, 0xb1, 0x6f, 0xf4, 0xa7, 0x2e, 0x56, 0x19, 0x65, 0xce, 0x6e, + 0xd1, 0x05, 0xbb, 0x6d, 0x41, 0xdc, 0x73, 0x26, 0xb6, 0xce, 0x5c, 0x18, 0x57, 0xf9, 0x40, 0x79, + 0x08, 0xc9, 0xd0, 0x45, 0xf2, 0x9b, 0xb9, 0x68, 0x83, 0xba, 0x88, 0x3a, 0x5d, 0x04, 0xd4, 0xc4, + 0x40, 0x98, 0xa9, 0x0e, 0xa9, 0xf0, 0xc2, 0x13, 0x9e, 0x7c, 0x33, 0x5b, 0xcf, 0x68, 0xca, 0x27, + 0xb0, 0x19, 0x7a, 0x23, 0x14, 0x97, 0x3b, 0x32, 0x17, 0x26, 0x84, 0xba, 0x0b, 0xb6, 0xd3, 0xf8, + 0xd5, 0x95, 0x60, 0xdd, 0xcd, 0x6c, 0xd7, 0x62, 0x77, 0xd8, 0x07, 0x90, 0xf2, 0x4d, 0xc3, 0x46, + 0x64, 0xe2, 0x61, 0xe1, 0xcc, 0x59, 0xa0, 0xfc, 0x3c, 0x0a, 0x6b, 0xdc, 0xe9, 0x73, 0xea, 0x49, + 0x57, 0xab, 0x17, 0x5d, 0xa5, 0x5e, 0xec, 0x6d, 0xd5, 0x3b, 0x04, 0x08, 0x97, 0xe4, 0xe7, 0xe5, + 0x52, 0x6c, 0x2f, 0xbd, 0x7f, 0x63, 0x55, 0x39, 0xbe, 0xdc, 0x9e, 0x69, 0x88, 0x43, 0x3d, 0x47, + 0x0d, 0x9d, 0x15, 0x9f, 0xbb, 0x4c, 0x6b, 0x90, 0x1a, 0x98, 0x44, 0x43, 0x9e, 0x87, 0xa6, 0x4c, + 0xce, 0xf4, 0xfe, 0x47, 0xcb, 0xb5, 0xe9, 0xbb, 0x54, 0xa1, 0xef, 0x52, 0xa5, 0x6e, 0x92, 0x1a, + 0xc5, 0xaa, 0xc9, 0x81, 0xf8, 0x2a, 0x5f, 0x4a, 0x90, 0x0a, 0xa7, 0x55, 0x0e, 0x21, 0x1b, 0xb4, + 0xae, 0x3d, 0xb6, 0x90, 0x21, 0xac, 0xba, 0xfb, 0x2f, 0xfd, 0xdf, 0xb7, 0x90, 0xa1, 0xa6, 0x45, + 0xcb, 0x74, 0x70, 0xf5, 0x86, 0x47, 0x57, 0x6c, 0xf8, 0x82, 0xc3, 0x62, 0xff, 0xcd, 0x61, 0x0b, + 0x5e, 0x90, 0x5f, 0xf7, 0xc2, 0xcf, 0x51, 0x48, 0x76, 0xd9, 0x21, 0x46, 0xd6, 0xff, 0x77, 0x0c, + 0xb7, 0x21, 0xe5, 0x3a, 0x96, 0xc6, 0x33, 0x32, 0xcb, 0x24, 0x5d, 0xc7, 0x52, 0x97, 0x5c, 0x16, + 0x7f, 0xa7, 0x67, 0x74, 0xed, 0x1d, 0x28, 0x98, 0x78, 0x5d, 0xc1, 0xef, 0x20, 0xc3, 0x05, 0x11, + 0x8f, 0xed, 0xe7, 0x54, 0x09, 0xf6, 0x82, 0xf3, 0xb7, 0xb6, 0xb8, 0x6a, 0xf1, 0x1c, 0xaf, 0x0a, + 0x34, 0xe5, 0xf1, 0x57, 0x49, 0xbc, 0xfc, 0xc5, 0x7f, 0x3e, 0x0b, 0xaa, 0x40, 0x97, 0x7f, 0x95, + 0x20, 0xc5, 0xda, 0x3e, 0xc6, 0x04, 0x2d, 0x88, 0x27, 0xbd, 0xad, 0x78, 0x1f, 0x02, 0xf0, 0x62, + 0xbe, 0xf9, 0x14, 0x8b, 0x8d, 0x4d, 0xb1, 0x48, 0xcf, 0x7c, 0x8a, 0x95, 0x2f, 0xc3, 0x4e, 0x63, + 0x6f, 0xd2, 0xa9, 0x38, 0xba, 0x41, 0xbf, 0xd7, 0x21, 0x61, 0x4f, 0xc6, 0x1a, 0x7d, 0x26, 0x64, + 0x6e, 0x19, 0x7b, 0x32, 0xee, 0x9f, 0xfa, 0x77, 0x7e, 0x91, 0x20, 0x3d, 0x77, 0x7c, 0x94, 0x02, + 0x5c, 0xab, 0x1f, 0x75, 0x0e, 0x1e, 0x36, 0xb4, 0x56, 0x43, 0xbb, 0x7f, 0x54, 0x3b, 0xd4, 0xbe, + 0x6a, 0x3f, 0x6c, 0x77, 0xbe, 0x6e, 0xe7, 0x22, 0x4a, 0x15, 0xb6, 0x58, 0x2e, 0x4c, 0xd5, 0xea, + 0xbd, 0x66, 0xbb, 0x9f, 0x93, 0x0a, 0xef, 0x9d, 0x9d, 0x97, 0x36, 0xe7, 0xca, 0xd4, 0x06, 0x3e, + 0xb6, 0xc9, 0x32, 0xe1, 0xa0, 0x73, 0x7c, 0xdc, 0xea, 0xe7, 0xa2, 0x4b, 0x04, 0x71, 0x43, 0xde, + 0x86, 0xcd, 0x45, 0x42, 0xbb, 0x75, 0x94, 0x8b, 0x15, 0x94, 0xb3, 0xf3, 0xd2, 0xfa, 0x1c, 0xba, + 0x6d, 0x5a, 0x85, 0xe4, 0xf7, 0xcf, 0x8b, 0x91, 0x9f, 0x7e, 0x28, 0x46, 0xee, 0xfc, 0x28, 0x41, + 0x76, 0xe1, 0x94, 0x28, 0xdb, 0x70, 0xbd, 0xd7, 0x3a, 0x6c, 0x37, 0x1b, 0xda, 0x71, 0xef, 0x50, + 0xeb, 0x7f, 0xd3, 0x6d, 0xce, 0x75, 0x71, 0x03, 0x32, 0x5d, 0xb5, 0xf9, 0xa8, 0xd3, 0x6f, 0xb2, + 0x4c, 0x4e, 0x2a, 0x6c, 0x9c, 0x9d, 0x97, 0xd2, 0x5d, 0x0f, 0x9f, 0x38, 0x04, 0x33, 0xfe, 0x4d, + 0x58, 0xef, 0xaa, 0x4d, 0xbe, 0x58, 0x0e, 0x8a, 0x16, 0x36, 0xcf, 0xce, 0x4b, 0xd9, 0xae, 0x87, + 0xb9, 0x11, 0x18, 0x6c, 0x17, 0xb2, 0x5d, 0xb5, 0xd3, 0xed, 0xf4, 0x6a, 0x47, 0x1c, 0x15, 0x2b, + 0xe4, 0xce, 0xce, 0x4b, 0x99, 0xe0, 0x88, 0x53, 0xd0, 0x6c, 0x9d, 0xf5, 0xfb, 0x2f, 0x2e, 0x8a, + 0xd2, 0xcb, 0x8b, 0xa2, 0xf4, 0xc7, 0x45, 0x51, 0x7a, 0x76, 0x59, 0x8c, 0xbc, 0xbc, 0x2c, 0x46, + 0x7e, 0xbb, 0x2c, 0x46, 0xbe, 0xbd, 0x6b, 0x98, 0x64, 0x34, 0x19, 0x54, 0x86, 0xce, 0xb8, 0x3a, + 0xdb, 0xd5, 0xf9, 0xcf, 0xb9, 0x1f, 0x15, 0x83, 0x35, 0x36, 0xf8, 0xec, 0xef, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x5f, 0xad, 0x08, 0x71, 0x6a, 0x0c, 0x00, 0x00, } func (m *PartSetHeader) Marshal() (dAtA []byte, err error) { diff --git a/proto/types/types.proto b/proto/types/types.proto index c35eb6b73..8663ad6f7 100644 --- a/proto/types/types.proto +++ b/proto/types/types.proto @@ -38,9 +38,9 @@ message PartSetHeader { } message Part { - uint32 index = 1; - bytes bytes = 2; - tendermint.proto.crypto.merkle.SimpleProof proof = 3 [(gogoproto.nullable) = false]; + uint32 index = 1; + bytes bytes = 2; + tendermint.proto.crypto.merkle.Proof proof = 3 [(gogoproto.nullable) = false]; } // BlockID diff --git a/types/block.go b/types/block.go index 0aedbe3e2..0c3194ac1 100644 --- a/types/block.go +++ b/types/block.go @@ -449,7 +449,7 @@ func (h *Header) Hash() tmbytes.HexBytes { if h == nil || len(h.ValidatorsHash) == 0 { return nil } - return merkle.SimpleHashFromByteSlices([][]byte{ + return merkle.HashFromByteSlices([][]byte{ cdcEncode(h.Version), cdcEncode(h.ChainID), cdcEncode(h.Height), @@ -867,7 +867,7 @@ func (commit *Commit) Hash() tmbytes.HexBytes { for i, commitSig := range commit.Signatures { bs[i] = cdcEncode(commitSig) } - commit.hash = merkle.SimpleHashFromByteSlices(bs) + commit.hash = merkle.HashFromByteSlices(bs) } return commit.hash } diff --git a/types/block_test.go b/types/block_test.go index 06dce55d9..5bb0cd18e 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -306,7 +306,7 @@ func TestHeaderHash(t *testing.T) { byteSlices = append(byteSlices, cdcEncode(f.Interface())) } assert.Equal(t, - bytes.HexBytes(merkle.SimpleHashFromByteSlices(byteSlices)), tc.header.Hash()) + bytes.HexBytes(merkle.HashFromByteSlices(byteSlices)), tc.header.Hash()) } }) } diff --git a/types/evidence.go b/types/evidence.go index 6c59bf93a..15f00950a 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -520,7 +520,7 @@ func (evl EvidenceList) Hash() []byte { for i := 0; i < len(evl); i++ { evidenceBzs[i] = evl[i].Bytes() } - return merkle.SimpleHashFromByteSlices(evidenceBzs) + return merkle.HashFromByteSlices(evidenceBzs) } func (evl EvidenceList) String() string { diff --git a/types/part_set.go b/types/part_set.go index bb05ce1cd..afa292b16 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -21,9 +21,9 @@ var ( ) type Part struct { - Index uint32 `json:"index"` - Bytes tmbytes.HexBytes `json:"bytes"` - Proof merkle.SimpleProof `json:"proof"` + Index uint32 `json:"index"` + Bytes tmbytes.HexBytes `json:"bytes"` + Proof merkle.Proof `json:"proof"` } // ValidateBasic performs basic validation. @@ -72,7 +72,7 @@ func PartFromProto(pb *tmproto.Part) (*Part, error) { } part := new(Part) - proof, err := merkle.SimpleProofFromProto(&pb.Proof) + proof, err := merkle.ProofFromProto(&pb.Proof) if err != nil { return nil, err } @@ -166,7 +166,7 @@ func NewPartSetFromData(data []byte, partSize uint32) *PartSet { partsBitArray.SetIndex(int(i), true) } // Compute merkle proofs - root, proofs := merkle.SimpleProofsFromByteSlices(partsBytes) + root, proofs := merkle.ProofsFromByteSlices(partsBytes) for i := uint32(0); i < total; i++ { parts[i].Proof = *proofs[i] } diff --git a/types/part_set_test.go b/types/part_set_test.go index 16ab388a1..b7253da10 100644 --- a/types/part_set_test.go +++ b/types/part_set_test.go @@ -115,7 +115,7 @@ func TestPartValidateBasic(t *testing.T) { {"Good Part", func(pt *Part) {}, false}, {"Too big part", func(pt *Part) { pt.Bytes = make([]byte, BlockPartSizeBytes+1) }, true}, {"Too big proof", func(pt *Part) { - pt.Proof = merkle.SimpleProof{ + pt.Proof = merkle.Proof{ Total: 1, Index: 1, LeafHash: make([]byte, 1024*1024), @@ -160,7 +160,7 @@ func TestParSetHeaderProtoBuf(t *testing.T) { func TestPartProtoBuf(t *testing.T) { - proof := merkle.SimpleProof{ + proof := merkle.Proof{ Total: 1, Index: 1, LeafHash: tmrand.Bytes(32), diff --git a/types/results.go b/types/results.go index 11ddbcea9..05937d550 100644 --- a/types/results.go +++ b/types/results.go @@ -54,12 +54,12 @@ func (a ABCIResults) Bytes() []byte { func (a ABCIResults) Hash() []byte { // NOTE: we copy the impl of the merkle tree for txs - // we should be consistent and either do it for both or not. - return merkle.SimpleHashFromByteSlices(a.toByteSlices()) + return merkle.HashFromByteSlices(a.toByteSlices()) } // ProveResult returns a merkle proof of one result from the set -func (a ABCIResults) ProveResult(i int) merkle.SimpleProof { - _, proofs := merkle.SimpleProofsFromByteSlices(a.toByteSlices()) +func (a ABCIResults) ProveResult(i int) merkle.Proof { + _, proofs := merkle.ProofsFromByteSlices(a.toByteSlices()) return *proofs[i] } diff --git a/types/tx.go b/types/tx.go index f9dec2c01..402a376b6 100644 --- a/types/tx.go +++ b/types/tx.go @@ -37,7 +37,7 @@ func (txs Txs) Hash() []byte { for i := 0; i < len(txs); i++ { txBzs[i] = txs[i].Hash() } - return merkle.SimpleHashFromByteSlices(txBzs) + return merkle.HashFromByteSlices(txBzs) } // Index returns the index of this transaction in the list, or -1 if not found @@ -69,7 +69,7 @@ func (txs Txs) Proof(i int) TxProof { for i := 0; i < l; i++ { bzs[i] = txs[i].Hash() } - root, proofs := merkle.SimpleProofsFromByteSlices(bzs) + root, proofs := merkle.ProofsFromByteSlices(bzs) return TxProof{ RootHash: root, @@ -80,9 +80,9 @@ func (txs Txs) Proof(i int) TxProof { // TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. type TxProof struct { - RootHash tmbytes.HexBytes `json:"root_hash"` - Data Tx `json:"data"` - Proof merkle.SimpleProof `json:"proof"` + RootHash tmbytes.HexBytes `json:"root_hash"` + Data Tx `json:"data"` + Proof merkle.Proof `json:"proof"` } // Leaf returns the hash(tx), which is the leaf in the merkle tree which this proof refers to. diff --git a/types/validator_set.go b/types/validator_set.go index 1f56faaac..d34f3decc 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -352,7 +352,7 @@ func (vals *ValidatorSet) Hash() []byte { for i, val := range vals.Validators { bzs[i] = val.Bytes() } - return merkle.SimpleHashFromByteSlices(bzs) + return merkle.HashFromByteSlices(bzs) } // Iterate will run the given function over the set. From b1dba352b08ce907e5a6b29f2e41838d3f57be86 Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 10 Jun 2020 18:56:24 +0200 Subject: [PATCH 07/12] light: added more tests for pruning, initialization and bisection (#4978) --- CHANGELOG_PENDING.md | 1 + light/client.go | 22 ++++-- light/client_test.go | 156 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 164 insertions(+), 15 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index e424bfbc9..acde88167 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -81,6 +81,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [rpc] [\#4532](https://github.com/tendermint/tendermint/pull/4923) Support `BlockByHash` query (@fedekunze) - [rpc] \#4979 Support EXISTS operator in `/tx_search` query (@melekes) - [p2p] \#4981 Expose `SaveAs` func on NodeKey (@melekes) +- [evidence] [#4821](https://github.com/tendermint/tendermint/pull/4821) Amnesia evidence can be detected, verified and committed (@cmwaters) ### IMPROVEMENTS: diff --git a/light/client.go b/light/client.go index 7ac138c76..8c9e1e2e6 100644 --- a/light/client.go +++ b/light/client.go @@ -477,6 +477,8 @@ func (c *Client) compareWithLatestHeight(height int64) (int64, error) { // // It returns provider.ErrSignedHeaderNotFound if header is not found by // primary. +// +// It will replace the primary provider if an error from a request to the provider occurs func (c *Client) VerifyHeaderAtHeight(height int64, now time.Time) (*types.SignedHeader, error) { if height <= 0 { return nil, errors.New("negative or zero height") @@ -639,7 +641,7 @@ func (c *Client) sequence( } // 2) Verify them - c.logger.Debug("Verify newHeader against trustedHeader", + c.logger.Debug("Verify adjacent newHeader against trustedHeader", "trustedHeight", trustedHeader.Height, "trustedHash", hash2str(trustedHeader.Hash()), "newHeight", interimHeader.Height, @@ -648,7 +650,7 @@ func (c *Client) sequence( err = VerifyAdjacent(c.chainID, trustedHeader, interimHeader, interimVals, c.trustingPeriod, now, c.maxClockDrift) if err != nil { - err = fmt.Errorf("verify adjacent from #%d to #%d failed: %w", + err := fmt.Errorf("verify adjacent from #%d to #%d failed: %w", trustedHeader.Height, interimHeader.Height, err) switch errors.Unwrap(err).(type) { @@ -657,7 +659,7 @@ func (c *Client) sequence( replaceErr := c.replacePrimaryProvider() if replaceErr != nil { c.logger.Error("Can't replace primary", "err", replaceErr) - return err // return original error + return fmt.Errorf("%v. Tried to replace primary but: %w", err.Error(), replaceErr) } // attempt to verify header again height-- @@ -700,7 +702,7 @@ func (c *Client) bisection( ) for { - c.logger.Debug("Verify newHeader against trustedHeader", + c.logger.Debug("Verify non-adjacent newHeader against trustedHeader", "trustedHeight", trustedHeader.Height, "trustedHash", hash2str(trustedHeader.Hash()), "newHeight", headerCache[depth].sh.Height, @@ -752,8 +754,18 @@ func (c *Client) bisection( return fmt.Errorf("verify non adjacent from #%d to #%d failed: %w", trustedHeader.Height, headerCache[depth].sh.Height, err) } + newProviderHeader, newProviderVals, err := c.fetchHeaderAndValsAtHeight(newHeader.Height) + if err != nil { + return err + } + if !bytes.Equal(newProviderHeader.Hash(), newHeader.Hash()) || !bytes.Equal(newProviderVals.Hash(), newVals.Hash()) { + err := fmt.Errorf("replacement provider has a different header: %X and/or vals: %X at height: %d"+ + "to the one being verified", newProviderHeader.Hash(), newProviderVals.Hash(), newHeader.Height) + return fmt.Errorf("verify non adjacent from #%d to #%d failed: %w", + trustedHeader.Height, headerCache[depth].sh.Height, err) + } // attempt to verify the header again - continue + return c.bisection(initiallyTrustedHeader, initiallyTrustedVals, newHeader, newVals, now) default: return fmt.Errorf("verify non adjacent from #%d to #%d failed: %w", diff --git a/light/client_test.go b/light/client_test.go index 19851d6e5..215e03704 100644 --- a/light/client_test.go +++ b/light/client_test.go @@ -62,6 +62,52 @@ var ( largeFullNode = mockp.New(GenMockNode(chainID, 10, 3, 0, bTime)) ) +func TestValidateTrustOptions(t *testing.T) { + testCases := []struct { + err bool + to light.TrustOptions + }{ + { + false, + trustOptions, + }, + { + true, + light.TrustOptions{ + Period: -1 * time.Hour, + Height: 1, + Hash: h1.Hash(), + }, + }, + { + true, + light.TrustOptions{ + Period: 1 * time.Hour, + Height: 0, + Hash: h1.Hash(), + }, + }, + { + true, + light.TrustOptions{ + Period: 1 * time.Hour, + Height: 1, + Hash: []byte("incorrect hash"), + }, + }, + } + + for _, tc := range testCases { + err := tc.to.ValidateBasic() + if tc.err { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + } + +} + func TestClient_SequentialVerification(t *testing.T) { newKeys := genPrivKeys(4) newVals := newKeys.ToValidators(10, 1) @@ -296,8 +342,11 @@ func TestClient_SkippingVerification(t *testing.T) { }) } - // start from a large header to make sure that the pivot height doesn't select a height outside - // the appropriate range +} + +// start from a large header to make sure that the pivot height doesn't select a height outside +// the appropriate range +func TestClientLargeBisectionVerification(t *testing.T) { veryLargeFullNode := mockp.New(GenMockNode(chainID, 100, 3, 1, bTime)) h1, err := veryLargeFullNode.SignedHeader(90) require.NoError(t, err) @@ -321,6 +370,34 @@ func TestClient_SkippingVerification(t *testing.T) { assert.Equal(t, h, h2) } +func TestClientBisectionBetweenTrustedHeaders(t *testing.T) { + c, err := light.NewClient( + chainID, + light.TrustOptions{ + Period: 4 * time.Hour, + Height: 1, + Hash: h1.Hash(), + }, + fullNode, + []provider.Provider{fullNode}, + dbs.New(dbm.NewMemDB(), chainID), + light.SkippingVerification(light.DefaultTrustLevel), + ) + require.NoError(t, err) + + _, err = c.VerifyHeaderAtHeight(3, bTime.Add(2*time.Hour)) + require.NoError(t, err) + + // confirm that the client already doesn't have the header + _, err = c.TrustedHeader(2) + require.Error(t, err) + + // verify using bisection the header between the two trusted headers + _, err = c.VerifyHeaderAtHeight(2, bTime.Add(1*time.Hour)) + assert.NoError(t, err) + +} + func TestClient_Cleanup(t *testing.T) { c, err := light.NewClient( chainID, @@ -514,12 +591,11 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) { func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) { // 1. options.Hash == trustedHeader.Hash { + // load the first three headers into the trusted store trustedStore := dbs.New(dbm.NewMemDB(), chainID) err := trustedStore.SaveSignedHeaderAndValidatorSet(h1, vals) require.NoError(t, err) - //header2 := keys.GenSignedHeader(chainID, 2, bTime.Add(2*time.Hour), nil, vals, vals, - // []byte("app_hash"), []byte("cons_hash"), []byte("results_hash"), 0, len(keys)) err = trustedStore.SaveSignedHeaderAndValidatorSet(h2, vals) require.NoError(t, err) @@ -554,6 +630,10 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) { valSet, _, err = c.TrustedValidatorSet(2) assert.Error(t, err) assert.Nil(t, valSet) + + h, err = c.TrustedHeader(3) + assert.Error(t, err) + assert.Nil(t, h) } // 2. options.Hash != trustedHeader.Hash @@ -907,26 +987,60 @@ func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) { // header should still be verified assert.EqualValues(t, 2, h.Height) - // no witnesses left to verify -> error + // remaining withness doesn't have header -> error _, err = c.VerifyHeaderAtHeight(3, bTime.Add(2*time.Hour)) - assert.Error(t, err) + if assert.Error(t, err) { + assert.Equal(t, "awaiting response from all witnesses exceeded dropout time", err.Error()) + } assert.EqualValues(t, 0, len(c.Witnesses())) + + // no witnesses left, will not be allowed to verify a header + _, err = c.VerifyHeaderAtHeight(3, bTime.Add(2*time.Hour)) + if assert.Error(t, err) { + assert.Equal(t, "no witnesses connected. please reset light client", err.Error()) + } } func TestClientTrustedValidatorSet(t *testing.T) { + noValSetNode := mockp.New( + chainID, + headerSet, + map[int64]*types.ValidatorSet{ + 1: nil, + 2: nil, + 3: nil, + }, + ) + + differentVals, _ := types.RandValidatorSet(10, 100) + + badValSetNode := mockp.New( + chainID, + headerSet, + map[int64]*types.ValidatorSet{ + 1: vals, + 2: differentVals, + 3: differentVals, + }, + ) + c, err := light.NewClient( chainID, trustOptions, - fullNode, - []provider.Provider{fullNode}, + noValSetNode, + []provider.Provider{badValSetNode, fullNode, fullNode}, dbs.New(dbm.NewMemDB(), chainID), light.Logger(log.TestingLogger()), ) - require.NoError(t, err) + assert.Equal(t, 2, len(c.Witnesses())) _, err = c.VerifyHeaderAtHeight(2, bTime.Add(2*time.Hour).Add(1*time.Second)) - require.NoError(t, err) + assert.Error(t, err) + assert.Equal(t, 1, len(c.Witnesses())) + + _, err = c.VerifyHeaderAtHeight(2, bTime.Add(2*time.Hour).Add(1*time.Second)) + assert.NoError(t, err) valSet, height, err := c.TrustedValidatorSet(0) assert.NoError(t, err) @@ -974,6 +1088,28 @@ func TestClientReportsConflictingHeadersEvidence(t *testing.T) { assert.True(t, fullNode.HasEvidence(ev)) } +func TestClientPrunesHeadersAndValidatorSets(t *testing.T) { + c, err := light.NewClient( + chainID, + trustOptions, + fullNode, + []provider.Provider{fullNode}, + dbs.New(dbm.NewMemDB(), chainID), + light.Logger(log.TestingLogger()), + light.PruningSize(1), + ) + require.NoError(t, err) + _, err = c.TrustedHeader(1) + require.NoError(t, err) + + h, err := c.Update(bTime.Add(2 * time.Hour)) + require.NoError(t, err) + require.Equal(t, int64(3), h.Height) + + _, err = c.TrustedHeader(1) + assert.Error(t, err) +} + func TestClientEnsureValidHeadersAndValSets(t *testing.T) { emptyValSet := &types.ValidatorSet{ Validators: nil, From a057da6ab5d373caf15cfc0ee7be87f656e2576a Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 10 Jun 2020 19:49:27 +0200 Subject: [PATCH 08/12] toml: make sections standout (#4993) ## Description make sections in the toml standout. Making this PR as I found it hard to find different sections on the `config.toml` when it was generated. This makes it somewhat simpler Closes: #XXX --- config/toml.go | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/config/toml.go b/config/toml.go index 2343b1646..a6f699620 100644 --- a/config/toml.go +++ b/config/toml.go @@ -72,7 +72,9 @@ const defaultConfigTemplate = `# This is a TOML config file. # "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable # or --home cmd flag. -##### main base config options ##### +####################################################################### +### Main Base Config Options ### +####################################################################### # TCP or UNIX socket address of the ABCI application, # or the name of an ABCI application compiled in with the Tendermint binary @@ -141,9 +143,14 @@ prof_laddr = "{{ .BaseConfig.ProfListenAddress }}" # so the app can decide if we should keep the connection or not filter_peers = {{ .BaseConfig.FilterPeers }} -##### advanced configuration options ##### -##### rpc server configuration options ##### +####################################################################### +### Advanced Configuration Options ### +####################################################################### + +####################################################### +### RPC Server Configuration Options ### +####################################################### [rpc] # TCP or UNIX socket address for the RPC server to listen on @@ -222,7 +229,9 @@ tls_cert_file = "{{ .RPC.TLSCertFile }}" # Otherwise, HTTP server is run. tls_key_file = "{{ .RPC.TLSKeyFile }}" -##### peer to peer configuration options ##### +####################################################### +### P2P Configuration Options ### +####################################################### [p2p] # Address to listen for incoming connections @@ -293,7 +302,9 @@ allow_duplicate_ip = {{ .P2P.AllowDuplicateIP }} handshake_timeout = "{{ .P2P.HandshakeTimeout }}" dial_timeout = "{{ .P2P.DialTimeout }}" -##### mempool configuration options ##### +####################################################### +### Mempool Configurattion Option ### +####################################################### [mempool] recheck = {{ .Mempool.Recheck }} @@ -315,7 +326,9 @@ cache_size = {{ .Mempool.CacheSize }} # NOTE: the max size of a tx transmitted over the network is {max_tx_bytes} + {amino overhead}. max_tx_bytes = {{ .Mempool.MaxTxBytes }} -##### state sync configuration options ##### +####################################################### +### State Sync Configuration Options ### +####################################################### [statesync] # State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine # snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in @@ -339,7 +352,9 @@ trust_period = "{{ .StateSync.TrustPeriod }}" # Will create a new, randomly named directory within, and remove it when done. temp_dir = "{{ .StateSync.TempDir }}" -##### fast sync configuration options ##### +####################################################### +### Fast Sync Configuration Connections ### +####################################################### [fastsync] # Fast Sync version to use: @@ -348,7 +363,9 @@ temp_dir = "{{ .StateSync.TempDir }}" # 2) "v2" - complete redesign of v0, optimized for testability & readability version = "{{ .FastSync.Version }}" -##### consensus configuration options ##### +####################################################### +### Consensus Configuration Options ### +####################################################### [consensus] wal_file = "{{ js .Consensus.WalPath }}" @@ -372,7 +389,9 @@ create_empty_blocks_interval = "{{ .Consensus.CreateEmptyBlocksInterval }}" peer_gossip_sleep_duration = "{{ .Consensus.PeerGossipSleepDuration }}" peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}" -##### transactions indexer configuration options ##### +####################################################### +### Transaction Indexer Configuration Options ### +####################################################### [tx_index] # What indexer to use for transactions @@ -404,7 +423,9 @@ index_keys = "{{ .TxIndex.IndexKeys }}" # indexed). index_all_keys = {{ .TxIndex.IndexAllKeys }} -##### instrumentation configuration options ##### +####################################################### +### Instrumentation Configuration Options ### +####################################################### [instrumentation] # When true, Prometheus metrics are served under /metrics on From 18d333c3927f3dce0d8d5970ee40e5ffcc33448b Mon Sep 17 00:00:00 2001 From: Callum Waters Date: Wed, 10 Jun 2020 20:17:32 +0200 Subject: [PATCH 09/12] docs: update amnesia adr (#4994) --- .../adr-056-proving-amnesia-attacks.md | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/docs/architecture/adr-056-proving-amnesia-attacks.md b/docs/architecture/adr-056-proving-amnesia-attacks.md index f0200ca7d..4fb24e211 100644 --- a/docs/architecture/adr-056-proving-amnesia-attacks.md +++ b/docs/architecture/adr-056-proving-amnesia-attacks.md @@ -4,6 +4,7 @@ - 02.04.20: Initial Draft - 06.04.20: Second Draft +- 10.06.20: Post Implementation Revision ## Context @@ -28,31 +29,28 @@ This creates a fork on the main chain. Back to the past, another form of flip f As the distinction between these two attacks (amnesia and back to the past) can only be distinguished by confirming with all validators (to see if it is a full fork or a light fork), for the purpose of simplicity, these attacks will be treated as the same. -Currently, the evidence reactor is used to simply broadcast and store evidence. Instead of perhaps creating a new reactor for the specific task of verifying these attacks, the current evidence reactor will be extended. +Currently, the evidence reactor is used to simply broadcast and store evidence. The idea of creating a new reactor for the specific task of verifying these attacks was briefly discussed, but it is decided that the current evidence reactor will be extended. -The process begins with a light client receiving conflicting headers (in the future this could also be a full node during fast sync), which it sends to a full node to analyse. As part of [evidence handling](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-047-handling-evidence-from-light-client.md), this could be deduced into potential amnesia evidence +The process begins with a light client receiving conflicting headers (in the future this could also be a full node during fast sync or state sync), which it sends to a full node to analyse. As part of [evidence handling](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-047-handling-evidence-from-light-client.md), this is extracted into potential amnesia evidence when the validator voted in more than one round for a different block. ```golang type PotentialAmnesiaEvidence struct { - V1 []*types.Vote - V2 []*types.Vote + VoteA *types.Vote + VoteB *types.Vote - timestamp time.Time + Heightstamp int64 } ``` -*NOTE: Unlike prior evidence types, `PotentialAmnesiaEvidence` and `AmnesiaEvidence` are processed as a batch instead - of individually. This will require changes to much of the API.* +*NOTE: There had been an earlier notion towards batching evidence against the entire set of validators all together but this has given way to individual processing predominantly to maintain consistency with the other forms of evidence. A more extensive breakdown can be found [here](https://github.com/tendermint/tendermint/issues/4729)* - *NOTE: `PotentialAmnesiaEvidence` could be constructed for when 1/3 or less vote in two different rounds but as it is not currently detected nor can it cause a fork, it will be ignored.* +The evidence will contain the precommit votes for a validator that voted for both rounds. If the validator voted in more than two rounds, then they will have multiple `PotentialAmnesiaEvidence` against them hence it is possible that there is multiple evidence for a validator in a single height but not for a single round. The votes should be all valid and the height and time that the infringement was made should be within: -The evidence should contain the precommit votes for the intersection of validators that voted for both rounds. The votes should be all valid and the height and time that the infringement was made should be within: +`MaxEvidenceAge - ProofTrialPeriod` -`MaxEvidenceAge - Amnesia trial period` +This trial period will be discussed later. -where `Amnesia trial period` is a configurable duration defaulted at 1 day. - -With reference to the honest nodes, C1 and C2, in the schematic, C2 will not PRECOMMIT an earlier round, but it is likely, if a node in C1 were to receive +2/3 PREVOTE's or PRECOMMIT's for a higher round, that it would remove the lock and PREVOTE and PRECOMMIT for the later round. Therefore, unfortunately it is not a case of simply punishing all nodes that have double voted in the `PotentialAmnesiaEvidence`. +Returning to the event of an amnesia attack, if we were to examine the behaviour of the honest nodes, C1 and C2, in the schematic, C2 will not PRECOMMIT an earlier round, but it is likely, if a node in C1 were to receive +2/3 PREVOTE's or PRECOMMIT's for a higher round, that it would remove the lock and PREVOTE and PRECOMMIT for the later round. Therefore, unfortunately it is not a case of simply punishing all nodes that have double voted in the `PotentialAmnesiaEvidence`. Instead we use the Proof of Lock Change (PoLC) referred to in the [consensus spec](https://github.com/tendermint/spec/blob/master/spec/consensus/consensus.md#terms). When an honest node votes again for a different block in a later round (which will only occur in very rare cases), it will generate the PoLC and store it in the evidence reactor for a time equal to the `MaxEvidenceAge` @@ -60,27 +58,28 @@ Instead we use the Proof of Lock Change (PoLC) referred to in the [consensus spe ```golang type ProofOfLockChange struct { Votes []*types.Vote + PubKey crypto.PubKey } ``` This can be either evidence of +2/3 PREVOTES or PRECOMMITS (either warrants the honest node the right to vote) and is valid, among other checks, so long as the PRECOMMIT vote of the node in V2 came after all the votes in the `ProofOfLockChange` i.e. it received +2/3 votes for a block and then voted for that block thereafter (F is unable to prove this). -In the event that an honest node receives `PotentialAmnesiaEvidence` it will first `Verify()` it and then will check if it is among the suspected nodes in the evidence. If so, it will retrieve the `ProofOfLockChange` and combine it with `PotentialAmensiaEvidence` to form `AmensiaEvidence`: +In the event that an honest node receives `PotentialAmnesiaEvidence` it will first `ValidateBasic()` and `Verify()` it and then will check if it is among the suspected nodes in the evidence. If so, it will retrieve the `ProofOfLockChange` and combine it with `PotentialAmensiaEvidence` to form `AmensiaEvidence`. All honest nodes that are part of the indicted group will have a time, measured in blocks, equal to `ProofTrialPeriod`, the aforementioned evidence paramter, to gossip their `AmnesiaEvidence` with their `ProofOfLockChange` ```golang type AmnesiaEvidence struct { - Evidence *types.PotentialAmnesiaEvidence - Proofs []*types.ProofOfLockChange + *types.PotentialAmnesiaEvidence + Polc *types.ProofOfLockChange } ``` -If the node is not required to submit any proof than it will simply broadcast the `PotentialAmnesiaEvidence` . +If the node is not required to submit any proof than it will simply broadcast the `PotentialAmnesiaEvidence`, stamp the height that it received the evidence and begin to wait out the trial period. It will ignore other `PotentialAmnesiaEvidence` gossiped at the same height and round. -When a node has successfully validated `PotentialAmnesiaEvidence` it timestamps it and refuses to receive the same form of `PotentialAmnesiaEvidence`. If a node receives `AmnesiaEvidence` it checks it against any current `AmnesiaEvidence` it might have and if so merges the two by adding the proofs, if it doesn't have it yet it run's `Verify()` and stores it. +If a node receives `AmnesiaEvidence` that contains a valid `ProofOfClockChange` it will add it to the evidence store and replace any PotentialAmnesiaEvidence of the same height and round. At this stage, an amnesia evidence with polc, it is ready to be submitted to the chin. If a node receives `AmnesiaEvidence` with an empty polc it will ignore it as each honest node will conduct their own trial period to be sure that time was given for any other honest nodes to respond. There can only be one `AmnesiaEvidence` and one `PotentialAmneisaEvidence` stored for each attack (i.e. for each height). -When, `time.Now() > PotentialAmnesiaEvidence.timestamp + AmnesiaTrialPeriod`, honest validators of the current validator set can begin proposing the block that contains the `AmnesiaEvidence`. +When, `state.LastBlockHeight > PotentialAmnesiaEvidence.timestamp + ProofTrialPeriod`, nodes will upgrade the corresponding `PotentialAmnesiaEvidence` and attach an empty `ProofOfLockChange`. Then honest validators of the current validator set can begin proposing the block that contains the `AmnesiaEvidence`. *NOTE: Even before the evidence is proposed and committed, the off-chain process of gossiping valid evidence could be enough for honest nodes to recognize the fork and halt.* @@ -88,11 +87,12 @@ When, `time.Now() > PotentialAmnesiaEvidence.timestamp + AmnesiaTrialPeriod`, ho Other validators will vote if: - The Amnesia Evidence is not valid -- The Amensia Evidence is not within the validators trial period i.e. too soon. -- The Amensia Evidence is of the same height but is different to the Amnesia Evidence that they have. i.e. is missing proofs. - (In this case, the validator will try again to gossip the latest Amnesia Evidence that it has) +- The Amensia Evidence is not within their own trial period i.e. too soon. +- They don't have the Amnesia Evidence and it is has an empty polc (each validator needs to run their own trial period of the evidence) - Is of an AmnesiaEvidence that has already been committed to the chain. +Finally it is important to stress that the protocol of having a trial period addresses attacks where a validator voted again for a different block at a later round and time. In the event, however, that the validator voted for an earlier round after voting for a later round i.e. `VoteA.Timestamp < VoteB.Timestamp && VoteA.Round > VoteB.Round` then this action is inexcusable and can be punished immediately without the need of a trial period. In this case, PotentialAmnesiaEvidence will be instantly upgraded to AmnesiaEvidence. + ## Status @@ -102,7 +102,7 @@ Proposed ### Positive -Increasing fork detection makes the system more secure +Increasing fork detection and accountability makes the system more secure ### Negative @@ -112,7 +112,6 @@ A delay between the detection of a fork and the punishment of one ### Neutral -Evidence package will need to be able to handle batch evidence as well as individual evidence (i.e. extra work) ## References From 31a361d1197ce1350aac35b9bd749f0f59a084dc Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 11 Jun 2020 11:10:37 +0200 Subject: [PATCH 10/12] proto: move keys to oneof (#4983) --- abci/example/kvstore/kvstore_test.go | 3 +- abci/example/kvstore/persistent_kvstore.go | 27 +- abci/types/pubkey.go | 20 +- abci/types/types.pb.go | 578 +++++++-------------- abci/types/types.proto | 10 +- abci/types/util.go | 3 +- consensus/reactor_test.go | 19 +- consensus/replay_test.go | 13 +- crypto/crypto.go | 2 + crypto/ed25519/ed25519.go | 10 + crypto/encoding/amino/encode_test.go | 3 + crypto/secp256k1/secp256k1.go | 13 +- crypto/sr25519/privkey.go | 4 + crypto/sr25519/pubkey.go | 10 +- p2p/conn/secret_connection_test.go | 1 + proto/crypto/keys/types.pb.go | 19 +- proto/crypto/keys/types.proto | 5 - proto/crypto/merkle/types.pb.go | 2 +- rpc/client/evidence_test.go | 9 +- rpc/client/helpers.go | 1 + rpc/client/http/http.go | 3 + rpc/client/rpc_test.go | 1 - state/execution.go | 11 +- state/execution_test.go | 62 +-- state/state_test.go | 25 +- types/protobuf.go | 71 +-- types/protobuf_test.go | 28 +- 27 files changed, 368 insertions(+), 585 deletions(-) diff --git a/abci/example/kvstore/kvstore_test.go b/abci/example/kvstore/kvstore_test.go index ef678d40c..bc6303479 100644 --- a/abci/example/kvstore/kvstore_test.go +++ b/abci/example/kvstore/kvstore_test.go @@ -1,7 +1,6 @@ package kvstore import ( - "bytes" "fmt" "io/ioutil" "sort" @@ -220,7 +219,7 @@ func valsEqual(t *testing.T, vals1, vals2 []types.ValidatorUpdate) { sort.Sort(types.ValidatorUpdates(vals2)) for i, v1 := range vals1 { v2 := vals2[i] - if !bytes.Equal(v1.PubKey.Data, v2.PubKey.Data) || + if !v1.PubKey.Equal(v2.PubKey) || v1.Power != v2.Power { t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) } diff --git a/abci/example/kvstore/persistent_kvstore.go b/abci/example/kvstore/persistent_kvstore.go index 15765c1b8..b2e0da99b 100644 --- a/abci/example/kvstore/persistent_kvstore.go +++ b/abci/example/kvstore/persistent_kvstore.go @@ -11,8 +11,9 @@ import ( "github.com/tendermint/tendermint/abci/example/code" "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/log" + pc "github.com/tendermint/tendermint/proto/crypto/keys" tmtypes "github.com/tendermint/tendermint/types" ) @@ -30,7 +31,7 @@ type PersistentKVStoreApplication struct { // validator set ValUpdates []types.ValidatorUpdate - valAddrToPubKeyMap map[string]types.PubKey + valAddrToPubKeyMap map[string]pc.PublicKey logger log.Logger } @@ -46,7 +47,7 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication return &PersistentKVStoreApplication{ app: &Application{state: state}, - valAddrToPubKeyMap: make(map[string]types.PubKey), + valAddrToPubKeyMap: make(map[string]pc.PublicKey), logger: log.NewNopLogger(), } } @@ -136,6 +137,7 @@ func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) }) } } + return types.ResponseBeginBlock{} } @@ -185,8 +187,12 @@ func (app *PersistentKVStoreApplication) Validators() (validators []types.Valida return } -func MakeValSetChangeTx(pubkey types.PubKey, power int64) []byte { - pubStr := base64.StdEncoding.EncodeToString(pubkey.Data) +func MakeValSetChangeTx(pubkey pc.PublicKey, power int64) []byte { + pk, err := cryptoenc.PubKeyFromProto(pubkey) + if err != nil { + panic(err) + } + pubStr := base64.StdEncoding.EncodeToString(pk.Bytes()) return []byte(fmt.Sprintf("val:%s!%d", pubStr, power)) } @@ -230,10 +236,11 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.Respon // add, update, or remove a validator func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate) types.ResponseDeliverTx { - key := []byte("val:" + string(v.PubKey.Data)) - - pubkey := make(ed25519.PubKey, ed25519.PubKeySize) - copy(pubkey, v.PubKey.Data) + key := []byte("val:" + string(v.PubKey.GetEd25519())) + pubkey, err := cryptoenc.PubKeyFromProto(v.PubKey) + if err != nil { + panic(fmt.Errorf("can't decode public key: %w", err)) + } if v.Power == 0 { // remove validator @@ -242,7 +249,7 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate panic(err) } if !hasKey { - pubStr := base64.StdEncoding.EncodeToString(v.PubKey.Data) + pubStr := base64.StdEncoding.EncodeToString(pubkey.Bytes()) return types.ResponseDeliverTx{ Code: code.CodeTypeUnauthorized, Log: fmt.Sprintf("Cannot remove non-existent validator %s", pubStr)} diff --git a/abci/types/pubkey.go b/abci/types/pubkey.go index 46cd8c5e8..aaff6debb 100644 --- a/abci/types/pubkey.go +++ b/abci/types/pubkey.go @@ -1,16 +1,24 @@ package types +import ( + "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" +) + const ( PubKeyEd25519 = "ed25519" ) -func Ed25519ValidatorUpdate(pubkey []byte, power int64) ValidatorUpdate { +func Ed25519ValidatorUpdate(pk []byte, power int64) ValidatorUpdate { + pke := ed25519.PubKey(pk) + pkp, err := cryptoenc.PubKeyToProto(pke) + if err != nil { + panic(err) + } + return ValidatorUpdate{ // Address: - PubKey: PubKey{ - Type: PubKeyEd25519, - Data: pubkey, - }, - Power: power, + PubKey: pkp, + Power: power, } } diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index d2427b504..c207b24e1 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -10,6 +10,7 @@ import ( proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" _ "github.com/golang/protobuf/ptypes/timestamp" + keys "github.com/tendermint/tendermint/proto/crypto/keys" merkle "github.com/tendermint/tendermint/proto/crypto/merkle" types "github.com/tendermint/tendermint/proto/types" grpc "google.golang.org/grpc" @@ -2926,8 +2927,8 @@ func (m *Validator) GetPower() int64 { // ValidatorUpdate type ValidatorUpdate struct { - PubKey PubKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` - Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` + PubKey keys.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` } func (m *ValidatorUpdate) Reset() { *m = ValidatorUpdate{} } @@ -2963,11 +2964,11 @@ func (m *ValidatorUpdate) XXX_DiscardUnknown() { var xxx_messageInfo_ValidatorUpdate proto.InternalMessageInfo -func (m *ValidatorUpdate) GetPubKey() PubKey { +func (m *ValidatorUpdate) GetPubKey() keys.PublicKey { if m != nil { return m.PubKey } - return PubKey{} + return keys.PublicKey{} } func (m *ValidatorUpdate) GetPower() int64 { @@ -3030,58 +3031,6 @@ func (m *VoteInfo) GetSignedLastBlock() bool { return false } -type PubKey struct { - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (m *PubKey) Reset() { *m = PubKey{} } -func (m *PubKey) String() string { return proto.CompactTextString(m) } -func (*PubKey) ProtoMessage() {} -func (*PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_9f1eaa49c51fa1ac, []int{44} -} -func (m *PubKey) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PubKey.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *PubKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_PubKey.Merge(m, src) -} -func (m *PubKey) XXX_Size() int { - return m.Size() -} -func (m *PubKey) XXX_DiscardUnknown() { - xxx_messageInfo_PubKey.DiscardUnknown(m) -} - -var xxx_messageInfo_PubKey proto.InternalMessageInfo - -func (m *PubKey) GetType() string { - if m != nil { - return m.Type - } - return "" -} - -func (m *PubKey) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - type Evidence struct { Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` Validator Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator"` @@ -3094,7 +3043,7 @@ func (m *Evidence) Reset() { *m = Evidence{} } func (m *Evidence) String() string { return proto.CompactTextString(m) } func (*Evidence) ProtoMessage() {} func (*Evidence) Descriptor() ([]byte, []int) { - return fileDescriptor_9f1eaa49c51fa1ac, []int{45} + return fileDescriptor_9f1eaa49c51fa1ac, []int{44} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3170,7 +3119,7 @@ func (m *Snapshot) Reset() { *m = Snapshot{} } func (m *Snapshot) String() string { return proto.CompactTextString(m) } func (*Snapshot) ProtoMessage() {} func (*Snapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_9f1eaa49c51fa1ac, []int{46} + return fileDescriptor_9f1eaa49c51fa1ac, []int{45} } func (m *Snapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3282,7 +3231,6 @@ func init() { proto.RegisterType((*Validator)(nil), "tendermint.abci.types.Validator") proto.RegisterType((*ValidatorUpdate)(nil), "tendermint.abci.types.ValidatorUpdate") proto.RegisterType((*VoteInfo)(nil), "tendermint.abci.types.VoteInfo") - proto.RegisterType((*PubKey)(nil), "tendermint.abci.types.PubKey") proto.RegisterType((*Evidence)(nil), "tendermint.abci.types.Evidence") proto.RegisterType((*Snapshot)(nil), "tendermint.abci.types.Snapshot") } @@ -3290,176 +3238,177 @@ func init() { func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptor_9f1eaa49c51fa1ac) } var fileDescriptor_9f1eaa49c51fa1ac = []byte{ - // 2699 bytes of a gzipped FileDescriptorProto + // 2706 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x6f, 0x1b, 0xc9, - 0xf1, 0xe7, 0x90, 0x14, 0x1f, 0x45, 0x91, 0xa2, 0xda, 0x5e, 0x2f, 0x97, 0xff, 0x5d, 0xc9, 0x18, - 0xaf, 0x1f, 0xfb, 0xf8, 0x4b, 0xbb, 0x5a, 0x20, 0xb0, 0x63, 0x27, 0x81, 0x28, 0xcb, 0xa1, 0xe2, - 0x87, 0xe4, 0x91, 0xe4, 0x78, 0x13, 0x60, 0x27, 0xcd, 0x99, 0x16, 0x39, 0x6b, 0x72, 0x66, 0x76, - 0xa6, 0x29, 0x8b, 0x41, 0x0e, 0x41, 0x10, 0x20, 0xc8, 0xcd, 0xb9, 0xe4, 0x96, 0xef, 0x90, 0x43, - 0x80, 0xcd, 0x17, 0x08, 0xb0, 0xc7, 0x3d, 0x05, 0x39, 0x6d, 0x02, 0x3b, 0xa7, 0xe4, 0x4b, 0x04, - 0xfd, 0x98, 0x17, 0xc5, 0xc7, 0x70, 0xe3, 0x5b, 0x2e, 0x44, 0x57, 0x4f, 0x55, 0x75, 0x77, 0x75, - 0x77, 0xd5, 0xaf, 0xaa, 0x09, 0x97, 0x70, 0xc7, 0xb0, 0x36, 0xe9, 0xc8, 0x25, 0xbe, 0xf8, 0xdd, - 0x70, 0x3d, 0x87, 0x3a, 0xe8, 0x0d, 0x4a, 0x6c, 0x93, 0x78, 0x03, 0xcb, 0xa6, 0x1b, 0x8c, 0x65, - 0x83, 0x7f, 0x6c, 0xae, 0xf3, 0xaf, 0x9b, 0x86, 0x37, 0x72, 0xa9, 0xb3, 0x39, 0x20, 0xde, 0xb3, - 0x3e, 0x89, 0xcb, 0x35, 0xdf, 0x14, 0x0c, 0xe7, 0x14, 0x36, 0x1b, 0xf1, 0x0f, 0x2e, 0xf6, 0xf0, - 0x20, 0xf8, 0xb2, 0xde, 0x75, 0x9c, 0x6e, 0x9f, 0x6c, 0x72, 0xaa, 0x33, 0x3c, 0xd9, 0xa4, 0xd6, - 0x80, 0xf8, 0x14, 0x0f, 0x5c, 0xc9, 0x70, 0x8d, 0xf6, 0x2c, 0xcf, 0xd4, 0x5d, 0xec, 0xd1, 0x91, - 0xe0, 0xda, 0xec, 0x3a, 0x5d, 0x27, 0x6a, 0x09, 0x3e, 0xf5, 0xdf, 0x25, 0x28, 0x6a, 0xe4, 0x8b, - 0x21, 0xf1, 0x29, 0xba, 0x09, 0x79, 0x62, 0xf4, 0x9c, 0x46, 0xf6, 0xb2, 0x72, 0xa3, 0xb2, 0xa5, - 0x6e, 0x4c, 0x5c, 0xce, 0x86, 0xe4, 0xde, 0x35, 0x7a, 0x4e, 0x3b, 0xa3, 0x71, 0x09, 0x74, 0x1b, - 0x96, 0x4e, 0xfa, 0x43, 0xbf, 0xd7, 0xc8, 0x71, 0xd1, 0x2b, 0xb3, 0x45, 0xef, 0x31, 0xd6, 0x76, - 0x46, 0x13, 0x32, 0x6c, 0x58, 0xcb, 0x3e, 0x71, 0x1a, 0xf9, 0x34, 0xc3, 0xee, 0xd9, 0x27, 0x7c, - 0x58, 0x26, 0x81, 0xda, 0x00, 0x3e, 0xa1, 0xba, 0xe3, 0x52, 0xcb, 0xb1, 0x1b, 0x4b, 0x5c, 0xfe, - 0xfa, 0x6c, 0xf9, 0x43, 0x42, 0xf7, 0x39, 0x7b, 0x3b, 0xa3, 0x95, 0xfd, 0x80, 0x60, 0x9a, 0x2c, - 0xdb, 0xa2, 0xba, 0xd1, 0xc3, 0x96, 0xdd, 0x28, 0xa4, 0xd1, 0xb4, 0x67, 0x5b, 0x74, 0x87, 0xb1, - 0x33, 0x4d, 0x56, 0x40, 0x30, 0x53, 0x7c, 0x31, 0x24, 0xde, 0xa8, 0x51, 0x4c, 0x63, 0x8a, 0xc7, - 0x8c, 0x95, 0x99, 0x82, 0xcb, 0xa0, 0xfb, 0x50, 0xe9, 0x90, 0xae, 0x65, 0xeb, 0x9d, 0xbe, 0x63, - 0x3c, 0x6b, 0x94, 0xb8, 0x8a, 0x1b, 0xb3, 0x55, 0xb4, 0x98, 0x40, 0x8b, 0xf1, 0xb7, 0x33, 0x1a, - 0x74, 0x42, 0x0a, 0xb5, 0xa0, 0x64, 0xf4, 0x88, 0xf1, 0x4c, 0xa7, 0x67, 0x8d, 0x32, 0xd7, 0x74, - 0x75, 0xb6, 0xa6, 0x1d, 0xc6, 0x7d, 0x74, 0xd6, 0xce, 0x68, 0x45, 0x43, 0x34, 0x99, 0x5d, 0x4c, - 0xd2, 0xb7, 0x4e, 0x89, 0xc7, 0xb4, 0x5c, 0x48, 0x63, 0x97, 0xbb, 0x82, 0x9f, 0xeb, 0x29, 0x9b, - 0x01, 0x81, 0x76, 0xa1, 0x4c, 0x6c, 0x53, 0x2e, 0xac, 0xc2, 0x15, 0x5d, 0x9b, 0x73, 0xc2, 0x6c, - 0x33, 0x58, 0x56, 0x89, 0xc8, 0x36, 0xfa, 0x3e, 0x14, 0x0c, 0x67, 0x30, 0xb0, 0x68, 0x63, 0x99, - 0xeb, 0x78, 0x77, 0xce, 0x92, 0x38, 0x6f, 0x3b, 0xa3, 0x49, 0x29, 0x74, 0x04, 0xb5, 0xbe, 0xe5, - 0x53, 0xdd, 0xb7, 0xb1, 0xeb, 0xf7, 0x1c, 0xea, 0x37, 0xaa, 0x5c, 0xcf, 0x07, 0xb3, 0xf5, 0x3c, - 0xb0, 0x7c, 0x7a, 0x18, 0x88, 0xb4, 0x33, 0x5a, 0xb5, 0x1f, 0xef, 0x60, 0x5a, 0x9d, 0x93, 0x13, - 0xe2, 0x85, 0x6a, 0x1b, 0xb5, 0x34, 0x5a, 0xf7, 0x99, 0x4c, 0xa0, 0x85, 0x69, 0x75, 0xe2, 0x1d, - 0x08, 0xc3, 0x85, 0xbe, 0x83, 0xcd, 0x50, 0xa9, 0x6e, 0xf4, 0x86, 0xf6, 0xb3, 0xc6, 0x0a, 0x57, - 0xbd, 0x39, 0x67, 0xc2, 0x0e, 0x36, 0x03, 0x45, 0x3b, 0x4c, 0xac, 0x9d, 0xd1, 0x56, 0xfb, 0xe3, - 0x9d, 0xc8, 0x84, 0x8b, 0xd8, 0x75, 0xfb, 0xa3, 0xf1, 0x31, 0xea, 0x7c, 0x8c, 0x8f, 0x66, 0x8f, - 0xb1, 0xcd, 0x24, 0xc7, 0x07, 0x41, 0xf8, 0x5c, 0x6f, 0xab, 0x08, 0x4b, 0xa7, 0xb8, 0x3f, 0x24, - 0xea, 0x75, 0xa8, 0xc4, 0xdc, 0x07, 0x6a, 0x40, 0x71, 0x40, 0x7c, 0x1f, 0x77, 0x49, 0x43, 0xb9, - 0xac, 0xdc, 0x28, 0x6b, 0x01, 0xa9, 0xd6, 0x60, 0x39, 0xee, 0x2c, 0xd4, 0x41, 0x28, 0xc8, 0x1c, - 0x00, 0x13, 0x3c, 0x25, 0x9e, 0xcf, 0x6e, 0xbd, 0x14, 0x94, 0x24, 0xba, 0x02, 0x55, 0x7e, 0xc4, - 0xf4, 0xe0, 0x3b, 0x73, 0x66, 0x79, 0x6d, 0x99, 0x77, 0x3e, 0x91, 0x4c, 0xeb, 0x50, 0x71, 0xb7, - 0xdc, 0x90, 0x25, 0xc7, 0x59, 0xc0, 0xdd, 0x72, 0x25, 0x83, 0xfa, 0x5d, 0xa8, 0x8f, 0xfb, 0x0b, - 0x54, 0x87, 0xdc, 0x33, 0x32, 0x92, 0xe3, 0xb1, 0x26, 0xba, 0x28, 0x97, 0xc5, 0xc7, 0x28, 0x6b, - 0x72, 0x8d, 0x7f, 0xcc, 0x86, 0xc2, 0xa1, 0x8b, 0x60, 0x3e, 0x8e, 0x79, 0x68, 0x2e, 0x5d, 0xd9, - 0x6a, 0x6e, 0x08, 0xf7, 0xbd, 0x11, 0xb8, 0xef, 0x8d, 0xa3, 0xc0, 0x7d, 0xb7, 0x4a, 0x5f, 0x7d, - 0xb3, 0x9e, 0x79, 0xf1, 0xf7, 0x75, 0x45, 0xe3, 0x12, 0xe8, 0x2d, 0x76, 0x8b, 0xb1, 0x65, 0xeb, - 0x96, 0x29, 0xc7, 0x29, 0x72, 0x7a, 0xcf, 0x44, 0x8f, 0xa1, 0x6e, 0x38, 0xb6, 0x4f, 0x6c, 0x7f, - 0xe8, 0xeb, 0x22, 0x3c, 0x48, 0x07, 0x3c, 0xed, 0x66, 0xed, 0x04, 0xec, 0x07, 0x9c, 0x5b, 0x5b, - 0x31, 0x92, 0x1d, 0xe8, 0x01, 0xc0, 0x29, 0xee, 0x5b, 0x26, 0xa6, 0x8e, 0xe7, 0x37, 0xf2, 0x97, - 0x73, 0x33, 0x94, 0x3d, 0x09, 0x18, 0x8f, 0x5d, 0x13, 0x53, 0xd2, 0xca, 0xb3, 0x99, 0x6b, 0x31, - 0x79, 0x74, 0x0d, 0x56, 0xb0, 0xeb, 0xea, 0x3e, 0xc5, 0x94, 0xe8, 0x9d, 0x11, 0x25, 0x3e, 0x77, - 0xd2, 0xcb, 0x5a, 0x15, 0xbb, 0xee, 0x21, 0xeb, 0x6d, 0xb1, 0x4e, 0xd5, 0x0c, 0x77, 0x9b, 0xfb, - 0x43, 0x84, 0x20, 0x6f, 0x62, 0x8a, 0xb9, 0xb5, 0x96, 0x35, 0xde, 0x66, 0x7d, 0x2e, 0xa6, 0x3d, - 0x69, 0x03, 0xde, 0x46, 0x97, 0xa0, 0xd0, 0x23, 0x56, 0xb7, 0x47, 0xf9, 0xb2, 0x73, 0x9a, 0xa4, - 0xd8, 0xc6, 0xb8, 0x9e, 0x73, 0x4a, 0x78, 0x48, 0x29, 0x69, 0x82, 0x50, 0x7f, 0x9f, 0x85, 0xd5, - 0x73, 0x3e, 0x93, 0xe9, 0xed, 0x61, 0xbf, 0x17, 0x8c, 0xc5, 0xda, 0xe8, 0x0e, 0xd3, 0x8b, 0x4d, - 0xe2, 0xc9, 0x50, 0xb8, 0x16, 0xb7, 0x00, 0xdf, 0x33, 0x69, 0x82, 0x36, 0xe7, 0x92, 0x2b, 0x97, - 0x32, 0xe8, 0x18, 0xea, 0x7d, 0xec, 0x53, 0x5d, 0x78, 0x1c, 0x9d, 0xc7, 0xb6, 0xdc, 0x4c, 0xff, - 0xfb, 0x00, 0x07, 0x9e, 0x8a, 0x9d, 0x6e, 0xa9, 0xae, 0xd6, 0x4f, 0xf4, 0xa2, 0xa7, 0x70, 0xb1, - 0x33, 0xfa, 0x39, 0xb6, 0xa9, 0x65, 0x13, 0xfd, 0xdc, 0x26, 0xad, 0x4f, 0x51, 0xbd, 0x7b, 0x6a, - 0x99, 0xc4, 0x36, 0x82, 0xdd, 0xb9, 0x10, 0xaa, 0x08, 0x77, 0xcf, 0x57, 0x9f, 0x42, 0x2d, 0x19, - 0x01, 0x50, 0x0d, 0xb2, 0xf4, 0x4c, 0x9a, 0x24, 0x4b, 0xcf, 0xd0, 0x77, 0x20, 0xcf, 0xd4, 0x71, - 0x73, 0xd4, 0xa6, 0x86, 0x68, 0x29, 0x7d, 0x34, 0x72, 0x89, 0xc6, 0xf9, 0x55, 0x35, 0xbc, 0x0a, - 0x61, 0x54, 0x18, 0xd7, 0xad, 0xbe, 0x07, 0x2b, 0x63, 0x0e, 0x3f, 0xb6, 0xaf, 0x4a, 0x7c, 0x5f, - 0xd5, 0x15, 0xa8, 0x26, 0xfc, 0xba, 0x7a, 0x09, 0x2e, 0x4e, 0x72, 0xd0, 0xaa, 0x1d, 0xf6, 0x27, - 0x5c, 0x2c, 0xba, 0x0d, 0xa5, 0xd0, 0x43, 0x8b, 0xab, 0x38, 0xcd, 0x6e, 0x81, 0x88, 0x16, 0x0a, - 0xb0, 0x9b, 0xc8, 0x4e, 0x33, 0x3f, 0x2d, 0x59, 0x3e, 0xfd, 0x22, 0x76, 0xdd, 0x36, 0xf6, 0x7b, - 0xea, 0xcf, 0xa0, 0x31, 0xcd, 0xef, 0x8e, 0x2d, 0x26, 0x1f, 0x1e, 0xd2, 0x4b, 0x50, 0x38, 0x71, - 0xbc, 0x01, 0xa6, 0x5c, 0x59, 0x55, 0x93, 0x14, 0x3b, 0xbc, 0xc2, 0x07, 0xe7, 0x78, 0xb7, 0x20, - 0x54, 0x1d, 0xde, 0x9a, 0xea, 0x75, 0x99, 0x88, 0x65, 0x9b, 0x44, 0x58, 0xb5, 0xaa, 0x09, 0x22, - 0x52, 0x24, 0x26, 0x2b, 0x08, 0x36, 0xac, 0xcf, 0x57, 0xcc, 0xf5, 0x97, 0x35, 0x49, 0xa9, 0x7f, - 0x29, 0x43, 0x49, 0x23, 0xbe, 0xcb, 0x1c, 0x02, 0x6a, 0x43, 0x99, 0x9c, 0x19, 0x44, 0xe0, 0x2a, - 0x65, 0x0e, 0x0a, 0x11, 0x32, 0xbb, 0x01, 0x3f, 0x0b, 0xfb, 0xa1, 0x30, 0xba, 0x95, 0xc0, 0x94, - 0x57, 0xe6, 0x29, 0x89, 0x83, 0xca, 0x3b, 0x49, 0x50, 0xf9, 0xee, 0x1c, 0xd9, 0x31, 0x54, 0x79, - 0x2b, 0x81, 0x2a, 0xe7, 0x0d, 0x9c, 0x80, 0x95, 0x7b, 0x13, 0x60, 0xe5, 0xbc, 0xe5, 0x4f, 0xc1, - 0x95, 0x7b, 0x13, 0x70, 0xe5, 0x8d, 0xb9, 0x73, 0x99, 0x08, 0x2c, 0xef, 0x24, 0x81, 0xe5, 0x3c, - 0x73, 0x8c, 0x21, 0xcb, 0x07, 0x93, 0x90, 0xe5, 0x7b, 0x73, 0x74, 0x4c, 0x85, 0x96, 0x3b, 0xe7, - 0xa0, 0xe5, 0xb5, 0x39, 0xaa, 0x26, 0x60, 0xcb, 0xbd, 0x04, 0xb6, 0x84, 0x54, 0xb6, 0x99, 0x02, - 0x2e, 0xef, 0x9d, 0x07, 0x97, 0xd7, 0xe7, 0x1d, 0xb5, 0x49, 0xe8, 0xf2, 0x07, 0x63, 0xe8, 0xf2, - 0xea, 0xbc, 0x55, 0x8d, 0xc3, 0xcb, 0xe3, 0x29, 0xf0, 0xf2, 0xc3, 0x39, 0x8a, 0xe6, 0xe0, 0xcb, - 0xe3, 0x29, 0xf8, 0x72, 0x9e, 0xda, 0x39, 0x00, 0xb3, 0x33, 0x0b, 0x60, 0x7e, 0x34, 0x6f, 0xca, - 0xe9, 0x10, 0x26, 0x99, 0x89, 0x30, 0x3f, 0x9e, 0x33, 0xc8, 0xe2, 0x10, 0xf3, 0x3d, 0x16, 0xe4, - 0xc7, 0x5c, 0x12, 0x73, 0x85, 0xc4, 0xf3, 0x1c, 0x4f, 0xa2, 0x37, 0x41, 0xa8, 0x37, 0x18, 0xec, - 0x88, 0x1c, 0xcf, 0x0c, 0x38, 0xca, 0x03, 0x4f, 0xcc, 0xcd, 0xa8, 0x7f, 0x56, 0x22, 0x59, 0x1e, - 0x9d, 0xe3, 0x90, 0xa5, 0x2c, 0x21, 0x4b, 0x0c, 0xa5, 0x66, 0x93, 0x28, 0x75, 0x1d, 0x2a, 0x2c, - 0x94, 0x8c, 0x01, 0x50, 0xec, 0x06, 0x00, 0x14, 0xbd, 0x0f, 0xab, 0x1c, 0x43, 0x08, 0x2c, 0x2b, - 0xe3, 0x47, 0x9e, 0x07, 0xc3, 0x15, 0xf6, 0x41, 0x1c, 0x5d, 0x11, 0x48, 0xfe, 0x1f, 0x2e, 0xc4, - 0x78, 0xc3, 0x10, 0x25, 0x90, 0x56, 0x3d, 0xe4, 0xde, 0x96, 0xb1, 0xea, 0x61, 0x64, 0xa0, 0x08, - 0xdc, 0x22, 0xc8, 0x1b, 0x8e, 0x49, 0x64, 0x00, 0xe1, 0x6d, 0x06, 0x78, 0xfb, 0x4e, 0x57, 0x86, - 0x09, 0xd6, 0x64, 0x5c, 0xa1, 0x4f, 0x2d, 0x0b, 0x67, 0xa9, 0xfe, 0x49, 0x89, 0xf4, 0x45, 0x78, - 0x77, 0x12, 0x34, 0x55, 0x5e, 0x27, 0x34, 0xcd, 0xfe, 0x77, 0xd0, 0x54, 0xfd, 0x75, 0x36, 0xda, - 0xd2, 0x10, 0x74, 0x7e, 0x3b, 0x13, 0x44, 0xe1, 0x77, 0x89, 0x6f, 0x90, 0x0c, 0xbf, 0x32, 0x5f, - 0x28, 0xf0, 0x6d, 0x48, 0xe6, 0x0b, 0x45, 0x11, 0x90, 0x39, 0xc1, 0x12, 0x63, 0xd7, 0x73, 0x9c, - 0x13, 0xdd, 0x71, 0xfd, 0x49, 0x19, 0xbf, 0xc0, 0x9b, 0xa2, 0x7a, 0xb4, 0x21, 0xaa, 0x47, 0x1b, - 0x07, 0x4c, 0x60, 0xdf, 0xf5, 0xb5, 0x92, 0x2b, 0x5b, 0x31, 0x98, 0x51, 0x4e, 0x60, 0xe1, 0xb7, - 0xa1, 0xcc, 0x96, 0xe2, 0xbb, 0xd8, 0x20, 0xdc, 0xc9, 0x96, 0xb5, 0xa8, 0x43, 0x35, 0x01, 0x9d, - 0x77, 0xf6, 0xe8, 0x11, 0x14, 0xc8, 0x29, 0xb1, 0x29, 0xdb, 0x33, 0x66, 0xe6, 0xb7, 0xa7, 0x82, - 0x4b, 0x62, 0xd3, 0x56, 0x83, 0x19, 0xf7, 0x5f, 0xdf, 0xac, 0xd7, 0x85, 0xcc, 0x87, 0xce, 0xc0, - 0xa2, 0x64, 0xe0, 0xd2, 0x91, 0x26, 0xb5, 0xa8, 0xbf, 0xc9, 0x32, 0x8c, 0x97, 0x08, 0x04, 0x13, - 0xcd, 0x1d, 0x5c, 0xa2, 0x6c, 0x0c, 0xf7, 0xa7, 0xdb, 0x82, 0x77, 0x00, 0xba, 0xd8, 0xd7, 0x9f, - 0x63, 0x9b, 0x12, 0x53, 0xee, 0x43, 0xb9, 0x8b, 0xfd, 0x1f, 0xf3, 0x0e, 0x06, 0xdd, 0xd8, 0xe7, - 0xa1, 0x4f, 0x4c, 0xbe, 0x21, 0x39, 0xad, 0xd8, 0xc5, 0xfe, 0xb1, 0x4f, 0xcc, 0xd8, 0x5a, 0x8b, - 0xaf, 0x63, 0xad, 0x49, 0x7b, 0x97, 0xc6, 0xed, 0xfd, 0xdb, 0x6c, 0x74, 0x5b, 0x22, 0x48, 0xfc, - 0xbf, 0x69, 0x8b, 0x3f, 0xf0, 0x44, 0x39, 0x19, 0x8d, 0xd1, 0xa7, 0xb0, 0x1a, 0xde, 0x52, 0x7d, - 0xc8, 0x6f, 0x6f, 0x70, 0x0a, 0x17, 0xbb, 0xec, 0xf5, 0xd3, 0x64, 0xb7, 0x8f, 0x3e, 0x83, 0x37, - 0xc7, 0x7c, 0x52, 0x38, 0x40, 0x76, 0x21, 0xd7, 0xf4, 0x46, 0xd2, 0x35, 0x05, 0xfa, 0x23, 0xeb, - 0xe5, 0x5e, 0xcb, 0xad, 0xd9, 0x63, 0x69, 0x59, 0x1c, 0x67, 0x4c, 0x3c, 0x13, 0x57, 0xa0, 0xea, - 0x11, 0x8a, 0x2d, 0x5b, 0x4f, 0xa4, 0xc2, 0xcb, 0xa2, 0x53, 0x84, 0x08, 0xf5, 0x09, 0xbc, 0x31, - 0x11, 0x69, 0xa0, 0xef, 0x41, 0x39, 0x82, 0x2a, 0xca, 0xcc, 0x4c, 0x32, 0xcc, 0x88, 0x22, 0x09, - 0xf5, 0x4b, 0x25, 0x52, 0x9c, 0xcc, 0xb4, 0xee, 0x43, 0xc1, 0x23, 0xfe, 0xb0, 0x2f, 0xb2, 0x9e, - 0xda, 0xd6, 0x27, 0x8b, 0x20, 0x15, 0xd6, 0x3b, 0xec, 0x53, 0x4d, 0xaa, 0x50, 0x1f, 0x43, 0x41, - 0xf4, 0x20, 0x80, 0xc2, 0xf6, 0xce, 0xce, 0xee, 0xc1, 0x51, 0x3d, 0x83, 0xca, 0xb0, 0xb4, 0xdd, - 0xda, 0xd7, 0x8e, 0xea, 0x0a, 0xeb, 0xd6, 0x76, 0x7f, 0xb4, 0xbb, 0x73, 0x54, 0xcf, 0xa2, 0x55, - 0xa8, 0x8a, 0xb6, 0x7e, 0x6f, 0x5f, 0x7b, 0xb8, 0x7d, 0x54, 0xcf, 0xc5, 0xba, 0x0e, 0x77, 0x1f, - 0xdd, 0xdd, 0xd5, 0xea, 0x79, 0xf5, 0x63, 0x96, 0x4f, 0x4d, 0x01, 0x32, 0x51, 0xe6, 0xa4, 0xc4, - 0x32, 0x27, 0xf5, 0x77, 0x59, 0x68, 0x4e, 0xc7, 0x25, 0xe8, 0x60, 0x6c, 0xc5, 0x37, 0x17, 0x86, - 0x36, 0x63, 0xcb, 0x46, 0x57, 0xa1, 0xe6, 0x91, 0x13, 0x42, 0x8d, 0x9e, 0xc0, 0x4c, 0x22, 0xea, - 0x55, 0xb5, 0xaa, 0xec, 0xe5, 0x42, 0xbe, 0x60, 0xfb, 0x9c, 0x18, 0x54, 0x17, 0xa9, 0x9c, 0x38, - 0x7f, 0x65, 0xc6, 0xc6, 0x7a, 0x0f, 0x45, 0xa7, 0x7a, 0x38, 0xcf, 0x88, 0x65, 0x58, 0xd2, 0x76, - 0x8f, 0xb4, 0x4f, 0xeb, 0x59, 0x84, 0xa0, 0xc6, 0x9b, 0xfa, 0xe1, 0xa3, 0xed, 0x83, 0xc3, 0xf6, - 0x3e, 0x33, 0xe2, 0x05, 0x58, 0x09, 0x8c, 0x18, 0x74, 0xe6, 0xd5, 0xbf, 0x2a, 0xb0, 0x32, 0x76, - 0x3d, 0xd0, 0x4d, 0x58, 0x12, 0x40, 0x5c, 0x99, 0x59, 0xd0, 0xe7, 0xf7, 0x5d, 0xde, 0x28, 0x21, - 0x80, 0x5a, 0x50, 0x22, 0xb2, 0x5e, 0x31, 0xe9, 0x4a, 0xc6, 0x2b, 0x2f, 0x41, 0x5d, 0x43, 0x2a, - 0x08, 0xe5, 0x58, 0x38, 0x0d, 0x6f, 0xbe, 0xcc, 0x1c, 0xaf, 0x4f, 0x53, 0x12, 0x7a, 0x0e, 0xa9, - 0x25, 0x92, 0x54, 0x77, 0xa0, 0x12, 0x9b, 0x20, 0xfa, 0x3f, 0x28, 0x0f, 0xf0, 0x99, 0xac, 0x61, - 0x89, 0xa2, 0x44, 0x69, 0x80, 0xcf, 0x78, 0xf9, 0x0a, 0xbd, 0x09, 0x45, 0xf6, 0xb1, 0x8b, 0x85, - 0x23, 0xc9, 0x69, 0x85, 0x01, 0x3e, 0xfb, 0x21, 0xf6, 0x55, 0x03, 0x6a, 0xc9, 0xd2, 0x0e, 0x3b, - 0x59, 0x9e, 0x33, 0xb4, 0x4d, 0xae, 0x63, 0x49, 0x13, 0x04, 0xba, 0x0d, 0x4b, 0xa7, 0x8e, 0xf0, - 0x43, 0xb3, 0x6e, 0xe0, 0x13, 0x87, 0x92, 0x58, 0x81, 0x48, 0xc8, 0xa8, 0x8f, 0xa0, 0xc6, 0x3d, - 0xca, 0x36, 0xa5, 0x9e, 0xd5, 0x19, 0x52, 0x12, 0xaf, 0x54, 0x2e, 0x4f, 0xa8, 0x54, 0x86, 0xc8, - 0x23, 0xc4, 0x2d, 0x39, 0x51, 0x26, 0xe3, 0x84, 0xfa, 0x4b, 0x05, 0x96, 0xb8, 0x42, 0xe6, 0x6e, - 0x78, 0xd5, 0x47, 0x62, 0x5a, 0xd6, 0x46, 0x06, 0x00, 0x0e, 0x06, 0x0a, 0xe6, 0x7b, 0x75, 0x96, - 0xa3, 0x0b, 0xa7, 0xd5, 0x7a, 0x5b, 0x7a, 0xbc, 0x8b, 0x91, 0x82, 0x98, 0xd7, 0x8b, 0xa9, 0x55, - 0x5f, 0x28, 0x50, 0x3a, 0x3a, 0x93, 0xa7, 0x75, 0x4a, 0x31, 0x88, 0xcd, 0x7e, 0x8f, 0xcf, 0x5e, - 0x94, 0x4f, 0x04, 0x21, 0xab, 0x4b, 0xb9, 0xb0, 0x72, 0x75, 0x2f, 0xbc, 0x95, 0xf9, 0xc5, 0x12, - 0xcc, 0xa0, 0xa8, 0x27, 0x5d, 0x50, 0x1f, 0x8a, 0xfc, 0x3c, 0xec, 0xdd, 0x9d, 0x58, 0x31, 0x7c, - 0x08, 0xcb, 0x2e, 0xf6, 0xa8, 0xaf, 0x27, 0xea, 0x86, 0xd3, 0x72, 0xf4, 0x03, 0xec, 0xd1, 0x43, - 0x42, 0x13, 0xd5, 0xc3, 0x0a, 0x97, 0x17, 0x5d, 0xea, 0x2d, 0xa8, 0x26, 0x78, 0xd8, 0x62, 0xa9, - 0x43, 0x71, 0x3f, 0x38, 0x37, 0x9c, 0x08, 0x67, 0x92, 0x8d, 0x66, 0xa2, 0xde, 0x86, 0x72, 0x78, - 0xac, 0x59, 0x06, 0x82, 0x4d, 0xd3, 0x23, 0xbe, 0x2f, 0x67, 0x1b, 0x90, 0xbc, 0x44, 0xea, 0x3c, - 0x97, 0x55, 0xa0, 0x9c, 0x26, 0x08, 0x95, 0xc0, 0xca, 0x58, 0x34, 0x45, 0x77, 0xa0, 0xe8, 0x0e, - 0x3b, 0x7a, 0x70, 0xa0, 0x2a, 0x5b, 0xef, 0x4c, 0x5b, 0xd4, 0xb0, 0x73, 0x9f, 0x8c, 0x02, 0xb3, - 0xb9, 0x9c, 0x8a, 0x86, 0xc9, 0xc6, 0x87, 0xf9, 0x05, 0x94, 0x82, 0xb3, 0x8c, 0xee, 0xc6, 0xef, - 0xab, 0x18, 0xe1, 0xf2, 0xbc, 0x40, 0x2f, 0x07, 0x89, 0x04, 0x59, 0xbe, 0xe4, 0x5b, 0x5d, 0x9b, - 0x98, 0x7a, 0x94, 0x0a, 0xf1, 0x31, 0x4b, 0xda, 0x8a, 0xf8, 0xf0, 0x20, 0xc8, 0x83, 0xd4, 0x8f, - 0xa0, 0x20, 0xe6, 0x3a, 0xf1, 0x80, 0x4f, 0x88, 0xb1, 0xea, 0x3f, 0x15, 0x28, 0x05, 0x0e, 0x67, - 0xa2, 0x50, 0x62, 0x11, 0xd9, 0x6f, 0xbb, 0x88, 0x69, 0xe5, 0xec, 0xe0, 0xf1, 0x20, 0xbf, 0xf0, - 0xe3, 0xc1, 0x87, 0x80, 0xf8, 0x49, 0xd1, 0x4f, 0x1d, 0x6a, 0xd9, 0x5d, 0x5d, 0xec, 0x85, 0x80, - 0x84, 0x75, 0xfe, 0xe5, 0x09, 0xff, 0x70, 0xc0, 0xb7, 0xe5, 0x57, 0x0a, 0x94, 0xc2, 0x00, 0xbe, - 0x68, 0xd9, 0xf2, 0x12, 0x14, 0x64, 0x90, 0x12, 0x75, 0x4b, 0x49, 0x85, 0x67, 0x34, 0x1f, 0xbb, - 0x2d, 0x4d, 0x28, 0x0d, 0x08, 0xc5, 0xdc, 0xce, 0x22, 0x4d, 0x0d, 0xe9, 0xf7, 0xaf, 0x40, 0x25, - 0x56, 0x47, 0x46, 0x45, 0xc8, 0x3d, 0x22, 0xcf, 0xeb, 0x19, 0x54, 0x81, 0xa2, 0x46, 0x78, 0xe9, - 0xa8, 0xae, 0x6c, 0x7d, 0x59, 0x81, 0x95, 0xed, 0xd6, 0xce, 0x1e, 0x8b, 0xa1, 0x96, 0x81, 0x79, - 0x0a, 0xbb, 0x0f, 0x79, 0x9e, 0xc5, 0xa7, 0x78, 0xb7, 0x6e, 0xa6, 0xa9, 0x43, 0x22, 0x0d, 0x96, - 0x78, 0xb2, 0x8f, 0xd2, 0x3c, 0x67, 0x37, 0x53, 0x95, 0x27, 0xd9, 0x24, 0xf9, 0xa9, 0x4f, 0xf1, - 0xca, 0xdd, 0x4c, 0x53, 0xb3, 0x44, 0x9f, 0x41, 0x39, 0xca, 0xe2, 0xd3, 0xbe, 0x7d, 0x37, 0x53, - 0x57, 0x33, 0x99, 0xfe, 0x28, 0x4f, 0x49, 0xfb, 0xf2, 0xdb, 0x4c, 0xed, 0x65, 0xd1, 0x53, 0x28, - 0x06, 0x19, 0x61, 0xba, 0xd7, 0xe9, 0x66, 0xca, 0x4a, 0x23, 0xdb, 0x3e, 0x91, 0xd8, 0xa7, 0x79, - 0x82, 0x6f, 0xa6, 0x2a, 0xa7, 0xa2, 0x63, 0x28, 0x48, 0x28, 0x9e, 0xea, 0xdd, 0xb9, 0x99, 0xae, - 0x7e, 0xc8, 0x8c, 0x1c, 0x95, 0x4e, 0xd2, 0xfe, 0xed, 0xa0, 0x99, 0xba, 0x8e, 0x8c, 0x30, 0x40, - 0x2c, 0xbb, 0x4f, 0xfd, 0x7f, 0x82, 0x66, 0xfa, 0xfa, 0x30, 0xfa, 0x29, 0x94, 0xc2, 0x1c, 0x2e, - 0xe5, 0xbb, 0x7e, 0x33, 0x6d, 0x89, 0x16, 0x7d, 0x0e, 0xd5, 0x64, 0xda, 0xb2, 0xc8, 0x6b, 0x7d, - 0x73, 0xa1, 0xda, 0x2b, 0x1b, 0x2b, 0x99, 0xc9, 0x2c, 0xf2, 0x86, 0xdf, 0x5c, 0xa8, 0x20, 0x8b, - 0x4e, 0x61, 0xf5, 0x7c, 0xf2, 0xb1, 0xe8, 0xc3, 0x7e, 0x73, 0xe1, 0x42, 0x2d, 0x1a, 0x01, 0x9a, - 0x90, 0xc0, 0x2c, 0xfc, 0xda, 0xdf, 0x5c, 0xbc, 0x7a, 0xdb, 0xda, 0xfd, 0xea, 0xe5, 0x9a, 0xf2, - 0xf5, 0xcb, 0x35, 0xe5, 0x1f, 0x2f, 0xd7, 0x94, 0x17, 0xaf, 0xd6, 0x32, 0x5f, 0xbf, 0x5a, 0xcb, - 0xfc, 0xed, 0xd5, 0x5a, 0xe6, 0x27, 0x1f, 0x74, 0x2d, 0xda, 0x1b, 0x76, 0x36, 0x0c, 0x67, 0xb0, - 0x19, 0xa9, 0x8d, 0x37, 0xa3, 0xbf, 0x5d, 0x75, 0x0a, 0x3c, 0xf8, 0x7d, 0xf2, 0x9f, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x33, 0x72, 0x48, 0xac, 0x8b, 0x25, 0x00, 0x00, + 0xf1, 0xe7, 0x4b, 0x7c, 0x14, 0x45, 0x8a, 0x6a, 0x7b, 0xbd, 0x5c, 0xfe, 0x77, 0x25, 0x63, 0xbc, + 0x7e, 0xed, 0xfa, 0x4f, 0xed, 0x6a, 0x81, 0xc0, 0x8e, 0x9d, 0x04, 0xa2, 0x2c, 0x87, 0x8a, 0x1f, + 0x92, 0x47, 0x92, 0xe3, 0x4d, 0x80, 0x9d, 0x34, 0x67, 0x5a, 0xe4, 0xac, 0xc8, 0x99, 0xd9, 0x99, + 0xa6, 0x2c, 0x06, 0x39, 0x04, 0x41, 0x80, 0x20, 0x37, 0xe7, 0x92, 0x5b, 0xbe, 0x43, 0x0e, 0x01, + 0x36, 0x5f, 0x20, 0xc0, 0x1e, 0xf7, 0x14, 0xe4, 0xb4, 0x09, 0xec, 0x9c, 0x92, 0x2f, 0x11, 0xf4, + 0x63, 0x5e, 0x14, 0x1f, 0xc3, 0x8d, 0x6f, 0xb9, 0x10, 0xdd, 0x35, 0x55, 0xd5, 0xdd, 0xd5, 0xdd, + 0x55, 0xbf, 0xaa, 0x26, 0x5c, 0xc2, 0x1d, 0xdd, 0xdc, 0xa0, 0x23, 0x87, 0x78, 0xe2, 0xb7, 0xe9, + 0xb8, 0x36, 0xb5, 0xd1, 0x5b, 0x94, 0x58, 0x06, 0x71, 0x07, 0xa6, 0x45, 0x9b, 0x8c, 0xa5, 0xc9, + 0x3f, 0x36, 0xd6, 0xf9, 0xd7, 0x0d, 0xdd, 0x1d, 0x39, 0xd4, 0xde, 0x18, 0x10, 0xf7, 0xa4, 0x4f, + 0xa2, 0x72, 0x8d, 0xb7, 0x05, 0xc3, 0x39, 0x85, 0x8d, 0xf7, 0x62, 0x92, 0x27, 0x64, 0x14, 0xff, + 0x5c, 0x8f, 0xca, 0x39, 0xd8, 0xc5, 0x03, 0xff, 0xcb, 0x7a, 0xd7, 0xb6, 0xbb, 0x7d, 0xb2, 0xc1, + 0x7b, 0x9d, 0xe1, 0xf1, 0x06, 0x35, 0x07, 0xc4, 0xa3, 0x78, 0xe0, 0x48, 0x86, 0x6b, 0xb4, 0x67, + 0xba, 0x86, 0xe6, 0x60, 0x97, 0x8e, 0x04, 0xd7, 0x46, 0xd7, 0xee, 0xda, 0x61, 0x4b, 0xf0, 0x29, + 0xff, 0x2e, 0x42, 0x41, 0x25, 0x5f, 0x0c, 0x89, 0x47, 0xd1, 0x6d, 0xc8, 0x11, 0xbd, 0x67, 0xd7, + 0x33, 0x97, 0xd3, 0x37, 0xca, 0x9b, 0x4a, 0x73, 0xe2, 0x6a, 0x9b, 0x92, 0x7b, 0x47, 0xef, 0xd9, + 0xed, 0x94, 0xca, 0x25, 0xd0, 0x5d, 0x58, 0x3a, 0xee, 0x0f, 0xbd, 0x5e, 0x3d, 0xcb, 0x45, 0xaf, + 0xcc, 0x16, 0x7d, 0xc0, 0x58, 0xdb, 0x29, 0x55, 0xc8, 0xb0, 0x61, 0x4d, 0xeb, 0xd8, 0xae, 0xe7, + 0x92, 0x0c, 0xbb, 0x6b, 0x1d, 0xf3, 0x61, 0x99, 0x04, 0x6a, 0x03, 0x78, 0x84, 0x6a, 0xb6, 0x43, + 0x4d, 0xdb, 0xaa, 0x2f, 0x71, 0xf9, 0xeb, 0xb3, 0xe5, 0x0f, 0x08, 0xdd, 0xe3, 0xec, 0xed, 0x94, + 0x5a, 0xf2, 0xfc, 0x0e, 0xd3, 0x64, 0x5a, 0x26, 0xd5, 0xf4, 0x1e, 0x36, 0xad, 0x7a, 0x3e, 0x89, + 0xa6, 0x5d, 0xcb, 0xa4, 0xdb, 0x8c, 0x9d, 0x69, 0x32, 0xfd, 0x0e, 0x33, 0xc5, 0x17, 0x43, 0xe2, + 0x8e, 0xea, 0x85, 0x24, 0xa6, 0x78, 0xca, 0x58, 0x99, 0x29, 0xb8, 0x0c, 0x7a, 0x08, 0xe5, 0x0e, + 0xe9, 0x9a, 0x96, 0xd6, 0xe9, 0xdb, 0xfa, 0x49, 0xbd, 0xc8, 0x55, 0xdc, 0x98, 0xad, 0xa2, 0xc5, + 0x04, 0x5a, 0x8c, 0xbf, 0x9d, 0x52, 0xa1, 0x13, 0xf4, 0x50, 0x0b, 0x8a, 0x7a, 0x8f, 0xe8, 0x27, + 0x1a, 0x3d, 0xab, 0x97, 0xb8, 0xa6, 0xab, 0xb3, 0x35, 0x6d, 0x33, 0xee, 0xc3, 0xb3, 0x76, 0x4a, + 0x2d, 0xe8, 0xa2, 0xc9, 0xec, 0x62, 0x90, 0xbe, 0x79, 0x4a, 0x5c, 0xa6, 0xe5, 0x42, 0x12, 0xbb, + 0xdc, 0x17, 0xfc, 0x5c, 0x4f, 0xc9, 0xf0, 0x3b, 0x68, 0x07, 0x4a, 0xc4, 0x32, 0xe4, 0xc2, 0xca, + 0x5c, 0xd1, 0xb5, 0x39, 0x27, 0xcc, 0x32, 0xfc, 0x65, 0x15, 0x89, 0x6c, 0xa3, 0xef, 0x43, 0x5e, + 0xb7, 0x07, 0x03, 0x93, 0xd6, 0x97, 0xb9, 0x8e, 0xf7, 0xe7, 0x2c, 0x89, 0xf3, 0xb6, 0x53, 0xaa, + 0x94, 0x42, 0x87, 0x50, 0xed, 0x9b, 0x1e, 0xd5, 0x3c, 0x0b, 0x3b, 0x5e, 0xcf, 0xa6, 0x5e, 0xbd, + 0xc2, 0xf5, 0x7c, 0x38, 0x5b, 0xcf, 0x23, 0xd3, 0xa3, 0x07, 0xbe, 0x48, 0x3b, 0xa5, 0x56, 0xfa, + 0x51, 0x02, 0xd3, 0x6a, 0x1f, 0x1f, 0x13, 0x37, 0x50, 0x5b, 0xaf, 0x26, 0xd1, 0xba, 0xc7, 0x64, + 0x7c, 0x2d, 0x4c, 0xab, 0x1d, 0x25, 0x20, 0x0c, 0x17, 0xfa, 0x36, 0x36, 0x02, 0xa5, 0x9a, 0xde, + 0x1b, 0x5a, 0x27, 0xf5, 0x15, 0xae, 0x7a, 0x63, 0xce, 0x84, 0x6d, 0x6c, 0xf8, 0x8a, 0xb6, 0x99, + 0x58, 0x3b, 0xa5, 0xae, 0xf6, 0xc7, 0x89, 0xc8, 0x80, 0x8b, 0xd8, 0x71, 0xfa, 0xa3, 0xf1, 0x31, + 0x6a, 0x7c, 0x8c, 0x8f, 0x66, 0x8f, 0xb1, 0xc5, 0x24, 0xc7, 0x07, 0x41, 0xf8, 0x1c, 0xb5, 0x55, + 0x80, 0xa5, 0x53, 0xdc, 0x1f, 0x12, 0xe5, 0x3a, 0x94, 0x23, 0xee, 0x03, 0xd5, 0xa1, 0x30, 0x20, + 0x9e, 0x87, 0xbb, 0xa4, 0x9e, 0xbe, 0x9c, 0xbe, 0x51, 0x52, 0xfd, 0xae, 0x52, 0x85, 0xe5, 0xa8, + 0xb3, 0x50, 0x06, 0x81, 0x20, 0x73, 0x00, 0x4c, 0xf0, 0x94, 0xb8, 0x1e, 0xbb, 0xf5, 0x52, 0x50, + 0x76, 0xd1, 0x15, 0xa8, 0xf0, 0x23, 0xa6, 0xf9, 0xdf, 0x99, 0x33, 0xcb, 0xa9, 0xcb, 0x9c, 0xf8, + 0x4c, 0x32, 0xad, 0x43, 0xd9, 0xd9, 0x74, 0x02, 0x96, 0x2c, 0x67, 0x01, 0x67, 0xd3, 0x91, 0x0c, + 0xca, 0x77, 0xa1, 0x36, 0xee, 0x2f, 0x50, 0x0d, 0xb2, 0x27, 0x64, 0x24, 0xc7, 0x63, 0x4d, 0x74, + 0x51, 0x2e, 0x8b, 0x8f, 0x51, 0x52, 0xe5, 0x1a, 0xff, 0x98, 0x09, 0x84, 0x03, 0x17, 0xc1, 0x7c, + 0x1c, 0xf3, 0xd0, 0x5c, 0xba, 0xbc, 0xd9, 0x68, 0x0a, 0xf7, 0xdd, 0xf4, 0xdd, 0x77, 0xf3, 0xd0, + 0x77, 0xdf, 0xad, 0xe2, 0x57, 0xdf, 0xac, 0xa7, 0x5e, 0xfe, 0x7d, 0x3d, 0xad, 0x72, 0x09, 0xf4, + 0x0e, 0xbb, 0xc5, 0xd8, 0xb4, 0x34, 0xd3, 0x90, 0xe3, 0x14, 0x78, 0x7f, 0xd7, 0x40, 0x4f, 0xa1, + 0xa6, 0xdb, 0x96, 0x47, 0x2c, 0x6f, 0xe8, 0x69, 0x22, 0x3c, 0x48, 0x07, 0x3c, 0xed, 0x66, 0x6d, + 0xfb, 0xec, 0xfb, 0x9c, 0x5b, 0x5d, 0xd1, 0xe3, 0x04, 0xf4, 0x08, 0xe0, 0x14, 0xf7, 0x4d, 0x03, + 0x53, 0xdb, 0xf5, 0xea, 0xb9, 0xcb, 0xd9, 0x19, 0xca, 0x9e, 0xf9, 0x8c, 0x47, 0x8e, 0x81, 0x29, + 0x69, 0xe5, 0xd8, 0xcc, 0xd5, 0x88, 0x3c, 0xba, 0x06, 0x2b, 0xd8, 0x71, 0x34, 0x8f, 0x62, 0x4a, + 0xb4, 0xce, 0x88, 0x12, 0x8f, 0x3b, 0xe9, 0x65, 0xb5, 0x82, 0x1d, 0xe7, 0x80, 0x51, 0x5b, 0x8c, + 0xa8, 0x18, 0xc1, 0x6e, 0x73, 0x7f, 0x88, 0x10, 0xe4, 0x0c, 0x4c, 0x31, 0xb7, 0xd6, 0xb2, 0xca, + 0xdb, 0x8c, 0xe6, 0x60, 0xda, 0x93, 0x36, 0xe0, 0x6d, 0x74, 0x09, 0xf2, 0x3d, 0x62, 0x76, 0x7b, + 0x94, 0x2f, 0x3b, 0xab, 0xca, 0x1e, 0xdb, 0x18, 0xc7, 0xb5, 0x4f, 0x09, 0x0f, 0x29, 0x45, 0x55, + 0x74, 0x94, 0xdf, 0x67, 0x60, 0xf5, 0x9c, 0xcf, 0x64, 0x7a, 0x7b, 0xd8, 0xeb, 0xf9, 0x63, 0xb1, + 0x36, 0xba, 0xc7, 0xf4, 0x62, 0x83, 0xb8, 0x32, 0x14, 0xae, 0x45, 0x2d, 0xc0, 0xf7, 0x4c, 0x9a, + 0xa0, 0xcd, 0xb9, 0xe4, 0xca, 0xa5, 0x0c, 0x3a, 0x82, 0x5a, 0x1f, 0x7b, 0x54, 0x13, 0x1e, 0x47, + 0xe3, 0xb1, 0x2d, 0x3b, 0xd3, 0xff, 0x3e, 0xc2, 0xbe, 0xa7, 0x62, 0xa7, 0x5b, 0xaa, 0xab, 0xf6, + 0x63, 0x54, 0xf4, 0x1c, 0x2e, 0x76, 0x46, 0x3f, 0xc7, 0x16, 0x35, 0x2d, 0xa2, 0x9d, 0xdb, 0xa4, + 0xf5, 0x29, 0xaa, 0x77, 0x4e, 0x4d, 0x83, 0x58, 0xba, 0xbf, 0x3b, 0x17, 0x02, 0x15, 0xc1, 0xee, + 0x79, 0xca, 0x73, 0xa8, 0xc6, 0x23, 0x00, 0xaa, 0x42, 0x86, 0x9e, 0x49, 0x93, 0x64, 0xe8, 0x19, + 0xfa, 0x0e, 0xe4, 0x98, 0x3a, 0x6e, 0x8e, 0xea, 0xd4, 0x10, 0x2d, 0xa5, 0x0f, 0x47, 0x0e, 0x51, + 0x39, 0xbf, 0xa2, 0x04, 0x57, 0x21, 0x88, 0x0a, 0xe3, 0xba, 0x95, 0x9b, 0xb0, 0x32, 0xe6, 0xf0, + 0x23, 0xfb, 0x9a, 0x8e, 0xee, 0xab, 0xb2, 0x02, 0x95, 0x98, 0x5f, 0x57, 0x2e, 0xc1, 0xc5, 0x49, + 0x0e, 0x5a, 0xb1, 0x02, 0x7a, 0xcc, 0xc5, 0xa2, 0xbb, 0x50, 0x0c, 0x3c, 0xb4, 0xb8, 0x8a, 0xd3, + 0xec, 0xe6, 0x8b, 0xa8, 0x81, 0x00, 0xbb, 0x89, 0xec, 0x34, 0xf3, 0xd3, 0x92, 0xe1, 0xd3, 0x2f, + 0x60, 0xc7, 0x69, 0x63, 0xaf, 0xa7, 0xfc, 0x0c, 0xea, 0xd3, 0xfc, 0xee, 0xd8, 0x62, 0x72, 0xc1, + 0x21, 0xbd, 0x04, 0xf9, 0x63, 0xdb, 0x1d, 0x60, 0xca, 0x95, 0x55, 0x54, 0xd9, 0x63, 0x87, 0x57, + 0xf8, 0xe0, 0x2c, 0x27, 0x8b, 0x8e, 0xa2, 0xc1, 0x3b, 0x53, 0xbd, 0x2e, 0x13, 0x31, 0x2d, 0x83, + 0x08, 0xab, 0x56, 0x54, 0xd1, 0x09, 0x15, 0x89, 0xc9, 0x8a, 0x0e, 0x1b, 0xd6, 0xe3, 0x2b, 0xe6, + 0xfa, 0x4b, 0xaa, 0xec, 0x29, 0x7f, 0x29, 0x41, 0x51, 0x25, 0x9e, 0xc3, 0x1c, 0x02, 0x6a, 0x43, + 0x89, 0x9c, 0xe9, 0x44, 0xe0, 0xaa, 0xf4, 0x1c, 0x14, 0x22, 0x64, 0x76, 0x7c, 0x7e, 0x16, 0xf6, + 0x03, 0x61, 0x74, 0x27, 0x86, 0x29, 0xaf, 0xcc, 0x53, 0x12, 0x05, 0x95, 0xf7, 0xe2, 0xa0, 0xf2, + 0xfd, 0x39, 0xb2, 0x63, 0xa8, 0xf2, 0x4e, 0x0c, 0x55, 0xce, 0x1b, 0x38, 0x06, 0x2b, 0x77, 0x27, + 0xc0, 0xca, 0x79, 0xcb, 0x9f, 0x82, 0x2b, 0x77, 0x27, 0xe0, 0xca, 0x1b, 0x73, 0xe7, 0x32, 0x11, + 0x58, 0xde, 0x8b, 0x03, 0xcb, 0x79, 0xe6, 0x18, 0x43, 0x96, 0x8f, 0x26, 0x21, 0xcb, 0x9b, 0x73, + 0x74, 0x4c, 0x85, 0x96, 0xdb, 0xe7, 0xa0, 0xe5, 0xb5, 0x39, 0xaa, 0x26, 0x60, 0xcb, 0xdd, 0x18, + 0xb6, 0x84, 0x44, 0xb6, 0x99, 0x02, 0x2e, 0x1f, 0x9c, 0x07, 0x97, 0xd7, 0xe7, 0x1d, 0xb5, 0x49, + 0xe8, 0xf2, 0x07, 0x63, 0xe8, 0xf2, 0xea, 0xbc, 0x55, 0x8d, 0xc3, 0xcb, 0xa3, 0x29, 0xf0, 0xf2, + 0xd6, 0x1c, 0x45, 0x73, 0xf0, 0xe5, 0xd1, 0x14, 0x7c, 0x39, 0x4f, 0xed, 0x1c, 0x80, 0xd9, 0x99, + 0x05, 0x30, 0x3f, 0x9a, 0x37, 0xe5, 0x64, 0x08, 0x93, 0xcc, 0x44, 0x98, 0x1f, 0xcf, 0x19, 0x64, + 0x71, 0x88, 0x79, 0x93, 0x05, 0xf9, 0x31, 0x97, 0xc4, 0x5c, 0x21, 0x71, 0x5d, 0xdb, 0x95, 0xe8, + 0x4d, 0x74, 0x94, 0x1b, 0x0c, 0x76, 0x84, 0x8e, 0x67, 0x06, 0x1c, 0xe5, 0x81, 0x27, 0xe2, 0x66, + 0x94, 0x3f, 0xa7, 0x43, 0x59, 0x1e, 0x9d, 0xa3, 0x90, 0xa5, 0x24, 0x21, 0x4b, 0x04, 0xa5, 0x66, + 0xe2, 0x28, 0x75, 0x1d, 0xca, 0x2c, 0x94, 0x8c, 0x01, 0x50, 0xec, 0xf8, 0x00, 0x14, 0x7d, 0x00, + 0xab, 0x1c, 0x43, 0x08, 0x2c, 0x2b, 0xe3, 0x47, 0x8e, 0x07, 0xc3, 0x15, 0xf6, 0x41, 0x1c, 0x5d, + 0x11, 0x48, 0xfe, 0x1f, 0x2e, 0x44, 0x78, 0x83, 0x10, 0x25, 0x90, 0x56, 0x2d, 0xe0, 0xde, 0x92, + 0xb1, 0xea, 0x71, 0x68, 0xa0, 0x10, 0xdc, 0x22, 0xc8, 0xe9, 0xb6, 0x41, 0x64, 0x00, 0xe1, 0x6d, + 0x06, 0x78, 0xfb, 0x76, 0x57, 0x86, 0x09, 0xd6, 0x64, 0x5c, 0x81, 0x4f, 0x2d, 0x09, 0x67, 0xa9, + 0xfc, 0x29, 0x1d, 0xea, 0x0b, 0xf1, 0xee, 0x24, 0x68, 0x9a, 0x7e, 0x93, 0xd0, 0x34, 0xf3, 0xdf, + 0x41, 0x53, 0xe5, 0xd7, 0x99, 0x70, 0x4b, 0x03, 0xd0, 0xf9, 0xed, 0x4c, 0x10, 0x86, 0xdf, 0x25, + 0xbe, 0x41, 0x32, 0xfc, 0xca, 0x7c, 0x21, 0xcf, 0xb7, 0x21, 0x9e, 0x2f, 0x14, 0x44, 0x40, 0xe6, + 0x1d, 0x96, 0x18, 0x3b, 0xae, 0x6d, 0x1f, 0x6b, 0xb6, 0xe3, 0x4d, 0xca, 0xf8, 0x05, 0xde, 0x14, + 0x25, 0xa2, 0xa6, 0x28, 0x2e, 0x35, 0xf7, 0x99, 0xc0, 0x9e, 0xe3, 0xa9, 0x45, 0x47, 0xb6, 0x22, + 0x30, 0xa3, 0x14, 0xc3, 0xc2, 0xef, 0x42, 0x89, 0x2d, 0xc5, 0x73, 0xb0, 0x4e, 0xb8, 0x93, 0x2d, + 0xa9, 0x21, 0x41, 0x31, 0x00, 0x9d, 0x77, 0xf6, 0xe8, 0x09, 0xe4, 0xc9, 0x29, 0xb1, 0x28, 0xdb, + 0x33, 0x66, 0xe6, 0x77, 0xa7, 0x82, 0x4b, 0x62, 0xd1, 0x56, 0x9d, 0x19, 0xf7, 0x5f, 0xdf, 0xac, + 0xd7, 0x84, 0xcc, 0x2d, 0x7b, 0x60, 0x52, 0x32, 0x70, 0xe8, 0x48, 0x95, 0x5a, 0x94, 0xdf, 0x64, + 0x18, 0xc6, 0x8b, 0x05, 0x82, 0x89, 0xe6, 0xf6, 0x2f, 0x51, 0x26, 0x82, 0xfb, 0x93, 0x6d, 0xc1, + 0x7b, 0x00, 0x5d, 0xec, 0x69, 0x2f, 0xb0, 0x45, 0x89, 0x21, 0xf7, 0xa1, 0xd4, 0xc5, 0xde, 0x8f, + 0x39, 0x81, 0x41, 0x37, 0xf6, 0x79, 0xe8, 0x11, 0x83, 0x6f, 0x48, 0x56, 0x2d, 0x74, 0xb1, 0x77, + 0xe4, 0x11, 0x23, 0xb2, 0xd6, 0xc2, 0x9b, 0x58, 0x6b, 0xdc, 0xde, 0xc5, 0x71, 0x7b, 0xff, 0x36, + 0x13, 0xde, 0x96, 0x10, 0x12, 0xff, 0x6f, 0xda, 0xe2, 0x0f, 0x3c, 0x51, 0x8e, 0x47, 0x63, 0xf4, + 0x29, 0xac, 0x06, 0xb7, 0x54, 0x1b, 0xf2, 0xdb, 0xeb, 0x9f, 0xc2, 0xc5, 0x2e, 0x7b, 0xed, 0x34, + 0x4e, 0xf6, 0xd0, 0x67, 0xf0, 0xf6, 0x98, 0x4f, 0x0a, 0x06, 0xc8, 0x2c, 0xe4, 0x9a, 0xde, 0x8a, + 0xbb, 0x26, 0x5f, 0x7f, 0x68, 0xbd, 0xec, 0x1b, 0xb9, 0x35, 0xbb, 0x2c, 0x2d, 0x8b, 0xe2, 0x8c, + 0x89, 0x67, 0xe2, 0x0a, 0x54, 0x5c, 0x42, 0xb1, 0x69, 0x69, 0xb1, 0x54, 0x78, 0x59, 0x10, 0x45, + 0x88, 0x50, 0x9e, 0xc1, 0x5b, 0x13, 0x91, 0x06, 0xfa, 0x1e, 0x94, 0x42, 0xa8, 0x92, 0x9e, 0x99, + 0x49, 0x06, 0x19, 0x51, 0x28, 0xa1, 0x7c, 0x99, 0x0e, 0x15, 0xc7, 0x33, 0xad, 0x87, 0x90, 0x77, + 0x89, 0x37, 0xec, 0x8b, 0xac, 0xa7, 0xba, 0xf9, 0xc9, 0x22, 0x48, 0x85, 0x51, 0x87, 0x7d, 0xaa, + 0x4a, 0x15, 0xca, 0x53, 0xc8, 0x0b, 0x0a, 0x02, 0xc8, 0x6f, 0x6d, 0x6f, 0xef, 0xec, 0x1f, 0xd6, + 0x52, 0xa8, 0x04, 0x4b, 0x5b, 0xad, 0x3d, 0xf5, 0xb0, 0x96, 0x66, 0x64, 0x75, 0xe7, 0x47, 0x3b, + 0xdb, 0x87, 0xb5, 0x0c, 0x5a, 0x85, 0x8a, 0x68, 0x6b, 0x0f, 0xf6, 0xd4, 0xc7, 0x5b, 0x87, 0xb5, + 0x6c, 0x84, 0x74, 0xb0, 0xf3, 0xe4, 0xfe, 0x8e, 0x5a, 0xcb, 0x29, 0x1f, 0xb3, 0x7c, 0x6a, 0x0a, + 0x90, 0x09, 0x33, 0xa7, 0x74, 0x24, 0x73, 0x52, 0x7e, 0x97, 0x81, 0xc6, 0x74, 0x5c, 0x82, 0xf6, + 0xc7, 0x56, 0x7c, 0x7b, 0x61, 0x68, 0x33, 0xb6, 0x6c, 0x74, 0x15, 0xaa, 0x2e, 0x39, 0x26, 0x54, + 0xef, 0x09, 0xcc, 0x24, 0xa2, 0x5e, 0x45, 0xad, 0x48, 0x2a, 0x17, 0xf2, 0x04, 0xdb, 0xe7, 0x44, + 0xa7, 0x9a, 0x48, 0xe5, 0xc4, 0xf9, 0x2b, 0x31, 0x36, 0x46, 0x3d, 0x10, 0x44, 0xe5, 0x60, 0x9e, + 0x11, 0x4b, 0xb0, 0xa4, 0xee, 0x1c, 0xaa, 0x9f, 0xd6, 0x32, 0x08, 0x41, 0x95, 0x37, 0xb5, 0x83, + 0x27, 0x5b, 0xfb, 0x07, 0xed, 0x3d, 0x66, 0xc4, 0x0b, 0xb0, 0xe2, 0x1b, 0xd1, 0x27, 0xe6, 0x94, + 0xbf, 0xa6, 0x61, 0x65, 0xec, 0x7a, 0xa0, 0xdb, 0xb0, 0x24, 0x80, 0x78, 0x7a, 0x66, 0x41, 0x9f, + 0xdf, 0x77, 0x79, 0xa3, 0x84, 0x00, 0x6a, 0x41, 0x91, 0xc8, 0x7a, 0xc5, 0xa4, 0x2b, 0x19, 0xad, + 0xbc, 0xf8, 0x75, 0x0d, 0xa9, 0x20, 0x90, 0x63, 0xe1, 0x34, 0xb8, 0xf9, 0x32, 0x73, 0xbc, 0x3e, + 0x4d, 0x49, 0xe0, 0x39, 0xa4, 0x96, 0x50, 0x52, 0xd9, 0x86, 0x72, 0x64, 0x82, 0xe8, 0xff, 0xa0, + 0x34, 0xc0, 0x67, 0xb2, 0x86, 0x25, 0x8a, 0x12, 0xc5, 0x01, 0x3e, 0xe3, 0xe5, 0x2b, 0xf4, 0x36, + 0x14, 0xd8, 0xc7, 0x2e, 0x16, 0x8e, 0x24, 0xab, 0xe6, 0x07, 0xf8, 0xec, 0x87, 0xd8, 0x53, 0x74, + 0xa8, 0xc6, 0x4b, 0x3b, 0xec, 0x64, 0xb9, 0xf6, 0xd0, 0x32, 0xb8, 0x8e, 0x25, 0x55, 0x74, 0xd0, + 0x5d, 0x58, 0x3a, 0xb5, 0x85, 0x1f, 0x9a, 0x75, 0x03, 0x9f, 0xd9, 0x94, 0x44, 0x0a, 0x44, 0x42, + 0x46, 0x79, 0x02, 0x55, 0xee, 0x51, 0xb6, 0x28, 0x75, 0xcd, 0xce, 0x90, 0x92, 0x68, 0xa5, 0x72, + 0x79, 0x42, 0xa5, 0x32, 0x40, 0x1e, 0x01, 0x6e, 0xc9, 0x8a, 0x32, 0x19, 0xef, 0x28, 0xbf, 0x4c, + 0xc3, 0x12, 0x57, 0xc8, 0xdc, 0x0d, 0xaf, 0xfa, 0x48, 0x4c, 0xcb, 0xda, 0x48, 0x07, 0xc0, 0xfe, + 0x40, 0xfe, 0x7c, 0xaf, 0xce, 0x72, 0x74, 0xc1, 0xb4, 0x5a, 0xef, 0x4a, 0x8f, 0x77, 0x31, 0x54, + 0x10, 0xf1, 0x7a, 0x11, 0xb5, 0xca, 0xcb, 0x34, 0x14, 0x0f, 0xcf, 0xe4, 0x69, 0x9d, 0x52, 0x0c, + 0x62, 0xb3, 0xdf, 0xe5, 0xb3, 0x17, 0xe5, 0x13, 0xd1, 0x91, 0xd5, 0xa5, 0x6c, 0x50, 0xb9, 0x7a, + 0x10, 0xdc, 0xca, 0xdc, 0x62, 0x09, 0xa6, 0x5f, 0xd4, 0x93, 0x2e, 0xa8, 0x0f, 0x05, 0x7e, 0x1e, + 0x76, 0xef, 0x4f, 0xac, 0x18, 0x3e, 0x86, 0x65, 0x07, 0xbb, 0xd4, 0xd3, 0x62, 0x75, 0xc3, 0x69, + 0x39, 0xfa, 0x3e, 0x76, 0xe9, 0x01, 0xa1, 0xb1, 0xea, 0x61, 0x99, 0xcb, 0x0b, 0x92, 0x72, 0x07, + 0x2a, 0x31, 0x1e, 0xb6, 0x58, 0x6a, 0x53, 0xdc, 0xf7, 0xcf, 0x0d, 0xef, 0x04, 0x33, 0xc9, 0x84, + 0x33, 0x51, 0xee, 0x42, 0x29, 0x38, 0xd6, 0x2c, 0x03, 0xc1, 0x86, 0xe1, 0x12, 0xcf, 0x93, 0xb3, + 0xf5, 0xbb, 0xbc, 0x44, 0x6a, 0xbf, 0x90, 0x55, 0xa0, 0xac, 0x2a, 0x3a, 0x8a, 0x0d, 0x2b, 0x63, + 0xd1, 0x14, 0x3d, 0x80, 0x82, 0x33, 0xec, 0x68, 0xfe, 0x81, 0x9a, 0x78, 0x9b, 0x24, 0x38, 0x3d, + 0x21, 0x23, 0xaf, 0xb9, 0x3f, 0xec, 0xf4, 0x4d, 0xfd, 0x21, 0x19, 0xf9, 0x06, 0x74, 0x86, 0x9d, + 0x87, 0xe2, 0x08, 0x8a, 0x01, 0x33, 0xd1, 0x01, 0x7f, 0x01, 0x45, 0xff, 0x54, 0xa3, 0xfb, 0xd1, + 0x9b, 0x2b, 0xc6, 0xba, 0x3c, 0x2f, 0xe4, 0xcb, 0x41, 0x42, 0x41, 0x96, 0x39, 0x79, 0x66, 0xd7, + 0x22, 0x86, 0x16, 0x26, 0x45, 0x7c, 0xcc, 0xa2, 0xba, 0x22, 0x3e, 0x3c, 0xf2, 0x33, 0x22, 0xe5, + 0x9f, 0x69, 0x28, 0xfa, 0x8e, 0x64, 0xe2, 0x69, 0x8f, 0x4d, 0x29, 0xf3, 0x6d, 0xa7, 0x34, 0xad, + 0x4c, 0xed, 0x3f, 0x0a, 0xe4, 0x16, 0x7e, 0x14, 0xb8, 0x05, 0x88, 0x9f, 0x00, 0xed, 0xd4, 0xa6, + 0xa6, 0xd5, 0xd5, 0x84, 0x65, 0x05, 0xd4, 0xab, 0xf1, 0x2f, 0xcf, 0xf8, 0x87, 0x7d, 0x6e, 0xe4, + 0x5f, 0xa5, 0xa1, 0x18, 0x04, 0xe6, 0x45, 0xcb, 0x91, 0x97, 0x20, 0x2f, 0x83, 0x8f, 0xa8, 0x47, + 0xca, 0x5e, 0x70, 0xf6, 0x72, 0x91, 0x5b, 0xd0, 0x80, 0xe2, 0x80, 0x50, 0xcc, 0x31, 0x8a, 0x48, + 0x3f, 0x83, 0xfe, 0x07, 0x57, 0xa0, 0x1c, 0xa9, 0x0f, 0xa3, 0x02, 0x64, 0x9f, 0x90, 0x17, 0xb5, + 0x14, 0x2a, 0x43, 0x41, 0x25, 0xbc, 0x24, 0x54, 0x4b, 0x6f, 0x7e, 0x59, 0x86, 0x95, 0xad, 0xd6, + 0xf6, 0x2e, 0x8b, 0x8d, 0xa6, 0x8e, 0x79, 0x6a, 0xba, 0x07, 0x39, 0x9e, 0x9d, 0x27, 0x78, 0x8f, + 0x6e, 0x24, 0xa9, 0x2f, 0x22, 0x15, 0x96, 0x78, 0x12, 0x8f, 0x92, 0x3c, 0x53, 0x37, 0x12, 0x95, + 0x1d, 0xd9, 0x24, 0xf9, 0x19, 0x4e, 0xf0, 0x7a, 0xdd, 0x48, 0x52, 0x8b, 0x44, 0x9f, 0x41, 0x29, + 0xcc, 0xce, 0x93, 0xbe, 0x69, 0x37, 0x12, 0x57, 0x29, 0x99, 0xfe, 0x30, 0xff, 0x48, 0xfa, 0xa2, + 0xdb, 0x48, 0xec, 0x3d, 0xd1, 0x73, 0x28, 0xf8, 0x99, 0x5e, 0xb2, 0x57, 0xe7, 0x46, 0xc2, 0x0a, + 0x22, 0xdb, 0x3e, 0x91, 0xb0, 0x27, 0x79, 0x5a, 0x6f, 0x24, 0x2a, 0x93, 0xa2, 0x23, 0xc8, 0x4b, + 0x88, 0x9d, 0xe8, 0x3d, 0xb9, 0x91, 0xac, 0x2e, 0xc8, 0x8c, 0x1c, 0x96, 0x44, 0x92, 0xfe, 0x9d, + 0xa0, 0x91, 0xb8, 0x3e, 0x8c, 0x30, 0x40, 0x24, 0x6b, 0x4f, 0xfc, 0x3f, 0x81, 0x46, 0xf2, 0xba, + 0x2f, 0xfa, 0x29, 0x14, 0x83, 0xdc, 0x2c, 0xe1, 0x7b, 0x7d, 0x23, 0x69, 0xe9, 0x15, 0x7d, 0x0e, + 0x95, 0x78, 0x3a, 0xb2, 0xc8, 0x2b, 0x7c, 0x63, 0xa1, 0x9a, 0x2a, 0x1b, 0x2b, 0x9e, 0xa1, 0x2c, + 0xf2, 0x36, 0xdf, 0x58, 0xa8, 0xd0, 0x8a, 0x4e, 0x61, 0xf5, 0x7c, 0x52, 0xb1, 0xe8, 0x83, 0x7d, + 0x63, 0xe1, 0x02, 0x2c, 0x1a, 0x01, 0x9a, 0x90, 0x98, 0x2c, 0xfc, 0x8a, 0xdf, 0x58, 0xbc, 0x2a, + 0xdb, 0xda, 0xf9, 0xea, 0xd5, 0x5a, 0xfa, 0xeb, 0x57, 0x6b, 0xe9, 0x7f, 0xbc, 0x5a, 0x4b, 0xbf, + 0x7c, 0xbd, 0x96, 0xfa, 0xfa, 0xf5, 0x5a, 0xea, 0x6f, 0xaf, 0xd7, 0x52, 0x3f, 0xf9, 0xb0, 0x6b, + 0xd2, 0xde, 0xb0, 0xd3, 0xd4, 0xed, 0xc1, 0x46, 0xa8, 0x36, 0xda, 0x0c, 0xff, 0x6d, 0xd5, 0xc9, + 0xf3, 0xe0, 0xf7, 0xc9, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x75, 0x7a, 0xc6, 0x83, 0x82, 0x25, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -6569,43 +6518,6 @@ func (m *VoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *PubKey) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *PubKey) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x12 - } - if len(m.Type) > 0 { - i -= len(m.Type) - copy(dAtA[i:], m.Type) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *Evidence) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -7903,23 +7815,6 @@ func (m *VoteInfo) Size() (n int) { return n } -func (m *PubKey) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Type) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - return n -} - func (m *Evidence) Size() (n int) { if m == nil { return 0 @@ -14477,125 +14372,6 @@ func (m *VoteInfo) Unmarshal(dAtA []byte) error { } return nil } -func (m *PubKey) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: PubKey: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Type = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *Evidence) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/abci/types/types.proto b/abci/types/types.proto index 2a9d0927d..7148cf1f2 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -6,6 +6,7 @@ option go_package = "github.com/tendermint/tendermint/abci/types"; // https://github.com/gogo/protobuf/blob/master/extensions.md import "proto/crypto/merkle/types.proto"; import "proto/types/types.proto"; +import "proto/crypto/keys/types.proto"; import "proto/types/params.proto"; import "google/protobuf/timestamp.proto"; import "third_party/proto/gogoproto/gogo.proto"; @@ -341,8 +342,8 @@ message Validator { // ValidatorUpdate message ValidatorUpdate { - PubKey pub_key = 1 [(gogoproto.nullable) = false]; - int64 power = 2; + tendermint.proto.crypto.keys.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + int64 power = 2; } // VoteInfo @@ -351,11 +352,6 @@ message VoteInfo { bool signed_last_block = 2; } -message PubKey { - string type = 1; - bytes data = 2; -} - message Evidence { string type = 1; Validator validator = 2 [(gogoproto.nullable) = false]; diff --git a/abci/types/util.go b/abci/types/util.go index 3cde88232..94a34c0c1 100644 --- a/abci/types/util.go +++ b/abci/types/util.go @@ -1,7 +1,6 @@ package types import ( - "bytes" "sort" ) @@ -24,7 +23,7 @@ func (v ValidatorUpdates) Len() int { // XXX: doesn't distinguish same validator with different power func (v ValidatorUpdates) Less(i, j int) bool { - return bytes.Compare(v[i].PubKey.Data, v[j].PubKey.Data) <= 0 + return v[i].PubKey.Compare(v[j].PubKey) <= 0 } func (v ValidatorUpdates) Swap(i, j int) { diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index f85f3b84c..57aec1f3b 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -21,6 +21,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" cstypes "github.com/tendermint/tendermint/consensus/types" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/libs/bits" "github.com/tendermint/tendermint/libs/bytes" @@ -361,7 +362,9 @@ func TestReactorVotingPowerChange(t *testing.T) { val1PubKey, err := css[0].privValidator.GetPubKey() require.NoError(t, err) - val1PubKeyABCI := types.TM2PB.PubKey(val1PubKey) + + val1PubKeyABCI, err := cryptoenc.PubKeyToProto(val1PubKey) + require.NoError(t, err) updateValidatorTx := kvstore.MakeValSetChangeTx(val1PubKeyABCI, 25) previousTotalVotingPower := css[0].GetRoundState().LastValidators.TotalVotingPower() @@ -441,8 +444,9 @@ func TestReactorValidatorSetChanges(t *testing.T) { logger.Info("---------------------------- Testing adding one validator") newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey() - require.NoError(t, err) - valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1) + assert.NoError(t, err) + valPubKey1ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey1) + assert.NoError(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) // wait till everyone makes block 2 @@ -470,7 +474,8 @@ func TestReactorValidatorSetChanges(t *testing.T) { updateValidatorPubKey1, err := css[nVals].privValidator.GetPubKey() require.NoError(t, err) - updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1) + updatePubKey1ABCI, err := cryptoenc.PubKeyToProto(updateValidatorPubKey1) + require.NoError(t, err) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) previousTotalVotingPower := css[nVals].GetRoundState().LastValidators.TotalVotingPower() @@ -491,12 +496,14 @@ func TestReactorValidatorSetChanges(t *testing.T) { newValidatorPubKey2, err := css[nVals+1].privValidator.GetPubKey() require.NoError(t, err) - newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2) + newVal2ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey2) + require.NoError(t, err) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey() require.NoError(t, err) - newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3) + newVal3ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey3) + require.NoError(t, err) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, newValidatorTx2, newValidatorTx3) diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 3d77efd08..7b4df25b0 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -22,6 +22,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" mempl "github.com/tendermint/tendermint/mempool" @@ -351,7 +352,8 @@ func TestSimulateValidatorsChange(t *testing.T) { incrementHeight(vss...) newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey() require.NoError(t, err) - valPubKey1ABCI := types.TM2PB.PubKey(newValidatorPubKey1) + valPubKey1ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey1) + require.NoError(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1, nil, mempl.TxInfo{}) assert.Nil(t, err) @@ -379,7 +381,8 @@ func TestSimulateValidatorsChange(t *testing.T) { incrementHeight(vss...) updateValidatorPubKey1, err := css[nVals].privValidator.GetPubKey() require.NoError(t, err) - updatePubKey1ABCI := types.TM2PB.PubKey(updateValidatorPubKey1) + updatePubKey1ABCI, err := cryptoenc.PubKeyToProto(updateValidatorPubKey1) + require.NoError(t, err) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1, nil, mempl.TxInfo{}) assert.Nil(t, err) @@ -407,13 +410,15 @@ func TestSimulateValidatorsChange(t *testing.T) { incrementHeight(vss...) newValidatorPubKey2, err := css[nVals+1].privValidator.GetPubKey() require.NoError(t, err) - newVal2ABCI := types.TM2PB.PubKey(newValidatorPubKey2) + newVal2ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey2) + require.NoError(t, err) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx2, nil, mempl.TxInfo{}) assert.Nil(t, err) newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey() require.NoError(t, err) - newVal3ABCI := types.TM2PB.PubKey(newValidatorPubKey3) + newVal3ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey3) + require.NoError(t, err) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3, nil, mempl.TxInfo{}) assert.Nil(t, err) diff --git a/crypto/crypto.go b/crypto/crypto.go index 045a35e86..765632f71 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -24,6 +24,7 @@ type PubKey interface { Bytes() []byte VerifyBytes(msg []byte, sig []byte) bool Equals(PubKey) bool + Type() string } type PrivKey interface { @@ -31,6 +32,7 @@ type PrivKey interface { Sign(msg []byte) ([]byte, error) PubKey() PubKey Equals(PrivKey) bool + Type() string } type Symmetric interface { diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index 19c383525..504da8783 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -30,6 +30,8 @@ const ( // SeedSize is the size, in bytes, of private key seeds. These are the // private key representations used by RFC 8032. SeedSize = 32 + + keyType = "ed25519" ) func init() { @@ -90,6 +92,10 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } +func (privKey PrivKey) Type() string { + return keyType +} + // GenPrivKey generates a new ed25519 private key. // It uses OS randomness in conjunction with the current global random seed // in tendermint/libs/common to generate the private key. @@ -151,6 +157,10 @@ func (pubKey PubKey) String() string { return fmt.Sprintf("PubKeyEd25519{%X}", []byte(pubKey)) } +func (pubKey PubKey) Type() string { + return keyType +} + func (pubKey PubKey) Equals(other crypto.PubKey) bool { if otherEd, ok := other.(PubKey); ok { return bytes.Equal(pubKey[:], otherEd[:]) diff --git a/crypto/encoding/amino/encode_test.go b/crypto/encoding/amino/encode_test.go index 8e5e44c3a..509ffa279 100644 --- a/crypto/encoding/amino/encode_test.go +++ b/crypto/encoding/amino/encode_test.go @@ -160,6 +160,7 @@ func (privkey testPriv) Bytes() []byte { } func (privkey testPriv) Sign(msg []byte) ([]byte, error) { return []byte{}, nil } func (privkey testPriv) Equals(other crypto.PrivKey) bool { return true } +func (privkey testPriv) Type() string { return "testPriv" } type testPub []byte @@ -169,6 +170,8 @@ func (key testPub) Bytes() []byte { } func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true } func (key testPub) Equals(other crypto.PubKey) bool { return true } +func (key testPub) String() string { return "" } +func (key testPub) Type() string { return "testPub" } var ( privAminoName = "registerTest/Priv" diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go index 2fbf1799b..c223510dd 100644 --- a/crypto/secp256k1/secp256k1.go +++ b/crypto/secp256k1/secp256k1.go @@ -16,7 +16,10 @@ import ( var _ crypto.PrivKey = PrivKey{} -const PrivKeySize = 32 +const ( + PrivKeySize = 32 + keyType = "secp256k1" +) // PrivKey implements PrivKey. type PrivKey []byte @@ -42,6 +45,10 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } +func (privKey PrivKey) Type() string { + return keyType +} + // GenPrivKey generates a new ECDSA private key on curve secp256k1 private key. // It uses OS randomness to generate the private key. func GenPrivKey() PrivKey { @@ -140,6 +147,10 @@ func (pubKey PubKey) String() string { return fmt.Sprintf("PubKeySecp256k1{%X}", []byte(pubKey)) } +func (pubKey PubKey) Type() string { + return keyType +} + func (pubKey PubKey) Equals(other crypto.PubKey) bool { if otherSecp, ok := other.(PubKey); ok { return bytes.Equal(pubKey[:], otherSecp[:]) diff --git a/crypto/sr25519/privkey.go b/crypto/sr25519/privkey.go index 47d970796..215a50173 100644 --- a/crypto/sr25519/privkey.go +++ b/crypto/sr25519/privkey.go @@ -69,6 +69,10 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } +func (privKey PrivKey) Type() string { + return keyType +} + // GenPrivKey generates a new sr25519 private key. // It uses OS randomness in conjunction with the current global random seed // in tendermint/libs/common to generate the private key. diff --git a/crypto/sr25519/pubkey.go b/crypto/sr25519/pubkey.go index 0b578057a..1256136d3 100644 --- a/crypto/sr25519/pubkey.go +++ b/crypto/sr25519/pubkey.go @@ -13,7 +13,10 @@ import ( var _ crypto.PubKey = PubKey{} // PubKeySize is the number of bytes in an Sr25519 public key. -const PubKeySize = 32 +const ( + PubKeySize = 32 + keyType = "sr25519" +) // PubKeySr25519 implements crypto.PubKey for the Sr25519 signature scheme. type PubKey []byte @@ -67,3 +70,8 @@ func (pubKey PubKey) Equals(other crypto.PubKey) bool { } return false } + +func (pubKey PubKey) Type() string { + return keyType + +} diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 9ded86a15..914ebc40a 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -51,6 +51,7 @@ func (pk privKeyWithNilPubKey) Bytes() []byte { return pk.orig func (pk privKeyWithNilPubKey) Sign(msg []byte) ([]byte, error) { return pk.orig.Sign(msg) } func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil } func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) } +func (pk privKeyWithNilPubKey) Type() string { return "privKeyWithNilPubKey" } func TestSecretConnectionHandshake(t *testing.T) { fooSecConn, barSecConn := makeSecretConnPair(t) diff --git a/proto/crypto/keys/types.pb.go b/proto/crypto/keys/types.pb.go index 271cb4932..fd379dfbe 100644 --- a/proto/crypto/keys/types.pb.go +++ b/proto/crypto/keys/types.pb.go @@ -8,7 +8,6 @@ import ( fmt "fmt" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" - golang_proto "github.com/golang/protobuf/proto" io "io" math "math" math_bits "math/bits" @@ -16,7 +15,6 @@ import ( // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal -var _ = golang_proto.Marshal var _ = fmt.Errorf var _ = math.Inf @@ -177,18 +175,13 @@ func (*PrivateKey) XXX_OneofWrappers() []interface{} { func init() { proto.RegisterType((*PublicKey)(nil), "tendermint.proto.crypto.keys.PublicKey") - golang_proto.RegisterType((*PublicKey)(nil), "tendermint.proto.crypto.keys.PublicKey") proto.RegisterType((*PrivateKey)(nil), "tendermint.proto.crypto.keys.PrivateKey") - golang_proto.RegisterType((*PrivateKey)(nil), "tendermint.proto.crypto.keys.PrivateKey") } func init() { proto.RegisterFile("proto/crypto/keys/types.proto", fileDescriptor_943d79b57ec0188f) } -func init() { - golang_proto.RegisterFile("proto/crypto/keys/types.proto", fileDescriptor_943d79b57ec0188f) -} var fileDescriptor_943d79b57ec0188f = []byte{ - // 220 bytes of a gzipped FileDescriptorProto + // 215 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x03, 0x8b, 0x0b, 0xc9, 0x94, 0xa4, 0xe6, 0xa5, 0xa4, 0x16, 0xe5, 0x66, @@ -198,11 +191,11 @@ var fileDescriptor_943d79b57ec0188f = []byte{ 0x52, 0x5c, 0xec, 0xa9, 0x29, 0x46, 0xa6, 0xa6, 0x86, 0x96, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x3c, 0x1e, 0x0c, 0x41, 0x30, 0x01, 0x2b, 0x8e, 0x17, 0x0b, 0xe4, 0x19, 0x5f, 0x2c, 0x94, 0x67, 0x74, 0x62, 0xe5, 0x62, 0x2e, 0x2e, 0xcd, 0x55, 0xd2, 0xe7, 0xe2, 0x0a, 0x28, 0xca, 0x2c, 0x4b, 0x2c, - 0x49, 0x25, 0xa0, 0x15, 0xaa, 0xc1, 0x29, 0xe0, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, - 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc0, 0x63, 0x39, 0xc6, 0x0b, 0x8f, 0xe5, - 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4a, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, - 0xcf, 0xd5, 0x47, 0xf8, 0x0c, 0x99, 0x89, 0x11, 0x1c, 0x49, 0x6c, 0x60, 0x21, 0x63, 0x40, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xc1, 0xcf, 0x98, 0xcb, 0x2a, 0x01, 0x00, 0x00, + 0x49, 0x25, 0xa0, 0x15, 0xaa, 0xc1, 0xc9, 0xe7, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, + 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, + 0x18, 0xa2, 0x8c, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x11, 0xbe, + 0x42, 0x66, 0x62, 0x04, 0x45, 0x12, 0x1b, 0x58, 0xc8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x85, + 0x0d, 0xee, 0x82, 0x26, 0x01, 0x00, 0x00, } func (this *PublicKey) Compare(that interface{}) int { diff --git a/proto/crypto/keys/types.proto b/proto/crypto/keys/types.proto index 8ad0d6674..be4abd609 100644 --- a/proto/crypto/keys/types.proto +++ b/proto/crypto/keys/types.proto @@ -5,11 +5,6 @@ option go_package = "github.com/tendermint/tendermint/proto/crypto/keys"; import "third_party/proto/gogoproto/gogo.proto"; -option (gogoproto.marshaler_all) = true; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.sizer_all) = true; -option (gogoproto.goproto_registration) = true; - // PublicKey defines the keys available for use with Tendermint Validators message PublicKey { option (gogoproto.compare) = true; diff --git a/proto/crypto/merkle/types.pb.go b/proto/crypto/merkle/types.pb.go index 06835cc3b..41e452962 100644 --- a/proto/crypto/merkle/types.pb.go +++ b/proto/crypto/merkle/types.pb.go @@ -154,7 +154,7 @@ func (m *ProofOp) GetData() []byte { return nil } -// Proof is Merkle proof defined by the list of ProofOps +// ProofOps is Merkle proof defined by the list of ProofOps type ProofOps struct { Ops []ProofOp `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops"` } diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index e7ad34d07..71f6a4b9b 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -11,6 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/privval" tmproto "github.com/tendermint/tendermint/proto/types" @@ -122,7 +123,8 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { status, err := c.Status() require.NoError(t, err) - client.WaitForHeight(c, status.SyncInfo.LatestBlockHeight+2, nil) + err = client.WaitForHeight(c, status.SyncInfo.LatestBlockHeight+2, nil) + require.NoError(t, err) ed25519pub := pv.Key.PubKey.(ed25519.PubKey) rawpub := ed25519pub.Bytes() @@ -135,7 +137,10 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { err = abci.ReadMessage(bytes.NewReader(qres.Value), &v) require.NoError(t, err, "Error reading query result, value %v", qres.Value) - require.EqualValues(t, rawpub, v.PubKey.Data, "Stored PubKey not equal with expected, value %v", string(qres.Value)) + pk, err := cryptoenc.PubKeyFromProto(v.PubKey) + require.NoError(t, err) + + require.EqualValues(t, rawpub, pk.Bytes(), "Stored PubKey not equal with expected, value %v", string(qres.Value)) require.Equal(t, int64(9), v.Power, "Stored Power not equal with expected, value %v", string(qres.Value)) for _, fake := range fakes { diff --git a/rpc/client/helpers.go b/rpc/client/helpers.go index b090ac104..af8d4998e 100644 --- a/rpc/client/helpers.go +++ b/rpc/client/helpers.go @@ -48,6 +48,7 @@ func WaitForHeight(c StatusClient, h int64, waiter Waiter) error { return err } } + return nil } diff --git a/rpc/client/http/http.go b/rpc/client/http/http.go index 88625aeb2..ed6b6dbe3 100644 --- a/rpc/client/http/http.go +++ b/rpc/client/http/http.go @@ -207,6 +207,7 @@ func (c *baseRPCClient) Status() (*ctypes.ResultStatus, error) { if err != nil { return nil, err } + return result, nil } @@ -216,6 +217,7 @@ func (c *baseRPCClient) ABCIInfo() (*ctypes.ResultABCIInfo, error) { if err != nil { return nil, err } + return result, nil } @@ -234,6 +236,7 @@ func (c *baseRPCClient) ABCIQueryWithOptions( if err != nil { return nil, err } + return result, nil } diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index 3420df667..312e4c05a 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" mempl "github.com/tendermint/tendermint/mempool" diff --git a/state/execution.go b/state/execution.go index 350194cdd..739855675 100644 --- a/state/execution.go +++ b/state/execution.go @@ -8,6 +8,7 @@ import ( dbm "github.com/tendermint/tm-db" abci "github.com/tendermint/tendermint/abci/types" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/fail" "github.com/tendermint/tendermint/libs/log" mempl "github.com/tendermint/tendermint/mempool" @@ -380,10 +381,14 @@ func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, } // Check if validator's pubkey matches an ABCI type in the consensus params - thisKeyType := valUpdate.PubKey.Type - if !types.IsValidPubkeyType(params, thisKeyType) { + pk, err := cryptoenc.PubKeyFromProto(valUpdate.PubKey) + if err != nil { + return err + } + + if !types.IsValidPubkeyType(params, pk.Type()) { return fmt.Errorf("validator %v is using pubkey %s, which is unsupported for consensus", - valUpdate, thisKeyType) + valUpdate, pk.Type()) } } return nil diff --git a/state/execution_test.go b/state/execution_test.go index f20454c5f..c37f0d5e8 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -11,7 +11,7 @@ import ( "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/crypto/secp256k1" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/mempool/mock" tmproto "github.com/tendermint/tendermint/proto/types" @@ -175,8 +175,10 @@ func TestBeginBlockByzantineValidators(t *testing.T) { func TestValidateValidatorUpdates(t *testing.T) { pubkey1 := ed25519.GenPrivKey().PubKey() pubkey2 := ed25519.GenPrivKey().PubKey() - - secpKey := secp256k1.GenPrivKey().PubKey() + pk1, err := cryptoenc.PubKeyToProto(pubkey1) + assert.NoError(t, err) + pk2, err := cryptoenc.PubKeyToProto(pubkey2) + assert.NoError(t, err) defaultValidatorParams := tmproto.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}} @@ -190,42 +192,26 @@ func TestValidateValidatorUpdates(t *testing.T) { }{ { "adding a validator is OK", - - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}}, + []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}}, defaultValidatorParams, - false, }, { "updating a validator is OK", - - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}}, + []abci.ValidatorUpdate{{PubKey: pk1, Power: 20}}, defaultValidatorParams, - false, }, { "removing a validator is OK", - - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}}, + []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}}, defaultValidatorParams, - false, }, { "adding a validator with negative power results in error", - - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: -100}}, + []abci.ValidatorUpdate{{PubKey: pk2, Power: -100}}, defaultValidatorParams, - - true, - }, - { - "adding a validator with pubkey thats not in validator params results in error", - - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(secpKey), Power: -100}}, - defaultValidatorParams, - true, }, } @@ -249,6 +235,11 @@ func TestUpdateValidators(t *testing.T) { pubkey2 := ed25519.GenPrivKey().PubKey() val2 := types.NewValidator(pubkey2, 20) + pk, err := cryptoenc.PubKeyToProto(pubkey1) + require.NoError(t, err) + pk2, err := cryptoenc.PubKeyToProto(pubkey2) + require.NoError(t, err) + testCases := []struct { name string @@ -260,37 +251,29 @@ func TestUpdateValidators(t *testing.T) { }{ { "adding a validator is OK", - types.NewValidatorSet([]*types.Validator{val1}), - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 20}}, - + []abci.ValidatorUpdate{{PubKey: pk2, Power: 20}}, types.NewValidatorSet([]*types.Validator{val1, val2}), false, }, { "updating a validator is OK", - types.NewValidatorSet([]*types.Validator{val1}), - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey1), Power: 20}}, - + []abci.ValidatorUpdate{{PubKey: pk, Power: 20}}, types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}), false, }, { "removing a validator is OK", - types.NewValidatorSet([]*types.Validator{val1, val2}), - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}}, - + []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}}, types.NewValidatorSet([]*types.Validator{val1}), false, }, { "removing a non-existing validator results in error", - types.NewValidatorSet([]*types.Validator{val1}), - []abci.ValidatorUpdate{{PubKey: types.TM2PB.PubKey(pubkey2), Power: 0}}, - + []abci.ValidatorUpdate{{PubKey: pk2, Power: 0}}, types.NewValidatorSet([]*types.Validator{val1}), true, }, @@ -355,13 +338,14 @@ func TestEndBlockValidatorUpdates(t *testing.T) { blockID := types.BlockID{Hash: block.Hash(), PartsHeader: block.MakePartSet(testPartSize).Header()} pubkey := ed25519.GenPrivKey().PubKey() + pk, err := cryptoenc.PubKeyToProto(pubkey) + require.NoError(t, err) app.ValidatorUpdates = []abci.ValidatorUpdate{ - {PubKey: types.TM2PB.PubKey(pubkey), Power: 10}, + {PubKey: pk, Power: 10}, } state, _, err = blockExec.ApplyBlock(state, blockID, block) require.Nil(t, err) - // test new validator was added to NextValidators if assert.Equal(t, state.Validators.Size()+1, state.NextValidators.Size()) { idx, _ := state.NextValidators.GetByAddress(pubkey.Address()) @@ -408,9 +392,11 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { block := makeBlock(state, 1) blockID := types.BlockID{Hash: block.Hash(), PartsHeader: block.MakePartSet(testPartSize).Header()} + vp, err := cryptoenc.PubKeyToProto(state.Validators.Validators[0].PubKey) + require.NoError(t, err) // Remove the only validator app.ValidatorUpdates = []abci.ValidatorUpdate{ - {PubKey: types.TM2PB.PubKey(state.Validators.Validators[0].PubKey), Power: 0}, + {PubKey: vp, Power: 0}, } assert.NotPanics(t, func() { state, _, err = blockExec.ApplyBlock(state, blockID, block) }) diff --git a/state/state_test.go b/state/state_test.go index 83ba3bf95..4cae6f97b 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -17,6 +17,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" tmrand "github.com/tendermint/tendermint/libs/rand" tmstate "github.com/tendermint/tendermint/proto/state" tmproto "github.com/tendermint/tendermint/proto/types" @@ -432,7 +433,10 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { // add a validator val2PubKey := ed25519.GenPrivKey().PubKey() val2VotingPower := int64(100) - updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val2VotingPower} + fvp, err := cryptoenc.PubKeyToProto(val2PubKey) + require.NoError(t, err) + + updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) assert.NoError(t, err) updatedState2, err := sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates) @@ -468,7 +472,7 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { // Updating a validator does not reset the ProposerPriority to zero: // 1. Add - Val2 VotingPower change to 1 => updatedVotingPowVal2 := int64(1) - updateVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: updatedVotingPowVal2} + updateVal := abci.ValidatorUpdate{PubKey: fvp, Power: updatedVotingPowVal2} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateVal}) assert.NoError(t, err) @@ -546,7 +550,9 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { // add a validator with the same voting power as the first val2PubKey := ed25519.GenPrivKey().PubKey() - updateAddVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(val2PubKey), Power: val1VotingPower} + fvp, err := cryptoenc.PubKeyToProto(val2PubKey) + require.NoError(t, err) + updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val1VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) assert.NoError(t, err) @@ -727,7 +733,9 @@ func TestLargeGenesisValidator(t *testing.T) { // see: https://github.com/tendermint/tendermint/issues/2960 firstAddedValPubKey := ed25519.GenPrivKey().PubKey() firstAddedValVotingPower := int64(10) - firstAddedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(firstAddedValPubKey), Power: firstAddedValVotingPower} + fvp, err := cryptoenc.PubKeyToProto(firstAddedValPubKey) + require.NoError(t, err) + firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal}) assert.NoError(t, err) abciResponses := &tmstate.ABCIResponses{ @@ -770,8 +778,9 @@ func TestLargeGenesisValidator(t *testing.T) { // add 10 validators with the same voting power as the one added directly after genesis: for i := 0; i < 10; i++ { addedPubKey := ed25519.GenPrivKey().PubKey() - - addedVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(addedPubKey), Power: firstAddedValVotingPower} + ap, err := cryptoenc.PubKeyToProto(addedPubKey) + require.NoError(t, err) + addedVal := abci.ValidatorUpdate{PubKey: ap, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal}) assert.NoError(t, err) @@ -786,7 +795,9 @@ func TestLargeGenesisValidator(t *testing.T) { require.Equal(t, 10+2, len(state.NextValidators.Validators)) // remove genesis validator: - removeGenesisVal := abci.ValidatorUpdate{PubKey: types.TM2PB.PubKey(genesisPubKey), Power: 0} + gp, err := cryptoenc.PubKeyToProto(genesisPubKey) + require.NoError(t, err) + removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0} abciResponses = &tmstate.ABCIResponses{ EndBlock: &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}}, } diff --git a/types/protobuf.go b/types/protobuf.go index f745f2247..f3a40ff3e 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -8,6 +8,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/sr25519" tmproto "github.com/tendermint/tendermint/proto/types" @@ -89,33 +90,13 @@ func (tm2pb) PartSetHeader(header PartSetHeader) abci.PartSetHeader { // XXX: panics on unknown pubkey type func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate { - return abci.ValidatorUpdate{ - PubKey: TM2PB.PubKey(val.PubKey), - Power: val.VotingPower, + pk, err := cryptoenc.PubKeyToProto(val.PubKey) + if err != nil { + panic(err) } -} - -// XXX: panics on nil or unknown pubkey type -// TODO: add cases when new pubkey types are added to crypto -func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey { - switch pk := pubKey.(type) { - case ed25519.PubKey: - return abci.PubKey{ - Type: ABCIPubKeyTypeEd25519, - Data: pk[:], - } - case sr25519.PubKey: - return abci.PubKey{ - Type: ABCIPubKeyTypeSr25519, - Data: pk[:], - } - case secp256k1.PubKey: - return abci.PubKey{ - Type: ABCIPubKeyTypeSecp256k1, - Data: pk[:], - } - default: - panic(fmt.Sprintf("unknown pubkey type: %v %v", pubKey, reflect.TypeOf(pubKey))) + return abci.ValidatorUpdate{ + PubKey: pk, + Power: val.VotingPower, } } @@ -179,7 +160,10 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci. // XXX: panics on nil or unknown pubkey type func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate { - pubkeyABCI := TM2PB.PubKey(pubkey) + pubkeyABCI, err := cryptoenc.PubKeyToProto(pubkey) + if err != nil { + panic(err) + } return abci.ValidatorUpdate{ PubKey: pubkeyABCI, Power: power, @@ -194,41 +178,10 @@ var PB2TM = pb2tm{} type pb2tm struct{} -func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) { - switch pubKey.Type { - case ABCIPubKeyTypeEd25519: - if len(pubKey.Data) != ed25519.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", - len(pubKey.Data), ed25519.PubKeySize) - } - var pk = make(ed25519.PubKey, ed25519.PubKeySize) - copy(pk, pubKey.Data) - return pk, nil - case ABCIPubKeyTypeSr25519: - if len(pubKey.Data) != sr25519.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeySr25519. Got %d, expected %d", - len(pubKey.Data), sr25519.PubKeySize) - } - var pk = make(sr25519.PubKey, sr25519.PubKeySize) - copy(pk, pubKey.Data) - return pk, nil - case ABCIPubKeyTypeSecp256k1: - if len(pubKey.Data) != secp256k1.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeySecp256k1. Got %d, expected %d", - len(pubKey.Data), secp256k1.PubKeySize) - } - var pk = make(secp256k1.PubKey, secp256k1.PubKeySize) - copy(pk, pubKey.Data) - return pk, nil - default: - return nil, fmt.Errorf("unknown pubkey type %v", pubKey.Type) - } -} - func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error) { tmVals := make([]*Validator, len(vals)) for i, v := range vals { - pub, err := PB2TM.PubKey(v.PubKey) + pub, err := cryptoenc.PubKeyFromProto(v.PubKey) if err != nil { return nil, err } diff --git a/types/protobuf_test.go b/types/protobuf_test.go index c4ccf6ef2..213b1f303 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -13,22 +13,23 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/crypto/secp256k1" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/proto/version" ) func TestABCIPubKey(t *testing.T) { pkEd := ed25519.GenPrivKey().PubKey() - pkSecp := secp256k1.GenPrivKey().PubKey() - testABCIPubKey(t, pkEd, ABCIPubKeyTypeEd25519) - testABCIPubKey(t, pkSecp, ABCIPubKeyTypeSecp256k1) + err := testABCIPubKey(t, pkEd, ABCIPubKeyTypeEd25519) + assert.NoError(t, err) } -func testABCIPubKey(t *testing.T, pk crypto.PubKey, typeStr string) { - abciPubKey := TM2PB.PubKey(pk) - pk2, err := PB2TM.PubKey(abciPubKey) - assert.Nil(t, err) - assert.Equal(t, pk, pk2) +func testABCIPubKey(t *testing.T, pk crypto.PubKey, typeStr string) error { + abciPubKey, err := cryptoenc.PubKeyToProto(pk) + require.NoError(t, err) + pk2, err := cryptoenc.PubKeyFromProto(abciPubKey) + require.NoError(t, err) + require.Equal(t, pk, pk2) + return nil } func TestABCIValidators(t *testing.T) { @@ -54,13 +55,6 @@ func TestABCIValidators(t *testing.T) { tmVals, err = PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal}) assert.Nil(t, err) assert.Equal(t, tmValExpected, tmVals[0]) - - // val with incorrect pubkey data - abciVal = TM2PB.ValidatorUpdate(tmVal) - abciVal.PubKey.Data = []byte("incorrect!") - tmVals, err = PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal}) - assert.NotNil(t, err) - assert.Nil(t, tmVals) } func TestABCIConsensusParams(t *testing.T) { @@ -154,6 +148,8 @@ func (pubKeyEddie) Address() Address { return []byte{} } func (pubKeyEddie) Bytes() []byte { return []byte{} } func (pubKeyEddie) VerifyBytes(msg []byte, sig []byte) bool { return false } func (pubKeyEddie) Equals(crypto.PubKey) bool { return false } +func (pubKeyEddie) String() string { return "" } +func (pubKeyEddie) Type() string { return "pubKeyEddie" } func TestABCIValidatorFromPubKeyAndPower(t *testing.T) { pubkey := ed25519.GenPrivKey().PubKey() From f6243d8b9ec5dde8b0fe951d3726d77520ea1195 Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 11 Jun 2020 11:54:02 +0200 Subject: [PATCH 11/12] privval: migrate to protobuf (#4985) --- CHANGELOG_PENDING.md | 2 + blockchain/v1/reactor_test.go | 5 +- consensus/byzantine_test.go | 10 +- consensus/common_test.go | 10 +- consensus/replay_test.go | 18 +- consensus/state.go | 12 +- consensus/state_test.go | 11 +- consensus/types/height_vote_set_test.go | 7 +- crypto/ed25519/ed25519.go | 1 + evidence/pool_test.go | 12 +- libs/math/safemath.go | 12 + light/helpers_test.go | 6 +- privval/codec.go | 14 - privval/errors.go | 9 +- privval/file.go | 37 +- privval/file_test.go | 69 +- privval/messages.go | 83 +- privval/retry_signer_client.go | 5 +- privval/signer_client.go | 49 +- privval/signer_client_test.go | 176 ++- privval/signer_endpoint.go | 18 +- privval/signer_listener_endpoint.go | 7 +- privval/signer_requestHandler.go | 53 +- privval/signer_server.go | 15 +- proto/privval/msgs.pb.go | 1053 ++++++++++-- proto/privval/msgs.proto | 23 +- proto/privval/types.pb.go | 102 +- proto/privval/types.proto | 11 +- proto/types/canonical.pb.go | 1407 +++++++++++++++++ proto/types/canonical.proto | 37 + proto/types/types.pb.go | 166 +- proto/types/types.proto | 4 +- rpc/client/evidence_test.go | 14 +- state/tx_filter_test.go | 2 +- state/validation_test.go | 50 +- .../internal/test_harness.go | 12 +- .../internal/test_harness_test.go | 2 +- types/block.go | 3 +- types/block_test.go | 14 +- types/canonical.go | 52 +- types/evidence.go | 32 +- types/evidence_test.go | 14 +- types/priv_validator.go | 19 +- types/proposal.go | 12 +- types/proposal_test.go | 50 +- types/test_util.go | 11 +- types/validator_set_test.go | 4 +- types/vote.go | 19 +- types/vote_test.go | 103 +- 49 files changed, 3215 insertions(+), 642 deletions(-) delete mode 100644 privval/codec.go create mode 100644 proto/types/canonical.pb.go create mode 100644 proto/types/canonical.proto diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index acde88167..aba94092b 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -49,6 +49,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [store] \#4778 Transition store module to protobuf encoding - `BlockStoreStateJSON` is now `BlockStoreState` and is encoded as binary in the database - [rpc] \#4968 JSON encoding is now handled by `libs/json`, not Amino + - [types] \#4852 Vote & Proposal `SignBytes` is now func `VoteSignBytes` & `ProposalSignBytes` + - [privval] \#4985 `privval` reactor migration to Protobuf encoding - [evidence] \#4949 `evidence` reactor migration to Protobuf encoding - Apps diff --git a/blockchain/v1/reactor_test.go b/blockchain/v1/reactor_test.go index b7e337e1d..4d65c11b0 100644 --- a/blockchain/v1/reactor_test.go +++ b/blockchain/v1/reactor_test.go @@ -69,7 +69,10 @@ func makeVote( BlockID: blockID, } - _ = privVal.SignVote(header.ChainID, vote) + vpb := vote.ToProto() + + _ = privVal.SignVote(header.ChainID, vpb) + vote.Signature = vpb.Signature return vote } diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index a9adf0baa..c7ff8c1a0 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -181,18 +181,24 @@ func byzantineDecideProposalFunc(t *testing.T, height int64, round int32, cs *St block1, blockParts1 := cs.createProposalBlock() polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartsHeader: blockParts1.Header()} proposal1 := types.NewProposal(height, round, polRound, propBlockID) - if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal1); err != nil { + p1 := proposal1.ToProto() + if err := cs.privValidator.SignProposal(cs.state.ChainID, p1); err != nil { t.Error(err) } + proposal1.Signature = p1.Signature + // Create a new proposal block from state/txs from the mempool. block2, blockParts2 := cs.createProposalBlock() polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartsHeader: blockParts2.Header()} proposal2 := types.NewProposal(height, round, polRound, propBlockID) - if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal2); err != nil { + p2 := proposal2.ToProto() + if err := cs.privValidator.SignProposal(cs.state.ChainID, p2); err != nil { t.Error(err) } + proposal2.Signature = p2.Signature + block1Hash := block1.Hash() block2Hash := block2.Hash() diff --git a/consensus/common_test.go b/consensus/common_test.go index 54ee847ea..ecdbadb0f 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -105,8 +105,10 @@ func (vs *validatorStub) signVote( Type: voteType, BlockID: types.BlockID{Hash: hash, PartsHeader: header}, } + v := vote.ToProto() + err = vs.PrivValidator.SignVote(config.ChainID(), v) + vote.Signature = v.Signature - err = vs.PrivValidator.SignVote(config.ChainID(), vote) return vote, err } @@ -200,9 +202,13 @@ func decideProposal( // Make proposal polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()} proposal = types.NewProposal(height, round, polRound, propBlockID) - if err := vs.SignProposal(chainID, proposal); err != nil { + p := proposal.ToProto() + if err := vs.SignProposal(chainID, p); err != nil { panic(err) } + + proposal.Signature = p.Signature + return } diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 7b4df25b0..01156e8ce 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -360,10 +360,13 @@ func TestSimulateValidatorsChange(t *testing.T) { propBlock, _ := css[0].createProposalBlock() //changeProposer(t, cs1, vs2) propBlockParts := propBlock.MakePartSet(partSize) blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} + proposal := types.NewProposal(vss[1].Height, round, -1, blockID) - if err := vss[1].SignProposal(config.ChainID(), proposal); err != nil { + p := proposal.ToProto() + if err := vss[1].SignProposal(config.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } + proposal.Signature = p.Signature // set the proposal block if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -389,10 +392,13 @@ func TestSimulateValidatorsChange(t *testing.T) { propBlock, _ = css[0].createProposalBlock() //changeProposer(t, cs1, vs2) propBlockParts = propBlock.MakePartSet(partSize) blockID = types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} + proposal = types.NewProposal(vss[2].Height, round, -1, blockID) - if err := vss[2].SignProposal(config.ChainID(), proposal); err != nil { + p = proposal.ToProto() + if err := vss[2].SignProposal(config.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } + proposal.Signature = p.Signature // set the proposal block if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -447,9 +453,11 @@ func TestSimulateValidatorsChange(t *testing.T) { selfIndex := valIndexFn(0) proposal = types.NewProposal(vss[3].Height, round, -1, blockID) - if err := vss[3].SignProposal(config.ChainID(), proposal); err != nil { + p = proposal.ToProto() + if err := vss[3].SignProposal(config.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } + proposal.Signature = p.Signature // set the proposal block if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -508,9 +516,11 @@ func TestSimulateValidatorsChange(t *testing.T) { selfIndex = valIndexFn(0) proposal = types.NewProposal(vss[1].Height, round, -1, blockID) - if err := vss[1].SignProposal(config.ChainID(), proposal); err != nil { + p = proposal.ToProto() + if err := vss[1].SignProposal(config.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } + proposal.Signature = p.Signature // set the proposal block if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { diff --git a/consensus/state.go b/consensus/state.go index 51e44e99d..6b446db7e 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1032,7 +1032,9 @@ func (cs *State) defaultDecideProposal(height int64, round int32) { // Make proposal propBlockID := types.BlockID{Hash: block.Hash(), PartsHeader: blockParts.Header()} proposal := types.NewProposal(height, round, cs.ValidRound, propBlockID) - if err := cs.privValidator.SignProposal(cs.state.ChainID, proposal); err == nil { + p := proposal.ToProto() + if err := cs.privValidator.SignProposal(cs.state.ChainID, p); err == nil { + proposal.Signature = p.Signature // send proposal and block parts on internal msg queue cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) @@ -1683,11 +1685,13 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error { return ErrInvalidProposalPOLRound } + p := proposal.ToProto() // Verify signature - if !cs.Validators.GetProposer().PubKey.VerifyBytes(proposal.SignBytes(cs.state.ChainID), proposal.Signature) { + if !cs.Validators.GetProposer().PubKey.VerifyBytes(types.ProposalSignBytes(cs.state.ChainID, p), proposal.Signature) { return ErrInvalidProposalSignature } + proposal.Signature = p.Signature cs.Proposal = proposal // We don't update cs.ProposalBlockParts if it is already set. // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. @@ -2008,8 +2012,10 @@ func (cs *State) signVote( Type: msgType, BlockID: types.BlockID{Hash: hash, PartsHeader: header}, } + v := vote.ToProto() + err = cs.privValidator.SignVote(cs.state.ChainID, v) + vote.Signature = v.Signature - err = cs.privValidator.SignVote(cs.state.ChainID, vote) return vote, err } diff --git a/consensus/state_test.go b/consensus/state_test.go index 52d235190..d053fc005 100644 --- a/consensus/state_test.go +++ b/consensus/state_test.go @@ -205,10 +205,13 @@ func TestStateBadProposal(t *testing.T) { propBlockParts := propBlock.MakePartSet(partSize) blockID := types.BlockID{Hash: propBlock.Hash(), PartsHeader: propBlockParts.Header()} proposal := types.NewProposal(vs2.Height, round, -1, blockID) - if err := vs2.SignProposal(config.ChainID(), proposal); err != nil { + p := proposal.ToProto() + if err := vs2.SignProposal(config.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } + proposal.Signature = p.Signature + // set the proposal block if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { t.Fatal(err) @@ -1034,9 +1037,13 @@ func TestStateLockPOLSafety2(t *testing.T) { round++ // moving to the next round // in round 2 we see the polkad block from round 0 newProp := types.NewProposal(height, round, 0, propBlockID0) - if err := vs3.SignProposal(config.ChainID(), newProp); err != nil { + p := newProp.ToProto() + if err := vs3.SignProposal(config.ChainID(), p); err != nil { t.Fatal(err) } + + newProp.Signature = p.Signature + if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil { t.Fatal(err) } diff --git a/consensus/types/height_vote_set_test.go b/consensus/types/height_vote_set_test.go index 20174bbd7..4abcac9df 100644 --- a/consensus/types/height_vote_set_test.go +++ b/consensus/types/height_vote_set_test.go @@ -70,9 +70,14 @@ func makeVoteHR(t *testing.T, height int64, valIndex, round int32, privVals []ty BlockID: types.BlockID{Hash: []byte("fakehash"), PartsHeader: types.PartSetHeader{}}, } chainID := config.ChainID() - err = privVal.SignVote(chainID, vote) + + v := vote.ToProto() + err = privVal.SignVote(chainID, v) if err != nil { panic(fmt.Sprintf("Error signing vote: %v", err)) } + + vote.Signature = v.Signature + return vote } diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index 504da8783..8d86083b1 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -150,6 +150,7 @@ func (pubKey PubKey) VerifyBytes(msg []byte, sig []byte) bool { if len(sig) != SignatureSize { return false } + return ed25519.Verify(ed25519.PublicKey(pubKey), msg, sig) } diff --git a/evidence/pool_test.go b/evidence/pool_test.go index 666b4e8e8..d028c657b 100644 --- a/evidence/pool_test.go +++ b/evidence/pool_test.go @@ -331,14 +331,20 @@ func TestPotentialAmnesiaEvidence(t *testing.T) { require.NoError(t, err) voteA := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) - err = val.SignVote(evidenceChainID, voteA) + vA := voteA.ToProto() + err = val.SignVote(evidenceChainID, vA) + voteA.Signature = vA.Signature require.NoError(t, err) voteB := makeVote(25, 1, 0, pubKey.Address(), secondBlockID) - err = val.SignVote(evidenceChainID, voteB) + vB := voteB.ToProto() + err = val.SignVote(evidenceChainID, vB) + voteB.Signature = vB.Signature require.NoError(t, err) voteC := makeVote(25, 0, 0, pubKey.Address(), firstBlockID) voteC.Timestamp.Add(1 * time.Second) - err = val.SignVote(evidenceChainID, voteC) + vC := voteC.ToProto() + err = val.SignVote(evidenceChainID, vC) + voteC.Signature = vC.Signature require.NoError(t, err) ev := types.PotentialAmnesiaEvidence{ VoteA: voteA, diff --git a/libs/math/safemath.go b/libs/math/safemath.go index 2c59c191c..ff7f0908f 100644 --- a/libs/math/safemath.go +++ b/libs/math/safemath.go @@ -7,6 +7,7 @@ import ( var ErrOverflowInt32 = errors.New("int32 overflow") var ErrOverflowUint8 = errors.New("uint8 overflow") +var ErrOverflowInt8 = errors.New("int8 overflow") // SafeAddInt32 adds two int32 integers // If there is an overflow this will panic @@ -51,3 +52,14 @@ func SafeConvertUint8(a int64) (uint8, error) { } return uint8(a), nil } + +// SafeConvertInt8 takes an int64 and checks if it overflows +// If there is an overflow it returns an error +func SafeConvertInt8(a int64) (int8, error) { + if a > math.MaxInt8 { + return 0, ErrOverflowInt8 + } else if a < math.MinInt8 { + return 0, ErrOverflowInt8 + } + return int8(a), nil +} diff --git a/light/helpers_test.go b/light/helpers_test.go index bb3a804b0..7348ca601 100644 --- a/light/helpers_test.go +++ b/light/helpers_test.go @@ -108,13 +108,15 @@ func makeVote(header *types.Header, valset *types.ValidatorSet, Type: tmproto.PrecommitType, BlockID: blockID, } + + v := vote.ToProto() // Sign it - signBytes := vote.SignBytes(header.ChainID) - // TODO Consider reworking makeVote API to return an error + signBytes := types.VoteSignBytes(header.ChainID, v) sig, err := key.Sign(signBytes) if err != nil { panic(err) } + vote.Signature = sig return vote diff --git a/privval/codec.go b/privval/codec.go deleted file mode 100644 index d1f2eafa2..000000000 --- a/privval/codec.go +++ /dev/null @@ -1,14 +0,0 @@ -package privval - -import ( - amino "github.com/tendermint/go-amino" - - cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino" -) - -var cdc = amino.NewCodec() - -func init() { - cryptoamino.RegisterAmino(cdc) - RegisterRemoteSignerMsg(cdc) -} diff --git a/privval/errors.go b/privval/errors.go index 9f151f11d..d77082305 100644 --- a/privval/errors.go +++ b/privval/errors.go @@ -1,6 +1,7 @@ package privval import ( + "errors" "fmt" ) @@ -13,12 +14,12 @@ func (e EndpointTimeoutError) Temporary() bool { return true } // Socket errors. var ( - ErrUnexpectedResponse = fmt.Errorf("received unexpected response") - ErrNoConnection = fmt.Errorf("endpoint is not connected") + ErrUnexpectedResponse = errors.New("received unexpected response") + ErrNoConnection = errors.New("endpoint is not connected") ErrConnectionTimeout = EndpointTimeoutError{} - ErrReadTimeout = fmt.Errorf("endpoint read timed out") - ErrWriteTimeout = fmt.Errorf("endpoint write timed out") + ErrReadTimeout = errors.New("endpoint read timed out") + ErrWriteTimeout = errors.New("endpoint write timed out") ) // RemoteSignerError allows (remote) validators to include meaningful error descriptions in their reply. diff --git a/privval/file.go b/privval/file.go index 06c0073de..d870ccbbf 100644 --- a/privval/file.go +++ b/privval/file.go @@ -7,6 +7,8 @@ import ( "io/ioutil" "time" + "github.com/gogo/protobuf/proto" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" tmbytes "github.com/tendermint/tendermint/libs/bytes" @@ -27,7 +29,7 @@ const ( ) // A vote is either stepPrevote or stepPrecommit. -func voteToStep(vote *types.Vote) int8 { +func voteToStep(vote *tmproto.Vote) int8 { switch vote.Type { case tmproto.PrevoteType: return stepPrevote @@ -199,6 +201,7 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) *FilePV { pvKey.filePath = keyFilePath pvState := FilePVLastSignState{} + if loadState { stateJSONBytes, err := ioutil.ReadFile(stateFilePath) if err != nil { @@ -245,7 +248,7 @@ func (pv *FilePV) GetPubKey() (crypto.PubKey, error) { // SignVote signs a canonical representation of the vote, along with the // chainID. Implements PrivValidator. -func (pv *FilePV) SignVote(chainID string, vote *types.Vote) error { +func (pv *FilePV) SignVote(chainID string, vote *tmproto.Vote) error { if err := pv.signVote(chainID, vote); err != nil { return fmt.Errorf("error signing vote: %v", err) } @@ -254,7 +257,7 @@ func (pv *FilePV) SignVote(chainID string, vote *types.Vote) error { // SignProposal signs a canonical representation of the proposal, along with // the chainID. Implements PrivValidator. -func (pv *FilePV) SignProposal(chainID string, proposal *types.Proposal) error { +func (pv *FilePV) SignProposal(chainID string, proposal *tmproto.Proposal) error { if err := pv.signProposal(chainID, proposal); err != nil { return fmt.Errorf("error signing proposal: %v", err) } @@ -295,7 +298,7 @@ func (pv *FilePV) String() string { // signVote checks if the vote is good to sign and sets the vote signature. // It may need to set the timestamp as well if the vote is otherwise the same as // a previously signed vote (ie. we crashed after signing but before the vote hit the WAL). -func (pv *FilePV) signVote(chainID string, vote *types.Vote) error { +func (pv *FilePV) signVote(chainID string, vote *tmproto.Vote) error { height, round, step := vote.Height, vote.Round, voteToStep(vote) lss := pv.LastSignState @@ -305,7 +308,7 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error { return err } - signBytes := vote.SignBytes(chainID) + signBytes := types.VoteSignBytes(chainID, vote) // We might crash before writing to the wal, // causing us to try to re-sign for the same HRS. @@ -337,7 +340,7 @@ func (pv *FilePV) signVote(chainID string, vote *types.Vote) error { // signProposal checks if the proposal is good to sign and sets the proposal signature. // It may need to set the timestamp as well if the proposal is otherwise the same as // a previously signed proposal ie. we crashed after signing but before the proposal hit the WAL). -func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error { +func (pv *FilePV) signProposal(chainID string, proposal *tmproto.Proposal) error { height, round, step := proposal.Height, proposal.Round, stepPropose lss := pv.LastSignState @@ -347,7 +350,7 @@ func (pv *FilePV) signProposal(chainID string, proposal *types.Proposal) error { return err } - signBytes := proposal.SignBytes(chainID) + signBytes := types.ProposalSignBytes(chainID, proposal) // We might crash before writing to the wal, // causing us to try to re-sign for the same HRS. @@ -393,11 +396,11 @@ func (pv *FilePV) saveSigned(height int64, round int32, step int8, // returns the timestamp from the lastSignBytes. // returns true if the only difference in the votes is their timestamp. func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { - var lastVote, newVote types.CanonicalVote - if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastVote); err != nil { + var lastVote, newVote tmproto.CanonicalVote + if err := proto.Unmarshal(lastSignBytes, &lastVote); err != nil { panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into vote: %v", err)) } - if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newVote); err != nil { + if err := proto.Unmarshal(newSignBytes, &newVote); err != nil { panic(fmt.Sprintf("signBytes cannot be unmarshalled into vote: %v", err)) } @@ -407,20 +410,18 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T now := tmtime.Now() lastVote.Timestamp = now newVote.Timestamp = now - lastVoteBytes, _ := tmjson.Marshal(lastVote) - newVoteBytes, _ := tmjson.Marshal(newVote) - return lastTime, bytes.Equal(newVoteBytes, lastVoteBytes) + return lastTime, proto.Equal(&newVote, &lastVote) } // returns the timestamp from the lastSignBytes. // returns true if the only difference in the proposals is their timestamp func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { - var lastProposal, newProposal types.CanonicalProposal - if err := cdc.UnmarshalBinaryLengthPrefixed(lastSignBytes, &lastProposal); err != nil { + var lastProposal, newProposal tmproto.CanonicalProposal + if err := proto.Unmarshal(lastSignBytes, &lastProposal); err != nil { panic(fmt.Sprintf("LastSignBytes cannot be unmarshalled into proposal: %v", err)) } - if err := cdc.UnmarshalBinaryLengthPrefixed(newSignBytes, &newProposal); err != nil { + if err := proto.Unmarshal(newSignBytes, &newProposal); err != nil { panic(fmt.Sprintf("signBytes cannot be unmarshalled into proposal: %v", err)) } @@ -429,8 +430,6 @@ func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (ti now := tmtime.Now() lastProposal.Timestamp = now newProposal.Timestamp = now - lastProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(lastProposal) - newProposalBytes, _ := cdc.MarshalBinaryLengthPrefixed(newProposal) - return lastTime, bytes.Equal(newProposalBytes, lastProposalBytes) + return lastTime, proto.Equal(&newProposal, &lastProposal) } diff --git a/privval/file_test.go b/privval/file_test.go index 540e952a5..cb6f5819f 100644 --- a/privval/file_test.go +++ b/privval/file_test.go @@ -52,10 +52,10 @@ func TestResetValidator(t *testing.T) { // test vote height, round := int64(10), int32(1) - voteType := byte(tmproto.PrevoteType) + voteType := tmproto.PrevoteType blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) - err = privVal.SignVote("mychainid", vote) + err = privVal.SignVote("mychainid", vote.ToProto()) assert.NoError(t, err, "expected no error signing vote") // priv val after signing is not same as empty @@ -121,8 +121,8 @@ func TestUnmarshalValidatorKey(t *testing.T) { privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() addr := pubKey.Address() - pubBytes := []byte(pubKey.(ed25519.PubKey)) - privBytes := []byte(privKey) + pubBytes := pubKey.Bytes() + privBytes := privKey.Bytes() pubB64 := base64.StdEncoding.EncodeToString(pubBytes) privB64 := base64.StdEncoding.EncodeToString(privBytes) @@ -167,15 +167,16 @@ func TestSignVote(t *testing.T) { block2 := types.BlockID{Hash: []byte{3, 2, 1}, PartsHeader: types.PartSetHeader{}} height, round := int64(10), int32(1) - voteType := byte(tmproto.PrevoteType) + voteType := tmproto.PrevoteType // sign a vote for first time vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1) - err = privVal.SignVote("mychainid", vote) + v := vote.ToProto() + err = privVal.SignVote("mychainid", v) assert.NoError(err, "expected no error signing vote") // try to sign the same vote again; should be fine - err = privVal.SignVote("mychainid", vote) + err = privVal.SignVote("mychainid", v) assert.NoError(err, "expected no error on signing same vote") // now try some bad votes @@ -187,14 +188,15 @@ func TestSignVote(t *testing.T) { } for _, c := range cases { - err = privVal.SignVote("mychainid", c) + cpb := c.ToProto() + err = privVal.SignVote("mychainid", cpb) assert.Error(err, "expected error on signing conflicting vote") } // try signing a vote with a different time stamp sig := vote.Signature vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) - err = privVal.SignVote("mychainid", vote) + err = privVal.SignVote("mychainid", v) assert.NoError(err) assert.Equal(sig, vote.Signature) } @@ -215,11 +217,12 @@ func TestSignProposal(t *testing.T) { // sign a proposal for first time proposal := newProposal(height, round, block1) - err = privVal.SignProposal("mychainid", proposal) + pbp := proposal.ToProto() + err = privVal.SignProposal("mychainid", pbp) assert.NoError(err, "expected no error signing proposal") // try to sign the same proposal again; should be fine - err = privVal.SignProposal("mychainid", proposal) + err = privVal.SignProposal("mychainid", pbp) assert.NoError(err, "expected no error on signing same proposal") // now try some bad Proposals @@ -231,14 +234,14 @@ func TestSignProposal(t *testing.T) { } for _, c := range cases { - err = privVal.SignProposal("mychainid", c) + err = privVal.SignProposal("mychainid", c.ToProto()) assert.Error(err, "expected error on signing conflicting proposal") } // try signing a proposal with a different time stamp sig := proposal.Signature proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) - err = privVal.SignProposal("mychainid", proposal) + err = privVal.SignProposal("mychainid", pbp) assert.NoError(err) assert.Equal(sig, proposal.Signature) } @@ -258,56 +261,60 @@ func TestDifferByTimestamp(t *testing.T) { // test proposal { proposal := newProposal(height, round, block1) - err := privVal.SignProposal(chainID, proposal) + pb := proposal.ToProto() + err := privVal.SignProposal(chainID, pb) assert.NoError(t, err, "expected no error signing proposal") - signBytes := proposal.SignBytes(chainID) + signBytes := types.ProposalSignBytes(chainID, pb) + sig := proposal.Signature timeStamp := proposal.Timestamp // manipulate the timestamp. should get changed back - proposal.Timestamp = proposal.Timestamp.Add(time.Millisecond) + pb.Timestamp = pb.Timestamp.Add(time.Millisecond) var emptySig []byte proposal.Signature = emptySig - err = privVal.SignProposal("mychainid", proposal) + err = privVal.SignProposal("mychainid", pb) assert.NoError(t, err, "expected no error on signing same proposal") - assert.Equal(t, timeStamp, proposal.Timestamp) - assert.Equal(t, signBytes, proposal.SignBytes(chainID)) + assert.Equal(t, timeStamp, pb.Timestamp) + assert.Equal(t, signBytes, types.ProposalSignBytes(chainID, pb)) assert.Equal(t, sig, proposal.Signature) } // test vote { - voteType := byte(tmproto.PrevoteType) + voteType := tmproto.PrevoteType blockID := types.BlockID{Hash: []byte{1, 2, 3}, PartsHeader: types.PartSetHeader{}} vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) - err := privVal.SignVote("mychainid", vote) + v := vote.ToProto() + err := privVal.SignVote("mychainid", v) assert.NoError(t, err, "expected no error signing vote") - signBytes := vote.SignBytes(chainID) - sig := vote.Signature + signBytes := types.VoteSignBytes(chainID, v) + sig := v.Signature timeStamp := vote.Timestamp // manipulate the timestamp. should get changed back - vote.Timestamp = vote.Timestamp.Add(time.Millisecond) + v.Timestamp = v.Timestamp.Add(time.Millisecond) var emptySig []byte - vote.Signature = emptySig - err = privVal.SignVote("mychainid", vote) + v.Signature = emptySig + err = privVal.SignVote("mychainid", v) assert.NoError(t, err, "expected no error on signing same vote") - assert.Equal(t, timeStamp, vote.Timestamp) - assert.Equal(t, signBytes, vote.SignBytes(chainID)) - assert.Equal(t, sig, vote.Signature) + assert.Equal(t, timeStamp, v.Timestamp) + assert.Equal(t, signBytes, types.VoteSignBytes(chainID, v)) + assert.Equal(t, sig, v.Signature) } } -func newVote(addr types.Address, idx int32, height int64, round int32, typ byte, blockID types.BlockID) *types.Vote { +func newVote(addr types.Address, idx int32, height int64, round int32, + typ tmproto.SignedMsgType, blockID types.BlockID) *types.Vote { return &types.Vote{ ValidatorAddress: addr, ValidatorIndex: idx, Height: height, Round: round, - Type: tmproto.SignedMsgType(typ), + Type: typ, Timestamp: tmtime.Now(), BlockID: blockID, } diff --git a/privval/messages.go b/privval/messages.go index fa7a0b09d..675051a8a 100644 --- a/privval/messages.go +++ b/privval/messages.go @@ -1,65 +1,40 @@ package privval import ( - amino "github.com/tendermint/go-amino" + "fmt" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/types" + "github.com/gogo/protobuf/proto" + + privvalproto "github.com/tendermint/tendermint/proto/privval" ) -// SignerMessage is sent between Signer Clients and Servers. -type SignerMessage interface{} - -func RegisterRemoteSignerMsg(cdc *amino.Codec) { - cdc.RegisterInterface((*SignerMessage)(nil), nil) - cdc.RegisterConcrete(&PubKeyRequest{}, "tendermint/remotesigner/PubKeyRequest", nil) - cdc.RegisterConcrete(&PubKeyResponse{}, "tendermint/remotesigner/PubKeyResponse", nil) - cdc.RegisterConcrete(&SignVoteRequest{}, "tendermint/remotesigner/SignVoteRequest", nil) - cdc.RegisterConcrete(&SignedVoteResponse{}, "tendermint/remotesigner/SignedVoteResponse", nil) - cdc.RegisterConcrete(&SignProposalRequest{}, "tendermint/remotesigner/SignProposalRequest", nil) - cdc.RegisterConcrete(&SignedProposalResponse{}, "tendermint/remotesigner/SignedProposalResponse", nil) - - cdc.RegisterConcrete(&PingRequest{}, "tendermint/remotesigner/PingRequest", nil) - cdc.RegisterConcrete(&PingResponse{}, "tendermint/remotesigner/PingResponse", nil) -} - // TODO: Add ChainIDRequest -// PubKeyRequest requests the consensus public key from the remote signer. -type PubKeyRequest struct{} +func mustWrapMsg(pb proto.Message) privvalproto.Message { + msg := privvalproto.Message{} -// PubKeyResponse is a response message containing the public key. -type PubKeyResponse struct { - PubKey crypto.PubKey - Error *RemoteSignerError -} + switch pb := pb.(type) { + case *privvalproto.Message: + msg = *pb + case *privvalproto.PubKeyRequest: + msg.Sum = &privvalproto.Message_PubKeyRequest{PubKeyRequest: pb} + case *privvalproto.PubKeyResponse: + msg.Sum = &privvalproto.Message_PubKeyResponse{PubKeyResponse: pb} + case *privvalproto.SignVoteRequest: + msg.Sum = &privvalproto.Message_SignVoteRequest{SignVoteRequest: pb} + case *privvalproto.SignedVoteResponse: + msg.Sum = &privvalproto.Message_SignedVoteResponse{SignedVoteResponse: pb} + case *privvalproto.SignedProposalResponse: + msg.Sum = &privvalproto.Message_SignedProposalResponse{SignedProposalResponse: pb} + case *privvalproto.SignProposalRequest: + msg.Sum = &privvalproto.Message_SignProposalRequest{SignProposalRequest: pb} + case *privvalproto.PingRequest: + msg.Sum = &privvalproto.Message_PingRequest{} + case *privvalproto.PingResponse: + msg.Sum = &privvalproto.Message_PingResponse{} + default: + panic(fmt.Errorf("unknown message type %T", msg)) + } -// SignVoteRequest is a request to sign a vote -type SignVoteRequest struct { - Vote *types.Vote -} - -// SignedVoteResponse is a response containing a signed vote or an error -type SignedVoteResponse struct { - Vote *types.Vote - Error *RemoteSignerError -} - -// SignProposalRequest is a request to sign a proposal -type SignProposalRequest struct { - Proposal *types.Proposal -} - -// SignedProposalResponse is response containing a signed proposal or an error -type SignedProposalResponse struct { - Proposal *types.Proposal - Error *RemoteSignerError -} - -// PingRequest is a request to confirm that the connection is alive. -type PingRequest struct { -} - -// PingResponse is a response to confirm that the connection is alive. -type PingResponse struct { + return msg } diff --git a/privval/retry_signer_client.go b/privval/retry_signer_client.go index d2cde8741..7f0077e32 100644 --- a/privval/retry_signer_client.go +++ b/privval/retry_signer_client.go @@ -5,6 +5,7 @@ import ( "time" "github.com/tendermint/tendermint/crypto" + tmproto "github.com/tendermint/tendermint/proto/types" "github.com/tendermint/tendermint/types" ) @@ -58,7 +59,7 @@ func (sc *RetrySignerClient) GetPubKey() (crypto.PubKey, error) { return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) } -func (sc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error { +func (sc *RetrySignerClient) SignVote(chainID string, vote *tmproto.Vote) error { var err error for i := 0; i < sc.retries || sc.retries == 0; i++ { err = sc.next.SignVote(chainID, vote) @@ -70,7 +71,7 @@ func (sc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error { return fmt.Errorf("exhausted all attempts to sign vote: %w", err) } -func (sc *RetrySignerClient) SignProposal(chainID string, proposal *types.Proposal) error { +func (sc *RetrySignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error { var err error for i := 0; i < sc.retries || sc.retries == 0; i++ { err = sc.next.SignProposal(chainID, proposal) diff --git a/privval/signer_client.go b/privval/signer_client.go index 41908cb0e..f27203ef5 100644 --- a/privval/signer_client.go +++ b/privval/signer_client.go @@ -1,10 +1,14 @@ package privval import ( + "errors" "fmt" "time" "github.com/tendermint/tendermint/crypto" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" + privvalproto "github.com/tendermint/tendermint/proto/privval" + tmproto "github.com/tendermint/tendermint/proto/types" "github.com/tendermint/tendermint/types" ) @@ -48,15 +52,15 @@ func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error { // Ping sends a ping request to the remote signer func (sc *SignerClient) Ping() error { - response, err := sc.endpoint.SendRequest(&PingRequest{}) + response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PingRequest{})) if err != nil { sc.endpoint.Logger.Error("SignerClient::Ping", "err", err) return nil } - _, ok := response.(*PingResponse) - if !ok { + pb := response.GetPingResponse() + if pb == nil { sc.endpoint.Logger.Error("SignerClient::Ping", "err", "response != PingResponse") return err } @@ -67,64 +71,73 @@ func (sc *SignerClient) Ping() error { // GetPubKey retrieves a public key from a remote signer // returns an error if client is not able to provide the key func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { - response, err := sc.endpoint.SendRequest(&PubKeyRequest{}) + response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{})) if err != nil { sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", err) return nil, fmt.Errorf("send: %w", err) } - pubKeyResp, ok := response.(*PubKeyResponse) - if !ok { + pubKeyResp := response.GetPubKeyResponse() + if pubKeyResp == nil { sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != PubKeyResponse") return nil, fmt.Errorf("unexpected response type %T", response) } if pubKeyResp.Error != nil { sc.endpoint.Logger.Error("failed to get private validator's public key", "err", pubKeyResp.Error) - return nil, fmt.Errorf("remote error: %w", pubKeyResp.Error) + return nil, fmt.Errorf("remote error: %w", errors.New(pubKeyResp.Error.Description)) } - return pubKeyResp.PubKey, nil + pk, err := cryptoenc.PubKeyFromProto(*pubKeyResp.PubKey) + if err != nil { + return nil, err + } + + return pk, nil } // SignVote requests a remote signer to sign a vote -func (sc *SignerClient) SignVote(chainID string, vote *types.Vote) error { - response, err := sc.endpoint.SendRequest(&SignVoteRequest{Vote: vote}) +func (sc *SignerClient) SignVote(chainID string, vote *tmproto.Vote) error { + + response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote})) if err != nil { sc.endpoint.Logger.Error("SignerClient::SignVote", "err", err) return err } - resp, ok := response.(*SignedVoteResponse) - if !ok { + resp := response.GetSignedVoteResponse() + if resp == nil { sc.endpoint.Logger.Error("SignerClient::GetPubKey", "err", "response != SignedVoteResponse") return ErrUnexpectedResponse } if resp.Error != nil { - return resp.Error + return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} } + *vote = *resp.Vote return nil } // SignProposal requests a remote signer to sign a proposal -func (sc *SignerClient) SignProposal(chainID string, proposal *types.Proposal) error { - response, err := sc.endpoint.SendRequest(&SignProposalRequest{Proposal: proposal}) +func (sc *SignerClient) SignProposal(chainID string, proposal *tmproto.Proposal) error { + + response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignProposalRequest{Proposal: *proposal})) if err != nil { sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", err) return err } - resp, ok := response.(*SignedProposalResponse) - if !ok { + resp := response.GetSignedProposalResponse() + if resp == nil { sc.endpoint.Logger.Error("SignerClient::SignProposal", "err", "response != SignedProposalResponse") return ErrUnexpectedResponse } if resp.Error != nil { - return resp.Error + return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} } + *proposal = *resp.Proposal return nil diff --git a/privval/signer_client_test.go b/privval/signer_client_test.go index d13d2e057..f0a2be9f2 100644 --- a/privval/signer_client_test.go +++ b/privval/signer_client_test.go @@ -8,7 +8,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/tmhash" tmrand "github.com/tendermint/tendermint/libs/rand" + privvalproto "github.com/tendermint/tendermint/proto/privval" tmproto "github.com/tendermint/tendermint/proto/types" "github.com/tendermint/tendermint/types" ) @@ -95,14 +98,29 @@ func TestSignerGetPubKey(t *testing.T) { func TestSignerProposal(t *testing.T) { for _, tc := range getSignerTestCases(t) { ts := time.Now() - want := &types.Proposal{Timestamp: ts} - have := &types.Proposal{Timestamp: ts} + hash := tmrand.Bytes(tmhash.Size) + have := &types.Proposal{ + Type: tmproto.ProposalType, + Height: 1, + Round: 2, + POLRound: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + } + want := &types.Proposal{ + Type: tmproto.ProposalType, + Height: 1, + Round: 2, + POLRound: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + } defer tc.signerServer.Stop() defer tc.signerClient.Close() - require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want)) - require.NoError(t, tc.signerClient.SignProposal(tc.chainID, have)) + require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want.ToProto())) + require.NoError(t, tc.signerClient.SignProposal(tc.chainID, have.ToProto())) assert.Equal(t, want.Signature, have.Signature) } @@ -111,14 +129,33 @@ func TestSignerProposal(t *testing.T) { func TestSignerVote(t *testing.T) { for _, tc := range getSignerTestCases(t) { ts := time.Now() - want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} - have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} + hash := tmrand.Bytes(tmhash.Size) + valAddr := tmrand.Bytes(crypto.AddressSize) + want := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } + + have := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } defer tc.signerServer.Stop() defer tc.signerClient.Close() - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want)) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have)) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) assert.Equal(t, want.Signature, have.Signature) } @@ -127,16 +164,35 @@ func TestSignerVote(t *testing.T) { func TestSignerVoteResetDeadline(t *testing.T) { for _, tc := range getSignerTestCases(t) { ts := time.Now() - want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} - have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} + hash := tmrand.Bytes(tmhash.Size) + valAddr := tmrand.Bytes(crypto.AddressSize) + want := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } + + have := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } defer tc.signerServer.Stop() defer tc.signerClient.Close() time.Sleep(testTimeoutReadWrite2o3) - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want)) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have)) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) assert.Equal(t, want.Signature, have.Signature) // TODO(jleni): Clarify what is actually being tested @@ -144,8 +200,8 @@ func TestSignerVoteResetDeadline(t *testing.T) { // This would exceed the deadline if it was not extended by the previous message time.Sleep(testTimeoutReadWrite2o3) - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want)) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have)) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) assert.Equal(t, want.Signature, have.Signature) } } @@ -153,8 +209,27 @@ func TestSignerVoteResetDeadline(t *testing.T) { func TestSignerVoteKeepAlive(t *testing.T) { for _, tc := range getSignerTestCases(t) { ts := time.Now() - want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} - have := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} + hash := tmrand.Bytes(tmhash.Size) + valAddr := tmrand.Bytes(crypto.AddressSize) + want := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } + + have := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + } defer tc.signerServer.Stop() defer tc.signerClient.Close() @@ -168,8 +243,8 @@ func TestSignerVoteKeepAlive(t *testing.T) { time.Sleep(testTimeoutReadWrite * 3) tc.signerServer.Logger.Debug("TEST: Forced Wait DONE---------------------------------------------") - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want)) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have)) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) assert.Equal(t, want.Signature, have.Signature) } @@ -185,14 +260,24 @@ func TestSignerSignProposalErrors(t *testing.T) { defer tc.signerClient.Close() ts := time.Now() - proposal := &types.Proposal{Timestamp: ts} - err := tc.signerClient.SignProposal(tc.chainID, proposal) + hash := tmrand.Bytes(tmhash.Size) + proposal := &types.Proposal{ + Type: tmproto.ProposalType, + Height: 1, + Round: 2, + POLRound: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + Signature: []byte("signature"), + } + + err := tc.signerClient.SignProposal(tc.chainID, proposal.ToProto()) require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error()) - err = tc.mockPV.SignProposal(tc.chainID, proposal) + err = tc.mockPV.SignProposal(tc.chainID, proposal.ToProto()) require.Error(t, err) - err = tc.signerClient.SignProposal(tc.chainID, proposal) + err = tc.signerClient.SignProposal(tc.chainID, proposal.ToProto()) require.Error(t, err) } } @@ -200,7 +285,18 @@ func TestSignerSignProposalErrors(t *testing.T) { func TestSignerSignVoteErrors(t *testing.T) { for _, tc := range getSignerTestCases(t) { ts := time.Now() - vote := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} + hash := tmrand.Bytes(tmhash.Size) + valAddr := tmrand.Bytes(crypto.AddressSize) + vote := &types.Vote{ + Type: tmproto.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartsHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + Signature: []byte("signature"), + } // Replace signer service privval with one that always fails tc.signerServer.privVal = types.NewErroringMockPV() @@ -209,34 +305,32 @@ func TestSignerSignVoteErrors(t *testing.T) { defer tc.signerServer.Stop() defer tc.signerClient.Close() - err := tc.signerClient.SignVote(tc.chainID, vote) + err := tc.signerClient.SignVote(tc.chainID, vote.ToProto()) require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error()) - err = tc.mockPV.SignVote(tc.chainID, vote) + err = tc.mockPV.SignVote(tc.chainID, vote.ToProto()) require.Error(t, err) - err = tc.signerClient.SignVote(tc.chainID, vote) + err = tc.signerClient.SignVote(tc.chainID, vote.ToProto()) require.Error(t, err) } } -func brokenHandler(privVal types.PrivValidator, request SignerMessage, chainID string) (SignerMessage, error) { - var res SignerMessage +func brokenHandler(privVal types.PrivValidator, request privvalproto.Message, + chainID string) (privvalproto.Message, error) { + var res privvalproto.Message var err error - switch r := request.(type) { - + switch r := request.Sum.(type) { // This is broken and will answer most requests with a pubkey response - case *PubKeyRequest: - res = &PubKeyResponse{nil, nil} - case *SignVoteRequest: - res = &PubKeyResponse{nil, nil} - case *SignProposalRequest: - res = &PubKeyResponse{nil, nil} - - case *PingRequest: - err, res = nil, &PingResponse{} - + case *privvalproto.Message_PubKeyRequest: + res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil}) + case *privvalproto.Message_SignVoteRequest: + res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil}) + case *privvalproto.Message_SignProposalRequest: + res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: nil, Error: nil}) + case *privvalproto.Message_PingRequest: + err, res = nil, mustWrapMsg(&privvalproto.PingResponse{}) default: err = fmt.Errorf("unknown msg: %v", r) } @@ -257,7 +351,7 @@ func TestSignerUnexpectedResponse(t *testing.T) { ts := time.Now() want := &types.Vote{Timestamp: ts, Type: tmproto.PrecommitType} - e := tc.signerClient.SignVote(tc.chainID, want) + e := tc.signerClient.SignVote(tc.chainID, want.ToProto()) assert.EqualError(t, e, "received unexpected response") } } diff --git a/privval/signer_endpoint.go b/privval/signer_endpoint.go index 04b6701be..c18340465 100644 --- a/privval/signer_endpoint.go +++ b/privval/signer_endpoint.go @@ -6,7 +6,9 @@ import ( "sync" "time" + "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/libs/service" + privvalproto "github.com/tendermint/tendermint/proto/privval" ) const ( @@ -78,14 +80,13 @@ func (se *signerEndpoint) DropConnection() { } // ReadMessage reads a message from the endpoint -func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) { +func (se *signerEndpoint) ReadMessage() (msg privvalproto.Message, err error) { se.connMtx.Lock() defer se.connMtx.Unlock() if !se.isConnected() { - return nil, fmt.Errorf("endpoint is not connected") + return msg, fmt.Errorf("endpoint is not connected: %w", ErrNoConnection) } - // Reset read deadline deadline := time.Now().Add(se.timeoutReadWrite) @@ -93,15 +94,16 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) { if err != nil { return } - const maxRemoteSignerMsgSize = 1024 * 10 - _, err = cdc.UnmarshalBinaryLengthPrefixedReader(se.conn, &msg, maxRemoteSignerMsgSize) + protoReader := protoio.NewDelimitedReader(se.conn, maxRemoteSignerMsgSize) + err = protoReader.ReadMsg(&msg) if _, ok := err.(timeoutError); ok { if err != nil { err = fmt.Errorf("%v: %w", err, ErrReadTimeout) } else { err = fmt.Errorf("empty error: %w", ErrReadTimeout) } + se.Logger.Debug("Dropping [read]", "obj", se) se.dropConnection() } @@ -110,7 +112,7 @@ func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) { } // WriteMessage writes a message from the endpoint -func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) { +func (se *signerEndpoint) WriteMessage(msg privvalproto.Message) (err error) { se.connMtx.Lock() defer se.connMtx.Unlock() @@ -118,6 +120,8 @@ func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) { return fmt.Errorf("endpoint is not connected: %w", ErrNoConnection) } + protoWriter := protoio.NewDelimitedWriter(se.conn) + // Reset read deadline deadline := time.Now().Add(se.timeoutReadWrite) err = se.conn.SetWriteDeadline(deadline) @@ -125,7 +129,7 @@ func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) { return } - _, err = cdc.MarshalBinaryLengthPrefixedWriter(se.conn, msg) + _, err = protoWriter.WriteMsg(&msg) if _, ok := err.(timeoutError); ok { if err != nil { err = fmt.Errorf("%v: %w", err, ErrWriteTimeout) diff --git a/privval/signer_listener_endpoint.go b/privval/signer_listener_endpoint.go index 70a23181d..fdda05cc3 100644 --- a/privval/signer_listener_endpoint.go +++ b/privval/signer_listener_endpoint.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" + privvalproto "github.com/tendermint/tendermint/proto/privval" ) // SignerValidatorEndpointOption sets an optional parameter on the SocketVal. @@ -83,7 +84,7 @@ func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error } // SendRequest ensures there is a connection, sends a request and waits for a response -func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMessage, error) { +func (sl *SignerListenerEndpoint) SendRequest(request privvalproto.Message) (*privvalproto.Message, error) { sl.instanceMtx.Lock() defer sl.instanceMtx.Unlock() @@ -102,7 +103,7 @@ func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMess return nil, err } - return res, nil + return &res, nil } func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error { @@ -185,7 +186,7 @@ func (sl *SignerListenerEndpoint) pingLoop() { select { case <-sl.pingTimer.C: { - _, err := sl.SendRequest(&PingRequest{}) + _, err := sl.SendRequest(mustWrapMsg(&privvalproto.PingRequest{})) if err != nil { sl.Logger.Error("SignerListener: Ping timeout") sl.triggerReconnect() diff --git a/privval/signer_requestHandler.go b/privval/signer_requestHandler.go index c658abdfd..b51a1296f 100644 --- a/privval/signer_requestHandler.go +++ b/privval/signer_requestHandler.go @@ -4,45 +4,60 @@ import ( "fmt" "github.com/tendermint/tendermint/crypto" + cryptoenc "github.com/tendermint/tendermint/crypto/encoding" + privvalproto "github.com/tendermint/tendermint/proto/privval" "github.com/tendermint/tendermint/types" ) func DefaultValidationRequestHandler( privVal types.PrivValidator, - req SignerMessage, + req privvalproto.Message, chainID string, -) (SignerMessage, error) { - var res SignerMessage - var err error +) (privvalproto.Message, error) { + var ( + res privvalproto.Message + err error + ) - switch r := req.(type) { - case *PubKeyRequest: + switch r := req.Sum.(type) { + case *privvalproto.Message_PubKeyRequest: var pubKey crypto.PubKey pubKey, err = privVal.GetPubKey() + pk, err := cryptoenc.PubKeyToProto(pubKey) if err != nil { - res = &PubKeyResponse{nil, &RemoteSignerError{0, err.Error()}} - } else { - res = &PubKeyResponse{pubKey, nil} + return res, err } - case *SignVoteRequest: - err = privVal.SignVote(chainID, r.Vote) if err != nil { - res = &SignedVoteResponse{nil, &RemoteSignerError{0, err.Error()}} + res = mustWrapMsg(&privvalproto.PubKeyResponse{ + PubKey: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) } else { - res = &SignedVoteResponse{r.Vote, nil} + res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: &pk, Error: nil}) } - case *SignProposalRequest: - err = privVal.SignProposal(chainID, r.Proposal) + case *privvalproto.Message_SignVoteRequest: + vote := r.SignVoteRequest.Vote + + err = privVal.SignVote(chainID, vote) if err != nil { - res = &SignedProposalResponse{nil, &RemoteSignerError{0, err.Error()}} + res = mustWrapMsg(&privvalproto.SignedVoteResponse{ + Vote: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) } else { - res = &SignedProposalResponse{r.Proposal, nil} + res = mustWrapMsg(&privvalproto.SignedVoteResponse{Vote: vote, Error: nil}) } - case *PingRequest: - err, res = nil, &PingResponse{} + case *privvalproto.Message_SignProposalRequest: + proposal := r.SignProposalRequest.Proposal + + err = privVal.SignProposal(chainID, &proposal) + if err != nil { + res = mustWrapMsg(&privvalproto.SignedProposalResponse{ + Proposal: nil, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) + } else { + res = mustWrapMsg(&privvalproto.SignedProposalResponse{Proposal: &proposal, Error: nil}) + } + case *privvalproto.Message_PingRequest: + err, res = nil, mustWrapMsg(&privvalproto.PingResponse{}) default: err = fmt.Errorf("unknown msg: %v", r) diff --git a/privval/signer_server.go b/privval/signer_server.go index 242423b24..7853db05c 100644 --- a/privval/signer_server.go +++ b/privval/signer_server.go @@ -5,14 +5,15 @@ import ( "sync" "github.com/tendermint/tendermint/libs/service" + privvalproto "github.com/tendermint/tendermint/proto/privval" "github.com/tendermint/tendermint/types" ) // ValidationRequestHandlerFunc handles different remoteSigner requests type ValidationRequestHandlerFunc func( privVal types.PrivValidator, - requestMessage SignerMessage, - chainID string) (SignerMessage, error) + requestMessage privvalproto.Message, + chainID string) (privvalproto.Message, error) type SignerServer struct { service.BaseService @@ -70,7 +71,7 @@ func (ss *SignerServer) servicePendingRequest() { return } - var res SignerMessage + var res privvalproto.Message { // limit the scope of the lock ss.handlerMtx.Lock() @@ -82,11 +83,9 @@ func (ss *SignerServer) servicePendingRequest() { } } - if res != nil { - err = ss.endpoint.WriteMessage(res) - if err != nil { - ss.Logger.Error("SignerServer: writeMessage", "err", err) - } + err = ss.endpoint.WriteMessage(res) + if err != nil { + ss.Logger.Error("SignerServer: writeMessage", "err", err) } } diff --git a/proto/privval/msgs.pb.go b/proto/privval/msgs.pb.go index 20a9db741..aeb5d4f01 100644 --- a/proto/privval/msgs.pb.go +++ b/proto/privval/msgs.pb.go @@ -116,7 +116,7 @@ var xxx_messageInfo_PubKeyRequest proto.InternalMessageInfo // PubKeyResponse is a response message containing the public key. type PubKeyResponse struct { - PubKey keys.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + PubKey *keys.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } @@ -153,11 +153,11 @@ func (m *PubKeyResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PubKeyResponse proto.InternalMessageInfo -func (m *PubKeyResponse) GetPubKey() keys.PublicKey { +func (m *PubKeyResponse) GetPubKey() *keys.PublicKey { if m != nil { return m.PubKey } - return keys.PublicKey{} + return nil } func (m *PubKeyResponse) GetError() *RemoteSignerError { @@ -169,7 +169,7 @@ func (m *PubKeyResponse) GetError() *RemoteSignerError { // SignVoteRequest is a request to sign a vote type SignVoteRequest struct { - Vote types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` + Vote *types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` } func (m *SignVoteRequest) Reset() { *m = SignVoteRequest{} } @@ -205,31 +205,31 @@ func (m *SignVoteRequest) XXX_DiscardUnknown() { var xxx_messageInfo_SignVoteRequest proto.InternalMessageInfo -func (m *SignVoteRequest) GetVote() types.Vote { +func (m *SignVoteRequest) GetVote() *types.Vote { if m != nil { return m.Vote } - return types.Vote{} + return nil } // SignedVoteResponse is a response containing a signed vote or an error -type SignVoteResponse struct { - Vote types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` +type SignedVoteResponse struct { + Vote *types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } -func (m *SignVoteResponse) Reset() { *m = SignVoteResponse{} } -func (m *SignVoteResponse) String() string { return proto.CompactTextString(m) } -func (*SignVoteResponse) ProtoMessage() {} -func (*SignVoteResponse) Descriptor() ([]byte, []int) { +func (m *SignedVoteResponse) Reset() { *m = SignedVoteResponse{} } +func (m *SignedVoteResponse) String() string { return proto.CompactTextString(m) } +func (*SignedVoteResponse) ProtoMessage() {} +func (*SignedVoteResponse) Descriptor() ([]byte, []int) { return fileDescriptor_9ec52cc5e378f9a4, []int{4} } -func (m *SignVoteResponse) XXX_Unmarshal(b []byte) error { +func (m *SignedVoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *SignVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *SignedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_SignVoteResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_SignedVoteResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -239,26 +239,26 @@ func (m *SignVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, er return b[:n], nil } } -func (m *SignVoteResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_SignVoteResponse.Merge(m, src) +func (m *SignedVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedVoteResponse.Merge(m, src) } -func (m *SignVoteResponse) XXX_Size() int { +func (m *SignedVoteResponse) XXX_Size() int { return m.Size() } -func (m *SignVoteResponse) XXX_DiscardUnknown() { - xxx_messageInfo_SignVoteResponse.DiscardUnknown(m) +func (m *SignedVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignedVoteResponse.DiscardUnknown(m) } -var xxx_messageInfo_SignVoteResponse proto.InternalMessageInfo +var xxx_messageInfo_SignedVoteResponse proto.InternalMessageInfo -func (m *SignVoteResponse) GetVote() types.Vote { +func (m *SignedVoteResponse) GetVote() *types.Vote { if m != nil { return m.Vote } - return types.Vote{} + return nil } -func (m *SignVoteResponse) GetError() *RemoteSignerError { +func (m *SignedVoteResponse) GetError() *RemoteSignerError { if m != nil { return m.Error } @@ -312,7 +312,7 @@ func (m *SignProposalRequest) GetProposal() types.Proposal { // SignedProposalResponse is response containing a signed proposal or an error type SignedProposalResponse struct { - Proposal types.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` + Proposal *types.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } @@ -349,11 +349,11 @@ func (m *SignedProposalResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SignedProposalResponse proto.InternalMessageInfo -func (m *SignedProposalResponse) GetProposal() types.Proposal { +func (m *SignedProposalResponse) GetProposal() *types.Proposal { if m != nil { return m.Proposal } - return types.Proposal{} + return nil } func (m *SignedProposalResponse) GetError() *RemoteSignerError { @@ -437,49 +437,226 @@ func (m *PingResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PingResponse proto.InternalMessageInfo +type Message struct { + // Types that are valid to be assigned to Sum: + // *Message_PubKeyRequest + // *Message_PubKeyResponse + // *Message_SignVoteRequest + // *Message_SignedVoteResponse + // *Message_SignProposalRequest + // *Message_SignedProposalResponse + // *Message_PingRequest + // *Message_PingResponse + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_9ec52cc5e378f9a4, []int{9} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_PubKeyRequest struct { + PubKeyRequest *PubKeyRequest `protobuf:"bytes,1,opt,name=pub_key_request,json=pubKeyRequest,proto3,oneof" json:"pub_key_request,omitempty"` +} +type Message_PubKeyResponse struct { + PubKeyResponse *PubKeyResponse `protobuf:"bytes,2,opt,name=pub_key_response,json=pubKeyResponse,proto3,oneof" json:"pub_key_response,omitempty"` +} +type Message_SignVoteRequest struct { + SignVoteRequest *SignVoteRequest `protobuf:"bytes,3,opt,name=sign_vote_request,json=signVoteRequest,proto3,oneof" json:"sign_vote_request,omitempty"` +} +type Message_SignedVoteResponse struct { + SignedVoteResponse *SignedVoteResponse `protobuf:"bytes,4,opt,name=signed_vote_response,json=signedVoteResponse,proto3,oneof" json:"signed_vote_response,omitempty"` +} +type Message_SignProposalRequest struct { + SignProposalRequest *SignProposalRequest `protobuf:"bytes,5,opt,name=sign_proposal_request,json=signProposalRequest,proto3,oneof" json:"sign_proposal_request,omitempty"` +} +type Message_SignedProposalResponse struct { + SignedProposalResponse *SignedProposalResponse `protobuf:"bytes,6,opt,name=signed_proposal_response,json=signedProposalResponse,proto3,oneof" json:"signed_proposal_response,omitempty"` +} +type Message_PingRequest struct { + PingRequest *PingRequest `protobuf:"bytes,7,opt,name=ping_request,json=pingRequest,proto3,oneof" json:"ping_request,omitempty"` +} +type Message_PingResponse struct { + PingResponse *PingResponse `protobuf:"bytes,8,opt,name=ping_response,json=pingResponse,proto3,oneof" json:"ping_response,omitempty"` +} + +func (*Message_PubKeyRequest) isMessage_Sum() {} +func (*Message_PubKeyResponse) isMessage_Sum() {} +func (*Message_SignVoteRequest) isMessage_Sum() {} +func (*Message_SignedVoteResponse) isMessage_Sum() {} +func (*Message_SignProposalRequest) isMessage_Sum() {} +func (*Message_SignedProposalResponse) isMessage_Sum() {} +func (*Message_PingRequest) isMessage_Sum() {} +func (*Message_PingResponse) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetPubKeyRequest() *PubKeyRequest { + if x, ok := m.GetSum().(*Message_PubKeyRequest); ok { + return x.PubKeyRequest + } + return nil +} + +func (m *Message) GetPubKeyResponse() *PubKeyResponse { + if x, ok := m.GetSum().(*Message_PubKeyResponse); ok { + return x.PubKeyResponse + } + return nil +} + +func (m *Message) GetSignVoteRequest() *SignVoteRequest { + if x, ok := m.GetSum().(*Message_SignVoteRequest); ok { + return x.SignVoteRequest + } + return nil +} + +func (m *Message) GetSignedVoteResponse() *SignedVoteResponse { + if x, ok := m.GetSum().(*Message_SignedVoteResponse); ok { + return x.SignedVoteResponse + } + return nil +} + +func (m *Message) GetSignProposalRequest() *SignProposalRequest { + if x, ok := m.GetSum().(*Message_SignProposalRequest); ok { + return x.SignProposalRequest + } + return nil +} + +func (m *Message) GetSignedProposalResponse() *SignedProposalResponse { + if x, ok := m.GetSum().(*Message_SignedProposalResponse); ok { + return x.SignedProposalResponse + } + return nil +} + +func (m *Message) GetPingRequest() *PingRequest { + if x, ok := m.GetSum().(*Message_PingRequest); ok { + return x.PingRequest + } + return nil +} + +func (m *Message) GetPingResponse() *PingResponse { + if x, ok := m.GetSum().(*Message_PingResponse); ok { + return x.PingResponse + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_PubKeyRequest)(nil), + (*Message_PubKeyResponse)(nil), + (*Message_SignVoteRequest)(nil), + (*Message_SignedVoteResponse)(nil), + (*Message_SignProposalRequest)(nil), + (*Message_SignedProposalResponse)(nil), + (*Message_PingRequest)(nil), + (*Message_PingResponse)(nil), + } +} + func init() { proto.RegisterType((*RemoteSignerError)(nil), "tendermint.proto.privval.RemoteSignerError") proto.RegisterType((*PubKeyRequest)(nil), "tendermint.proto.privval.PubKeyRequest") proto.RegisterType((*PubKeyResponse)(nil), "tendermint.proto.privval.PubKeyResponse") proto.RegisterType((*SignVoteRequest)(nil), "tendermint.proto.privval.SignVoteRequest") - proto.RegisterType((*SignVoteResponse)(nil), "tendermint.proto.privval.SignVoteResponse") + proto.RegisterType((*SignedVoteResponse)(nil), "tendermint.proto.privval.SignedVoteResponse") proto.RegisterType((*SignProposalRequest)(nil), "tendermint.proto.privval.SignProposalRequest") proto.RegisterType((*SignedProposalResponse)(nil), "tendermint.proto.privval.SignedProposalResponse") proto.RegisterType((*PingRequest)(nil), "tendermint.proto.privval.PingRequest") proto.RegisterType((*PingResponse)(nil), "tendermint.proto.privval.PingResponse") + proto.RegisterType((*Message)(nil), "tendermint.proto.privval.Message") } func init() { proto.RegisterFile("proto/privval/msgs.proto", fileDescriptor_9ec52cc5e378f9a4) } var fileDescriptor_9ec52cc5e378f9a4 = []byte{ - // 430 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x41, 0x6b, 0xd4, 0x40, - 0x14, 0xc7, 0x77, 0x64, 0x5b, 0xf5, 0xad, 0x6d, 0x35, 0x82, 0x86, 0x45, 0x63, 0xc8, 0x41, 0x0b, - 0xc2, 0x04, 0x2a, 0x78, 0x77, 0x41, 0xb1, 0xf4, 0x12, 0x22, 0x08, 0x7a, 0x29, 0x9b, 0xe4, 0x91, - 0x0e, 0xdd, 0x64, 0xc6, 0x99, 0xc9, 0x42, 0x3e, 0x84, 0xe0, 0xdd, 0x83, 0x5f, 0xa7, 0xc7, 0x1e, - 0x3d, 0x89, 0xec, 0x7e, 0x11, 0xc9, 0xcc, 0xc4, 0xac, 0x2c, 0xbd, 0xc8, 0xde, 0xde, 0xfc, 0xe7, - 0xbd, 0xff, 0xfb, 0xff, 0x86, 0x04, 0x7c, 0x21, 0xb9, 0xe6, 0xb1, 0x90, 0x6c, 0xb9, 0x9c, 0x2f, - 0xe2, 0x4a, 0x95, 0x8a, 0x1a, 0xc9, 0xf3, 0x35, 0xd6, 0x05, 0xca, 0x8a, 0xd5, 0xda, 0x2a, 0xd4, - 0x35, 0x4d, 0x9f, 0xeb, 0x0b, 0x26, 0x8b, 0x73, 0x31, 0x97, 0xba, 0x8d, 0xed, 0x7c, 0xc9, 0x4b, - 0x3e, 0x54, 0xb6, 0x7f, 0xfa, 0xd4, 0x2a, 0xb9, 0x6c, 0x85, 0xe6, 0xf1, 0x25, 0xb6, 0x2a, 0xd6, - 0xad, 0x40, 0xb7, 0x60, 0xfa, 0xd8, 0x5e, 0x1b, 0x69, 0xf3, 0x22, 0x3a, 0x85, 0x07, 0x29, 0x56, - 0x5c, 0xe3, 0x07, 0x56, 0xd6, 0x28, 0xdf, 0x4a, 0xc9, 0xa5, 0xe7, 0xc1, 0x38, 0xe7, 0x05, 0xfa, - 0x24, 0x24, 0xc7, 0x7b, 0xa9, 0xa9, 0xbd, 0x10, 0x26, 0x05, 0xaa, 0x5c, 0x32, 0xa1, 0x19, 0xaf, - 0xfd, 0x5b, 0x21, 0x39, 0xbe, 0x9b, 0x6e, 0x4a, 0xd1, 0x11, 0x1c, 0x24, 0x4d, 0x76, 0x86, 0x6d, - 0x8a, 0x5f, 0x1a, 0x54, 0x3a, 0xfa, 0x4e, 0xe0, 0xb0, 0x57, 0x94, 0xe0, 0xb5, 0x42, 0xef, 0x1d, - 0xdc, 0x16, 0x4d, 0x76, 0x7e, 0x89, 0xad, 0x31, 0x9f, 0x9c, 0xbc, 0xa0, 0x5b, 0xe8, 0x96, 0x81, - 0x76, 0x0c, 0x34, 0x69, 0xb2, 0x05, 0xcb, 0xcf, 0xb0, 0x9d, 0x8d, 0xaf, 0x7e, 0x3d, 0x1b, 0xa5, - 0xfb, 0xc2, 0xf8, 0x79, 0x6f, 0x60, 0x0f, 0xbb, 0xa8, 0x26, 0xc7, 0xe4, 0xe4, 0x25, 0xbd, 0xe9, - 0x01, 0xe9, 0x16, 0x5d, 0x6a, 0x27, 0xa3, 0x53, 0x38, 0xea, 0xd4, 0x8f, 0x5c, 0xa3, 0x0b, 0xec, - 0xbd, 0x86, 0xf1, 0x92, 0x6b, 0x74, 0xd1, 0x9e, 0x6c, 0x9b, 0xda, 0x97, 0xeb, 0x46, 0x5c, 0x1e, - 0xd3, 0x1f, 0x7d, 0x25, 0x70, 0x7f, 0xf0, 0x72, 0xa8, 0xff, 0x69, 0xb6, 0x0b, 0xb4, 0x4f, 0xf0, - 0xb0, 0x53, 0x13, 0xc9, 0x05, 0x57, 0xf3, 0x45, 0x8f, 0x37, 0x83, 0x3b, 0xc2, 0x49, 0x2e, 0x55, - 0x78, 0x53, 0xaa, 0x7e, 0xd4, 0x25, 0xfb, 0x3b, 0x17, 0xfd, 0x20, 0xf0, 0xc8, 0x6c, 0x2c, 0x06, - 0x77, 0x07, 0xbc, 0x03, 0xfb, 0x5d, 0xc0, 0x1f, 0xc0, 0x24, 0x61, 0x75, 0xd9, 0x7f, 0x84, 0x87, - 0x70, 0xcf, 0x1e, 0x6d, 0xca, 0xd9, 0xfb, 0xab, 0x55, 0x40, 0xae, 0x57, 0x01, 0xf9, 0xbd, 0x0a, - 0xc8, 0xb7, 0x75, 0x30, 0xba, 0x5e, 0x07, 0xa3, 0x9f, 0xeb, 0x60, 0xf4, 0x99, 0x96, 0x4c, 0x5f, - 0x34, 0x19, 0xcd, 0x79, 0x15, 0x0f, 0x6b, 0x37, 0xcb, 0x7f, 0xfe, 0xdf, 0x6c, 0xdf, 0x1c, 0x5f, - 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0x52, 0xa9, 0xe1, 0x74, 0xd7, 0x03, 0x00, 0x00, + // 629 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0x41, 0x6f, 0xd3, 0x3c, + 0x1c, 0xc6, 0x93, 0x77, 0xed, 0xb6, 0xf7, 0xdf, 0x75, 0x65, 0x1e, 0x8c, 0x6a, 0x82, 0x52, 0x45, + 0x62, 0x0c, 0x01, 0xe9, 0x34, 0xae, 0x1c, 0xa0, 0x08, 0x29, 0x80, 0x26, 0x15, 0x83, 0x40, 0x70, + 0x29, 0x6d, 0x6a, 0x65, 0xd1, 0xda, 0xd8, 0xd8, 0xce, 0xa4, 0x7c, 0x04, 0x6e, 0x5c, 0x38, 0xf0, + 0x8d, 0x76, 0xdc, 0x91, 0x13, 0x42, 0xdd, 0x17, 0x41, 0xb1, 0x9d, 0x26, 0x6d, 0xd7, 0x4d, 0x93, + 0x76, 0x8b, 0x9f, 0xd8, 0xbf, 0xff, 0xf3, 0xc4, 0x4f, 0x55, 0xa8, 0x33, 0x4e, 0x25, 0x6d, 0x31, + 0x1e, 0x1e, 0x1f, 0xf7, 0x86, 0xad, 0x91, 0x08, 0x84, 0xab, 0x24, 0x54, 0x97, 0x24, 0x1a, 0x10, + 0x3e, 0x0a, 0x23, 0xa9, 0x15, 0xd7, 0x6c, 0xda, 0xde, 0x91, 0x87, 0x21, 0x1f, 0x74, 0x59, 0x8f, + 0xcb, 0xa4, 0xa5, 0xcf, 0x07, 0x34, 0xa0, 0xf9, 0x93, 0xde, 0xbf, 0x7d, 0x57, 0x2b, 0x3e, 0x4f, + 0x98, 0xa4, 0xad, 0x23, 0x92, 0x88, 0x96, 0x4c, 0x18, 0x31, 0x03, 0xb6, 0x6f, 0xeb, 0xd7, 0x4a, + 0x2a, 0xbe, 0x70, 0x5e, 0xc3, 0x06, 0x26, 0x23, 0x2a, 0xc9, 0xfb, 0x30, 0x88, 0x08, 0x7f, 0xc5, + 0x39, 0xe5, 0x08, 0x41, 0xc9, 0xa7, 0x03, 0x52, 0xb7, 0x9b, 0xf6, 0x6e, 0x19, 0xab, 0x67, 0xd4, + 0x84, 0xca, 0x80, 0x08, 0x9f, 0x87, 0x4c, 0x86, 0x34, 0xaa, 0xff, 0xd7, 0xb4, 0x77, 0xff, 0xc7, + 0x45, 0xc9, 0xa9, 0x41, 0xb5, 0x13, 0xf7, 0xdf, 0x92, 0x04, 0x93, 0x6f, 0x31, 0x11, 0xd2, 0xf9, + 0x69, 0xc3, 0x7a, 0xa6, 0x08, 0x46, 0x23, 0x41, 0xd0, 0x73, 0x58, 0x61, 0x71, 0xbf, 0x7b, 0x44, + 0x12, 0x05, 0xaf, 0xec, 0x3f, 0x70, 0xe7, 0xa2, 0xeb, 0x0c, 0x6e, 0x9a, 0xc1, 0xed, 0xc4, 0xfd, + 0x61, 0xe8, 0xa7, 0x84, 0x65, 0xa6, 0x48, 0xe8, 0x05, 0x94, 0x49, 0x6a, 0x52, 0x39, 0xa8, 0xec, + 0x3f, 0x72, 0x17, 0x7d, 0x3a, 0x77, 0x2e, 0x17, 0xd6, 0x27, 0x9d, 0x97, 0x50, 0x4b, 0xd5, 0x8f, + 0x54, 0x12, 0x63, 0x15, 0xed, 0x41, 0xe9, 0x98, 0x4a, 0x62, 0x4c, 0xdd, 0x99, 0x87, 0xea, 0x6f, + 0xa6, 0x8e, 0xa8, 0x9d, 0xce, 0x77, 0x1b, 0x90, 0x62, 0x0f, 0x34, 0xc7, 0x04, 0xbc, 0x32, 0xe8, + 0x3a, 0x02, 0x7d, 0x86, 0xcd, 0x54, 0xed, 0x70, 0xca, 0xa8, 0xe8, 0x0d, 0xb3, 0x50, 0x6d, 0x58, + 0x65, 0x46, 0x32, 0x7e, 0x9a, 0x8b, 0xfc, 0x64, 0x47, 0xdb, 0xa5, 0x93, 0x3f, 0xf7, 0x2c, 0x3c, + 0x39, 0xe7, 0xfc, 0xb2, 0x61, 0x4b, 0xc7, 0xcc, 0xe9, 0x26, 0xea, 0xb3, 0xab, 0xe3, 0x73, 0xf0, + 0x75, 0xc4, 0xae, 0x42, 0xa5, 0x13, 0x46, 0x41, 0x56, 0xb7, 0x75, 0x58, 0xd3, 0x4b, 0xed, 0xcf, + 0x19, 0x97, 0x61, 0xe5, 0x80, 0x08, 0xd1, 0x0b, 0x08, 0x7a, 0x07, 0x35, 0xd3, 0xbb, 0x2e, 0xd7, + 0xdb, 0x17, 0xf7, 0x2f, 0x9b, 0x3b, 0x55, 0x66, 0xcf, 0xc2, 0x55, 0x56, 0x14, 0xd0, 0x07, 0xb8, + 0x91, 0x23, 0xf5, 0x48, 0x93, 0x65, 0xf7, 0x72, 0xa6, 0xde, 0xef, 0x59, 0x78, 0x9d, 0x4d, 0xff, + 0x40, 0x3e, 0xc1, 0x86, 0x08, 0x83, 0xa8, 0x9b, 0x56, 0x63, 0x62, 0x75, 0x49, 0x61, 0x1f, 0x2e, + 0xc6, 0xce, 0xd4, 0xd9, 0xb3, 0x70, 0x4d, 0xcc, 0x34, 0xfc, 0x2b, 0xdc, 0x14, 0xea, 0x1e, 0x33, + 0xb4, 0xb1, 0x5c, 0x52, 0xec, 0xc7, 0x17, 0xb3, 0xa7, 0x4b, 0xee, 0x59, 0x18, 0x89, 0xf9, 0xea, + 0xfb, 0x70, 0x4b, 0x59, 0xcf, 0xae, 0x78, 0x62, 0xbf, 0xac, 0x46, 0x3c, 0xb9, 0x78, 0xc4, 0x4c, + 0x79, 0x3d, 0x0b, 0x6f, 0x8a, 0x73, 0x3a, 0x3d, 0x84, 0xba, 0x89, 0x51, 0x18, 0x63, 0xa2, 0x2c, + 0xab, 0x39, 0x7b, 0x97, 0x45, 0x99, 0x2d, 0xb2, 0x67, 0xe1, 0x2d, 0x71, 0x7e, 0xc5, 0xdf, 0xc0, + 0x1a, 0x0b, 0xa3, 0x60, 0x92, 0x64, 0x45, 0x4d, 0xb8, 0x7f, 0xc1, 0xfd, 0xe6, 0x7d, 0xf4, 0x2c, + 0x5c, 0x61, 0xf9, 0x12, 0x1d, 0x40, 0xd5, 0xb0, 0x8c, 0xdd, 0x55, 0x05, 0xdb, 0xb9, 0x0c, 0x36, + 0x31, 0xb9, 0xc6, 0x0a, 0xeb, 0x76, 0x19, 0x96, 0x44, 0x3c, 0x6a, 0x7b, 0x27, 0xe3, 0x86, 0x7d, + 0x3a, 0x6e, 0xd8, 0x7f, 0xc7, 0x0d, 0xfb, 0xc7, 0x59, 0xc3, 0x3a, 0x3d, 0x6b, 0x58, 0xbf, 0xcf, + 0x1a, 0xd6, 0x17, 0x37, 0x08, 0xe5, 0x61, 0xdc, 0x77, 0x7d, 0x3a, 0x6a, 0xe5, 0x23, 0x8a, 0x8f, + 0x53, 0x7f, 0x47, 0xfd, 0x65, 0xb5, 0x7c, 0xfa, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x18, 0x03, 0x41, + 0x2e, 0xa6, 0x06, 0x00, 0x00, } func (m *RemoteSignerError) Marshal() (dAtA []byte, err error) { @@ -572,16 +749,18 @@ func (m *PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - { - size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.PubKey != nil { + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintMsgs(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -605,20 +784,22 @@ func (m *SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - { - size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintMsgs(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } -func (m *SignVoteResponse) Marshal() (dAtA []byte, err error) { +func (m *SignedVoteResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -628,12 +809,12 @@ func (m *SignVoteResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *SignVoteResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *SignVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -650,16 +831,18 @@ func (m *SignVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - { - size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintMsgs(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -728,16 +911,18 @@ func (m *SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) i-- dAtA[i] = 0x12 } - { - size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Proposal != nil { + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintMsgs(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -787,6 +972,206 @@ func (m *PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Message) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_PubKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyRequest != nil { + { + size, err := m.PubKeyRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Message_PubKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyResponse != nil { + { + size, err := m.PubKeyResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_SignVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignVoteRequest != nil { + { + size, err := m.SignVoteRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedVoteResponse != nil { + { + size, err := m.SignedVoteResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Message_SignProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignProposalRequest != nil { + { + size, err := m.SignProposalRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedProposalResponse != nil { + { + size, err := m.SignedProposalResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Message_PingRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingRequest != nil { + { + size, err := m.PingRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Message_PingResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingResponse != nil { + { + size, err := m.PingResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMsgs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} func encodeVarintMsgs(dAtA []byte, offset int, v uint64) int { offset -= sovMsgs(v) base := offset @@ -829,8 +1214,10 @@ func (m *PubKeyResponse) Size() (n int) { } var l int _ = l - l = m.PubKey.Size() - n += 1 + l + sovMsgs(uint64(l)) + if m.PubKey != nil { + l = m.PubKey.Size() + n += 1 + l + sovMsgs(uint64(l)) + } if m.Error != nil { l = m.Error.Size() n += 1 + l + sovMsgs(uint64(l)) @@ -844,19 +1231,23 @@ func (m *SignVoteRequest) Size() (n int) { } var l int _ = l - l = m.Vote.Size() - n += 1 + l + sovMsgs(uint64(l)) + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovMsgs(uint64(l)) + } return n } -func (m *SignVoteResponse) Size() (n int) { +func (m *SignedVoteResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.Vote.Size() - n += 1 + l + sovMsgs(uint64(l)) + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovMsgs(uint64(l)) + } if m.Error != nil { l = m.Error.Size() n += 1 + l + sovMsgs(uint64(l)) @@ -881,8 +1272,10 @@ func (m *SignedProposalResponse) Size() (n int) { } var l int _ = l - l = m.Proposal.Size() - n += 1 + l + sovMsgs(uint64(l)) + if m.Proposal != nil { + l = m.Proposal.Size() + n += 1 + l + sovMsgs(uint64(l)) + } if m.Error != nil { l = m.Error.Size() n += 1 + l + sovMsgs(uint64(l)) @@ -908,6 +1301,115 @@ func (m *PingResponse) Size() (n int) { return n } +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_PubKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyRequest != nil { + l = m.PubKeyRequest.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_PubKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyResponse != nil { + l = m.PubKeyResponse.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_SignVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignVoteRequest != nil { + l = m.SignVoteRequest.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_SignedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedVoteResponse != nil { + l = m.SignedVoteResponse.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_SignProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignProposalRequest != nil { + l = m.SignProposalRequest.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_SignedProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedProposalResponse != nil { + l = m.SignedProposalResponse.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_PingRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingRequest != nil { + l = m.PingRequest.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} +func (m *Message_PingResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingResponse != nil { + l = m.PingResponse.Size() + n += 1 + l + sovMsgs(uint64(l)) + } + return n +} + func sovMsgs(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1129,6 +1631,9 @@ func (m *PubKeyResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.PubKey == nil { + m.PubKey = &keys.PublicKey{} + } if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1251,6 +1756,9 @@ func (m *SignVoteRequest) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Vote == nil { + m.Vote = &types.Vote{} + } if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1279,7 +1787,7 @@ func (m *SignVoteRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *SignVoteResponse) Unmarshal(dAtA []byte) error { +func (m *SignedVoteResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1302,10 +1810,10 @@ func (m *SignVoteResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: SignVoteResponse: wiretype end group for non-group") + return fmt.Errorf("proto: SignedVoteResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: SignVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: SignedVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1337,6 +1845,9 @@ func (m *SignVoteResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Vote == nil { + m.Vote = &types.Vote{} + } if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1545,6 +2056,9 @@ func (m *SignedProposalResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Proposal == nil { + m.Proposal = &types.Proposal{} + } if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1715,6 +2229,339 @@ func (m *PingResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *Message) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyRequest{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyResponse{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignVoteRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignVoteRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignVoteRequest{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedVoteResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedVoteResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedVoteResponse{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignProposalRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignProposalRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignProposalRequest{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedProposalResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedProposalResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedProposalResponse{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingRequest{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMsgs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMsgs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMsgs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingResponse{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMsgs(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthMsgs + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipMsgs(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/proto/privval/msgs.proto b/proto/privval/msgs.proto index a88c01658..f14df3628 100644 --- a/proto/privval/msgs.proto +++ b/proto/privval/msgs.proto @@ -17,18 +17,18 @@ message PubKeyRequest {} // PubKeyResponse is a response message containing the public key. message PubKeyResponse { - tendermint.proto.crypto.keys.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + tendermint.proto.crypto.keys.PublicKey pub_key = 1; RemoteSignerError error = 2; } // SignVoteRequest is a request to sign a vote message SignVoteRequest { - tendermint.proto.types.Vote vote = 1 [(gogoproto.nullable) = false]; + tendermint.proto.types.Vote vote = 1; } // SignedVoteResponse is a response containing a signed vote or an error -message SignVoteResponse { - tendermint.proto.types.Vote vote = 1 [(gogoproto.nullable) = false]; +message SignedVoteResponse { + tendermint.proto.types.Vote vote = 1; RemoteSignerError error = 2; } @@ -39,7 +39,7 @@ message SignProposalRequest { // SignedProposalResponse is response containing a signed proposal or an error message SignedProposalResponse { - tendermint.proto.types.Proposal proposal = 1 [(gogoproto.nullable) = false]; + tendermint.proto.types.Proposal proposal = 1; RemoteSignerError error = 2; } @@ -48,3 +48,16 @@ message PingRequest {} // PingResponse is a response to confirm that the connection is alive. message PingResponse {} + +message Message { + oneof sum { + PubKeyRequest pub_key_request = 1; + PubKeyResponse pub_key_response = 2; + SignVoteRequest sign_vote_request = 3; + SignedVoteResponse signed_vote_response = 4; + SignProposalRequest sign_proposal_request = 5; + SignedProposalResponse signed_proposal_response = 6; + PingRequest ping_request = 7; + PingResponse ping_response = 8; + } +} diff --git a/proto/privval/types.pb.go b/proto/privval/types.pb.go index 4e2dcfa0b..e394fee43 100644 --- a/proto/privval/types.pb.go +++ b/proto/privval/types.pb.go @@ -24,6 +24,43 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +type Errors int32 + +const ( + Errors_ERRORS_UNKNOWN Errors = 0 + Errors_ERRORS_UNEXPECTED_RESPONSE Errors = 1 + Errors_ERRORS_NO_CONNECTION Errors = 2 + Errors_ERRORS_CONNECTION_TIMEOUT Errors = 3 + Errors_ERRORS_READ_TIMEOUT Errors = 4 + Errors_ERRORS_WRITE_TIMEOUT Errors = 5 +) + +var Errors_name = map[int32]string{ + 0: "ERRORS_UNKNOWN", + 1: "ERRORS_UNEXPECTED_RESPONSE", + 2: "ERRORS_NO_CONNECTION", + 3: "ERRORS_CONNECTION_TIMEOUT", + 4: "ERRORS_READ_TIMEOUT", + 5: "ERRORS_WRITE_TIMEOUT", +} + +var Errors_value = map[string]int32{ + "ERRORS_UNKNOWN": 0, + "ERRORS_UNEXPECTED_RESPONSE": 1, + "ERRORS_NO_CONNECTION": 2, + "ERRORS_CONNECTION_TIMEOUT": 3, + "ERRORS_READ_TIMEOUT": 4, + "ERRORS_WRITE_TIMEOUT": 5, +} + +func (x Errors) String() string { + return proto.EnumName(Errors_name, int32(x)) +} + +func (Errors) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_a9d74c406df3ad93, []int{0} +} + // FilePVKey stores the immutable part of PrivValidator. type FilePVKey struct { Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` @@ -96,7 +133,7 @@ func (m *FilePVKey) GetFilePath() string { // FilePVLastSignState stores the mutable part of PrivValidator. type FilePVLastSignState struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int64 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` Step int32 `protobuf:"varint,3,opt,name=step,proto3" json:"step,omitempty"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` SignBytes []byte `protobuf:"bytes,5,opt,name=sign_bytes,json=signBytes,proto3" json:"sign_bytes,omitempty"` @@ -143,7 +180,7 @@ func (m *FilePVLastSignState) GetHeight() int64 { return 0 } -func (m *FilePVLastSignState) GetRound() int64 { +func (m *FilePVLastSignState) GetRound() int32 { if m != nil { return m.Round } @@ -179,6 +216,7 @@ func (m *FilePVLastSignState) GetFilePath() string { } func init() { + proto.RegisterEnum("tendermint.proto.privval.Errors", Errors_name, Errors_value) proto.RegisterType((*FilePVKey)(nil), "tendermint.proto.privval.FilePVKey") proto.RegisterType((*FilePVLastSignState)(nil), "tendermint.proto.privval.FilePVLastSignState") } @@ -186,32 +224,38 @@ func init() { func init() { proto.RegisterFile("proto/privval/types.proto", fileDescriptor_a9d74c406df3ad93) } var fileDescriptor_a9d74c406df3ad93 = []byte{ - // 385 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x4d, 0x8e, 0xd3, 0x30, - 0x14, 0x8e, 0x69, 0x9b, 0x4e, 0xcc, 0xac, 0x0c, 0x42, 0x61, 0x60, 0x42, 0x35, 0x0b, 0xc8, 0x2a, - 0x91, 0xe0, 0x06, 0x5d, 0x8c, 0x40, 0xc3, 0xa2, 0xca, 0x48, 0x2c, 0xd8, 0x44, 0x4e, 0xf3, 0x48, - 0xac, 0xc9, 0x24, 0x96, 0xfd, 0x52, 0xc9, 0xb7, 0xe0, 0x2a, 0xdc, 0x62, 0x96, 0xdd, 0x20, 0xb1, - 0x42, 0xa8, 0xbd, 0x08, 0xb2, 0x53, 0x94, 0x56, 0x2c, 0x66, 0xf7, 0xbe, 0xcf, 0xcf, 0xdf, 0x8f, - 0x65, 0xfa, 0x52, 0xaa, 0x0e, 0xbb, 0x54, 0x2a, 0xb1, 0xd9, 0xf0, 0x26, 0x45, 0x23, 0x41, 0x27, - 0x8e, 0x63, 0x21, 0x42, 0x5b, 0x82, 0xba, 0x17, 0x2d, 0x0e, 0x4c, 0x72, 0xd8, 0xba, 0x78, 0x8b, - 0xb5, 0x50, 0x65, 0x2e, 0xb9, 0x42, 0x93, 0x0e, 0x02, 0x55, 0x57, 0x75, 0xe3, 0x34, 0xec, 0x5f, - 0x5c, 0x0e, 0xcc, 0x5a, 0x19, 0x89, 0x5d, 0x7a, 0x07, 0x46, 0x1f, 0x1b, 0x5c, 0xfd, 0x24, 0x34, - 0xb8, 0x16, 0x0d, 0xac, 0xbe, 0xdc, 0x80, 0x61, 0x21, 0x9d, 0xf3, 0xb2, 0x54, 0xa0, 0x75, 0x48, - 0x16, 0x24, 0x3e, 0xcf, 0xfe, 0x41, 0x76, 0x4d, 0xe7, 0xb2, 0x2f, 0xf2, 0x3b, 0x30, 0xe1, 0x93, - 0x05, 0x89, 0x9f, 0xbe, 0x7f, 0x97, 0xfc, 0x17, 0x6d, 0xf0, 0x48, 0xac, 0x47, 0xb2, 0xea, 0x8b, - 0x46, 0xac, 0x6f, 0xc0, 0x2c, 0xa7, 0x0f, 0xbf, 0xdf, 0x78, 0x99, 0x2f, 0xfb, 0xc2, 0x3a, 0x7c, - 0xa2, 0x67, 0xb6, 0x81, 0x13, 0x9a, 0x38, 0xa1, 0xf8, 0x11, 0x21, 0x25, 0x36, 0x1c, 0x61, 0x54, - 0x9a, 0xdb, 0xfb, 0x56, 0xea, 0x15, 0x0d, 0xbe, 0x89, 0x06, 0x72, 0xc9, 0xb1, 0x0e, 0xa7, 0x0b, - 0x12, 0x07, 0xd9, 0x99, 0x25, 0x56, 0x1c, 0xeb, 0xab, 0x1f, 0x84, 0x3e, 0x1b, 0x7a, 0x7d, 0xe6, - 0x1a, 0x6f, 0x45, 0xd5, 0xde, 0x22, 0x47, 0x60, 0x2f, 0xa8, 0x5f, 0x83, 0xa8, 0x6a, 0x74, 0x05, - 0x27, 0xd9, 0x01, 0xb1, 0xe7, 0x74, 0xa6, 0xba, 0xbe, 0x2d, 0x5d, 0xbb, 0x49, 0x36, 0x00, 0xc6, - 0xe8, 0x54, 0x23, 0x48, 0x97, 0x74, 0x96, 0xb9, 0x99, 0xbd, 0xa6, 0x81, 0x16, 0x55, 0xcb, 0xb1, - 0x57, 0xe0, 0x6c, 0xcf, 0xb3, 0x91, 0x60, 0x97, 0x94, 0x5a, 0x90, 0x17, 0x06, 0x41, 0x87, 0xb3, - 0xf1, 0x78, 0x69, 0x89, 0xd3, 0xcc, 0xfe, 0x69, 0xe6, 0xe5, 0xc7, 0x87, 0x5d, 0x44, 0xb6, 0xbb, - 0x88, 0xfc, 0xd9, 0x45, 0xe4, 0xfb, 0x3e, 0xf2, 0xb6, 0xfb, 0xc8, 0xfb, 0xb5, 0x8f, 0xbc, 0xaf, - 0x49, 0x25, 0xb0, 0xee, 0x8b, 0x64, 0xdd, 0xdd, 0xa7, 0xe3, 0x6b, 0x1d, 0x8f, 0x27, 0x5f, 0xa8, - 0xf0, 0x1d, 0xfc, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0xe5, 0xc6, 0x2f, 0x79, 0x5a, 0x02, 0x00, - 0x00, + // 493 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0xcf, 0x6e, 0xd3, 0x4e, + 0x18, 0xcc, 0x36, 0x89, 0xd3, 0xec, 0xaf, 0xfa, 0x29, 0xda, 0x56, 0xe0, 0x06, 0x62, 0xa2, 0x1e, + 0x20, 0xe2, 0x60, 0x4b, 0xf0, 0x04, 0x24, 0xdd, 0x8a, 0x28, 0x60, 0x5b, 0x6b, 0x97, 0x22, 0x2e, + 0x96, 0x1d, 0x2f, 0xf6, 0xaa, 0xa9, 0x6d, 0xad, 0xd7, 0x91, 0xfc, 0x16, 0x3c, 0x06, 0x57, 0xde, + 0xa2, 0xc7, 0x5e, 0x90, 0x38, 0x21, 0x94, 0xbc, 0x08, 0xf2, 0x1f, 0xe2, 0x44, 0x1c, 0xb8, 0x7d, + 0x33, 0xf3, 0x79, 0xe6, 0x1b, 0x79, 0xe1, 0x79, 0xc2, 0x63, 0x11, 0x6b, 0x09, 0x67, 0xeb, 0xb5, + 0xbb, 0xd2, 0x44, 0x9e, 0xd0, 0x54, 0x2d, 0x39, 0x24, 0x0b, 0x1a, 0xf9, 0x94, 0xdf, 0xb1, 0x48, + 0x54, 0x8c, 0x5a, 0x6f, 0x0d, 0x9f, 0x8b, 0x90, 0x71, 0xdf, 0x49, 0x5c, 0x2e, 0x72, 0xad, 0x32, + 0x08, 0xe2, 0x20, 0x6e, 0xa6, 0x6a, 0x7f, 0x38, 0xaa, 0x98, 0x25, 0xcf, 0x13, 0x11, 0x6b, 0xb7, + 0x34, 0x4f, 0xf7, 0x03, 0x2e, 0xbe, 0x03, 0xd8, 0xbf, 0x62, 0x2b, 0x6a, 0x7e, 0x58, 0xd0, 0x1c, + 0xc9, 0xb0, 0xe7, 0xfa, 0x3e, 0xa7, 0x69, 0x2a, 0x83, 0x31, 0x98, 0x9c, 0x90, 0x3f, 0x10, 0x5d, + 0xc1, 0x5e, 0x92, 0x79, 0xce, 0x2d, 0xcd, 0xe5, 0xa3, 0x31, 0x98, 0xfc, 0xf7, 0xea, 0x85, 0xfa, + 0xd7, 0x69, 0x55, 0x86, 0x5a, 0x64, 0xa8, 0x66, 0xe6, 0xad, 0xd8, 0x72, 0x41, 0xf3, 0x69, 0xe7, + 0xfe, 0xe7, 0xb3, 0x16, 0x91, 0x92, 0xcc, 0x2b, 0x12, 0xe6, 0xf0, 0xb8, 0x68, 0x50, 0x1a, 0xb5, + 0x4b, 0xa3, 0xc9, 0x3f, 0x8c, 0x38, 0x5b, 0xbb, 0x82, 0x36, 0x4e, 0xbd, 0xe2, 0xfb, 0xc2, 0xea, + 0x09, 0xec, 0x7f, 0x66, 0x2b, 0xea, 0x24, 0xae, 0x08, 0xe5, 0xce, 0x18, 0x4c, 0xfa, 0xe4, 0xb8, + 0x20, 0x4c, 0x57, 0x84, 0x17, 0xdf, 0x00, 0x3c, 0xad, 0x7a, 0xbd, 0x73, 0x53, 0x61, 0xb1, 0x20, + 0xb2, 0x84, 0x2b, 0x28, 0x7a, 0x04, 0xa5, 0x90, 0xb2, 0x20, 0x14, 0x65, 0xc1, 0x36, 0xa9, 0x11, + 0x3a, 0x83, 0x5d, 0x1e, 0x67, 0x91, 0x5f, 0xb6, 0xeb, 0x92, 0x0a, 0x20, 0x04, 0x3b, 0xa9, 0xa0, + 0x49, 0x79, 0x69, 0x97, 0x94, 0x33, 0x7a, 0x0a, 0xfb, 0x29, 0x0b, 0x22, 0x57, 0x64, 0x9c, 0x96, + 0xb1, 0x27, 0xa4, 0x21, 0xd0, 0x08, 0xc2, 0x02, 0x38, 0x5e, 0x2e, 0x68, 0x2a, 0x77, 0x1b, 0x79, + 0x5a, 0x10, 0x87, 0x37, 0x4b, 0x87, 0x37, 0xbf, 0xfc, 0x0a, 0xa0, 0x84, 0x39, 0x8f, 0x79, 0x8a, + 0x10, 0xfc, 0x1f, 0x13, 0x62, 0x10, 0xcb, 0xb9, 0xd6, 0x17, 0xba, 0x71, 0xa3, 0x0f, 0x5a, 0x48, + 0x81, 0xc3, 0x1d, 0x87, 0x3f, 0x9a, 0x78, 0x66, 0xe3, 0x4b, 0x87, 0x60, 0xcb, 0x34, 0x74, 0x0b, + 0x0f, 0x00, 0x92, 0xe1, 0x59, 0xad, 0xeb, 0x86, 0x33, 0x33, 0x74, 0x1d, 0xcf, 0xec, 0xb9, 0xa1, + 0x0f, 0x8e, 0xd0, 0x08, 0x9e, 0xd7, 0x4a, 0x43, 0x3b, 0xf6, 0xfc, 0x3d, 0x36, 0xae, 0xed, 0x41, + 0x1b, 0x3d, 0x86, 0xa7, 0xb5, 0x4c, 0xf0, 0x9b, 0xcb, 0x9d, 0xd0, 0xd9, 0x73, 0xbc, 0x21, 0x73, + 0x1b, 0xef, 0x94, 0xee, 0xf4, 0xed, 0xfd, 0x46, 0x01, 0x0f, 0x1b, 0x05, 0xfc, 0xda, 0x28, 0xe0, + 0xcb, 0x56, 0x69, 0x3d, 0x6c, 0x95, 0xd6, 0x8f, 0xad, 0xd2, 0xfa, 0xa4, 0x06, 0x4c, 0x84, 0x99, + 0xa7, 0x2e, 0xe3, 0x3b, 0xad, 0xf9, 0xb1, 0xfb, 0xe3, 0xc1, 0x6b, 0xf7, 0xa4, 0x12, 0xbe, 0xfe, + 0x1d, 0x00, 0x00, 0xff, 0xff, 0x60, 0xba, 0xbc, 0x27, 0x05, 0x03, 0x00, 0x00, } func (m *FilePVKey) Marshal() (dAtA []byte, err error) { @@ -645,7 +689,7 @@ func (m *FilePVLastSignState) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Round |= int64(b&0x7F) << shift + m.Round |= int32(b&0x7F) << shift if b < 0x80 { break } diff --git a/proto/privval/types.proto b/proto/privval/types.proto index 80b613a7c..9c27e84a7 100644 --- a/proto/privval/types.proto +++ b/proto/privval/types.proto @@ -18,10 +18,19 @@ message FilePVKey { // FilePVLastSignState stores the mutable part of PrivValidator. message FilePVLastSignState { int64 height = 1; - int64 round = 2; + int32 round = 2; int32 step = 3; bytes signature = 4; bytes sign_bytes = 5; string file_path = 6; } + +enum Errors { + ERRORS_UNKNOWN = 0; + ERRORS_UNEXPECTED_RESPONSE = 1; + ERRORS_NO_CONNECTION = 2; + ERRORS_CONNECTION_TIMEOUT = 3; + ERRORS_READ_TIMEOUT = 4; + ERRORS_WRITE_TIMEOUT = 5; +} diff --git a/proto/types/canonical.pb.go b/proto/types/canonical.pb.go new file mode 100644 index 000000000..6740ba3d7 --- /dev/null +++ b/proto/types/canonical.pb.go @@ -0,0 +1,1407 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: proto/types/canonical.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type CanonicalBlockID struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + PartsHeader CanonicalPartSetHeader `protobuf:"bytes,2,opt,name=parts_header,json=partsHeader,proto3" json:"parts_header"` +} + +func (m *CanonicalBlockID) Reset() { *m = CanonicalBlockID{} } +func (m *CanonicalBlockID) String() string { return proto.CompactTextString(m) } +func (*CanonicalBlockID) ProtoMessage() {} +func (*CanonicalBlockID) Descriptor() ([]byte, []int) { + return fileDescriptor_3f9b1d584b46f180, []int{0} +} +func (m *CanonicalBlockID) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalBlockID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalBlockID.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalBlockID) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalBlockID.Merge(m, src) +} +func (m *CanonicalBlockID) XXX_Size() int { + return m.Size() +} +func (m *CanonicalBlockID) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalBlockID.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalBlockID proto.InternalMessageInfo + +func (m *CanonicalBlockID) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *CanonicalBlockID) GetPartsHeader() CanonicalPartSetHeader { + if m != nil { + return m.PartsHeader + } + return CanonicalPartSetHeader{} +} + +type CanonicalPartSetHeader struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` +} + +func (m *CanonicalPartSetHeader) Reset() { *m = CanonicalPartSetHeader{} } +func (m *CanonicalPartSetHeader) String() string { return proto.CompactTextString(m) } +func (*CanonicalPartSetHeader) ProtoMessage() {} +func (*CanonicalPartSetHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_3f9b1d584b46f180, []int{1} +} +func (m *CanonicalPartSetHeader) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalPartSetHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalPartSetHeader.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalPartSetHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalPartSetHeader.Merge(m, src) +} +func (m *CanonicalPartSetHeader) XXX_Size() int { + return m.Size() +} +func (m *CanonicalPartSetHeader) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalPartSetHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalPartSetHeader proto.InternalMessageInfo + +func (m *CanonicalPartSetHeader) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *CanonicalPartSetHeader) GetTotal() uint32 { + if m != nil { + return m.Total + } + return 0 +} + +type CanonicalProposal struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.proto.types.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Round int64 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` + POLRound int64 `protobuf:"varint,4,opt,name=pol_round,json=polRound,proto3" json:"pol_round,omitempty"` + BlockID CanonicalBlockID `protobuf:"bytes,5,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Timestamp time.Time `protobuf:"bytes,6,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + ChainID string `protobuf:"bytes,7,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *CanonicalProposal) Reset() { *m = CanonicalProposal{} } +func (m *CanonicalProposal) String() string { return proto.CompactTextString(m) } +func (*CanonicalProposal) ProtoMessage() {} +func (*CanonicalProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_3f9b1d584b46f180, []int{2} +} +func (m *CanonicalProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalProposal.Merge(m, src) +} +func (m *CanonicalProposal) XXX_Size() int { + return m.Size() +} +func (m *CanonicalProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalProposal proto.InternalMessageInfo + +func (m *CanonicalProposal) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return SIGNED_MSG_TYPE_UNKNOWN +} + +func (m *CanonicalProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *CanonicalProposal) GetRound() int64 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CanonicalProposal) GetPOLRound() int64 { + if m != nil { + return m.POLRound + } + return 0 +} + +func (m *CanonicalProposal) GetBlockID() CanonicalBlockID { + if m != nil { + return m.BlockID + } + return CanonicalBlockID{} +} + +func (m *CanonicalProposal) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *CanonicalProposal) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +type CanonicalVote struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.proto.types.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Round int64 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` + BlockID CanonicalBlockID `protobuf:"bytes,5,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Timestamp time.Time `protobuf:"bytes,6,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + ChainID string `protobuf:"bytes,7,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *CanonicalVote) Reset() { *m = CanonicalVote{} } +func (m *CanonicalVote) String() string { return proto.CompactTextString(m) } +func (*CanonicalVote) ProtoMessage() {} +func (*CanonicalVote) Descriptor() ([]byte, []int) { + return fileDescriptor_3f9b1d584b46f180, []int{3} +} +func (m *CanonicalVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalVote.Merge(m, src) +} +func (m *CanonicalVote) XXX_Size() int { + return m.Size() +} +func (m *CanonicalVote) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalVote.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalVote proto.InternalMessageInfo + +func (m *CanonicalVote) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return SIGNED_MSG_TYPE_UNKNOWN +} + +func (m *CanonicalVote) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *CanonicalVote) GetRound() int64 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CanonicalVote) GetBlockID() CanonicalBlockID { + if m != nil { + return m.BlockID + } + return CanonicalBlockID{} +} + +func (m *CanonicalVote) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *CanonicalVote) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func init() { + proto.RegisterType((*CanonicalBlockID)(nil), "tendermint.proto.types.CanonicalBlockID") + proto.RegisterType((*CanonicalPartSetHeader)(nil), "tendermint.proto.types.CanonicalPartSetHeader") + proto.RegisterType((*CanonicalProposal)(nil), "tendermint.proto.types.CanonicalProposal") + proto.RegisterType((*CanonicalVote)(nil), "tendermint.proto.types.CanonicalVote") +} + +func init() { proto.RegisterFile("proto/types/canonical.proto", fileDescriptor_3f9b1d584b46f180) } + +var fileDescriptor_3f9b1d584b46f180 = []byte{ + // 482 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x53, 0x4f, 0x8b, 0xd3, 0x40, + 0x14, 0x6f, 0xba, 0xdd, 0x36, 0x9d, 0x76, 0xfd, 0x33, 0x48, 0x0d, 0x15, 0x92, 0x52, 0x70, 0xa9, + 0x20, 0x09, 0xac, 0x27, 0xaf, 0xb3, 0x22, 0x16, 0x14, 0x97, 0xd9, 0xa2, 0xe0, 0xa5, 0x4c, 0x93, + 0x31, 0x19, 0x4c, 0x33, 0x21, 0x99, 0x1e, 0x7a, 0xf2, 0x2b, 0xec, 0xe7, 0xf1, 0x13, 0xec, 0x71, + 0x8f, 0x9e, 0xaa, 0xa4, 0x27, 0xbf, 0x85, 0xcc, 0x9b, 0xfe, 0x3b, 0x54, 0xbc, 0x09, 0x5e, 0xc2, + 0x7b, 0xbf, 0xf7, 0xde, 0xef, 0xfd, 0xf2, 0x7b, 0x0c, 0x7a, 0x92, 0x17, 0x52, 0xc9, 0x40, 0x2d, + 0x73, 0x5e, 0x06, 0x21, 0xcb, 0x64, 0x26, 0x42, 0x96, 0xfa, 0x80, 0xe2, 0x9e, 0xe2, 0x59, 0xc4, + 0x8b, 0xb9, 0xc8, 0x94, 0x41, 0x7c, 0xe8, 0xeb, 0x9f, 0xab, 0x44, 0x14, 0xd1, 0x34, 0x67, 0x85, + 0x5a, 0x06, 0x86, 0x20, 0x96, 0xb1, 0xdc, 0x47, 0xa6, 0xbb, 0xff, 0xf8, 0x90, 0x1c, 0xbe, 0x9b, + 0x82, 0x17, 0x4b, 0x19, 0xa7, 0xdc, 0xcc, 0xce, 0x16, 0x9f, 0x03, 0x25, 0xe6, 0xbc, 0x54, 0x6c, + 0x9e, 0x9b, 0x86, 0xe1, 0x57, 0xf4, 0xe0, 0x72, 0x2b, 0x86, 0xa4, 0x32, 0xfc, 0x32, 0x7e, 0x85, + 0x31, 0x6a, 0x24, 0xac, 0x4c, 0x1c, 0x6b, 0x60, 0x8d, 0xba, 0x14, 0x62, 0xfc, 0x11, 0x75, 0xb5, + 0x8a, 0x72, 0x9a, 0x70, 0x16, 0xf1, 0xc2, 0xa9, 0x0f, 0xac, 0x51, 0xe7, 0xc2, 0xf7, 0x8f, 0x0b, + 0xf7, 0x77, 0x9c, 0x57, 0xac, 0x50, 0xd7, 0x5c, 0xbd, 0x81, 0x29, 0xd2, 0xb8, 0x5d, 0x79, 0x35, + 0xda, 0x01, 0x26, 0x03, 0x0d, 0x09, 0xea, 0x1d, 0x6f, 0x3e, 0x2a, 0xe3, 0x11, 0x3a, 0x55, 0x52, + 0xb1, 0x14, 0xf6, 0x9f, 0x51, 0x93, 0x0c, 0x7f, 0xd5, 0xd1, 0xc3, 0x3d, 0x49, 0x21, 0x73, 0x59, + 0xb2, 0x14, 0xbf, 0x44, 0x0d, 0x2d, 0x06, 0xe6, 0xef, 0x5d, 0x3c, 0xfd, 0x93, 0xd4, 0x6b, 0x11, + 0x67, 0x3c, 0x7a, 0x57, 0xc6, 0x93, 0x65, 0xce, 0x29, 0x8c, 0xe0, 0x1e, 0x6a, 0x26, 0x5c, 0xc4, + 0x89, 0x82, 0x3d, 0x27, 0x74, 0x93, 0xe9, 0xf5, 0x85, 0x5c, 0x64, 0x91, 0x73, 0x02, 0xb0, 0x49, + 0xf0, 0x33, 0xd4, 0xce, 0x65, 0x3a, 0x35, 0x95, 0x86, 0xae, 0x90, 0x6e, 0xb5, 0xf2, 0xec, 0xab, + 0xf7, 0x6f, 0xa9, 0xc6, 0xa8, 0x9d, 0xcb, 0x14, 0x22, 0x3c, 0x41, 0xf6, 0x4c, 0xbb, 0x3c, 0x15, + 0x91, 0x73, 0x0a, 0x16, 0x8e, 0xfe, 0x6a, 0xe1, 0xe6, 0x2c, 0xe4, 0xbe, 0x36, 0xaf, 0x5a, 0x79, + 0xad, 0x0d, 0x40, 0x5b, 0x40, 0x35, 0x8e, 0x30, 0x41, 0xed, 0xdd, 0x5d, 0x9d, 0x26, 0xd0, 0xf6, + 0x7d, 0x73, 0x79, 0x7f, 0x7b, 0x79, 0x7f, 0xb2, 0xed, 0x20, 0xb6, 0x26, 0xba, 0xf9, 0xe1, 0x59, + 0x74, 0x3f, 0x86, 0xcf, 0x91, 0x1d, 0x26, 0x4c, 0x64, 0x5a, 0x59, 0x6b, 0x60, 0x8d, 0xda, 0xa4, + 0xa3, 0x77, 0x5d, 0x6a, 0x4c, 0xef, 0x82, 0xe2, 0x38, 0x1a, 0x7e, 0xab, 0xa3, 0xb3, 0x9d, 0xb4, + 0x0f, 0x52, 0xf1, 0x7f, 0xe7, 0xf3, 0x7f, 0x6f, 0x1e, 0x79, 0x7d, 0x5b, 0xb9, 0xd6, 0x5d, 0xe5, + 0x5a, 0x3f, 0x2b, 0xd7, 0xba, 0x59, 0xbb, 0xb5, 0xbb, 0xb5, 0x5b, 0xfb, 0xbe, 0x76, 0x6b, 0x9f, + 0x9e, 0xc7, 0x42, 0x25, 0x8b, 0x99, 0x1f, 0xca, 0x79, 0xb0, 0xff, 0xa7, 0xc3, 0xf0, 0xe0, 0x89, + 0xcf, 0x9a, 0x90, 0xbc, 0xf8, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb9, 0x73, 0xb0, 0x8c, 0x55, 0x04, + 0x00, 0x00, +} + +func (m *CanonicalBlockID) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalBlockID) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalBlockID) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PartsHeader.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CanonicalPartSetHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalPartSetHeader) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalPartSetHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Total != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Total)) + i-- + dAtA[i] = 0x10 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CanonicalProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x3a + } + n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintCanonical(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x32 + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.POLRound != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.POLRound)) + i-- + dAtA[i] = 0x20 + } + if m.Round != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x18 + } + if m.Height != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.Type != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CanonicalVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x3a + } + n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintCanonical(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x32 + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.Round != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x18 + } + if m.Height != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.Type != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintCanonical(dAtA []byte, offset int, v uint64) int { + offset -= sovCanonical(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *CanonicalBlockID) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + l = m.PartsHeader.Size() + n += 1 + l + sovCanonical(uint64(l)) + return n +} + +func (m *CanonicalPartSetHeader) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + if m.Total != 0 { + n += 1 + sovCanonical(uint64(m.Total)) + } + return n +} + +func (m *CanonicalProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovCanonical(uint64(m.Type)) + } + if m.Height != 0 { + n += 1 + sovCanonical(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovCanonical(uint64(m.Round)) + } + if m.POLRound != 0 { + n += 1 + sovCanonical(uint64(m.POLRound)) + } + l = m.BlockID.Size() + n += 1 + l + sovCanonical(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovCanonical(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + return n +} + +func (m *CanonicalVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovCanonical(uint64(m.Type)) + } + if m.Height != 0 { + n += 1 + sovCanonical(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovCanonical(uint64(m.Round)) + } + l = m.BlockID.Size() + n += 1 + l + sovCanonical(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovCanonical(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + return n +} + +func sovCanonical(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCanonical(x uint64) (n int) { + return sovCanonical(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *CanonicalBlockID) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalBlockID: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalBlockID: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PartsHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PartsHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalPartSetHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalPartSetHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalPartSetHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + m.Total = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Total |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field POLRound", wireType) + } + m.POLRound = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.POLRound |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCanonical(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCanonical + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCanonical + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCanonical + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCanonical = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCanonical = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCanonical = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/types/canonical.proto b/proto/types/canonical.proto new file mode 100644 index 000000000..431461bbc --- /dev/null +++ b/proto/types/canonical.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; +package tendermint.proto.types; + +option go_package = "github.com/tendermint/tendermint/proto/types"; + +import "third_party/proto/gogoproto/gogo.proto"; +import "proto/types/types.proto"; +import "google/protobuf/timestamp.proto"; + +message CanonicalBlockID { + bytes hash = 1; + CanonicalPartSetHeader parts_header = 2 [(gogoproto.nullable) = false]; +} + +message CanonicalPartSetHeader { + bytes hash = 1; + uint32 total = 2; +} + +message CanonicalProposal { + SignedMsgType type = 1; // type alias for byte + int64 height = 2; + int64 round = 3; + int64 pol_round = 4 [(gogoproto.customname) = "POLRound"]; + CanonicalBlockID block_id = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 7 [(gogoproto.customname) = "ChainID"]; +} + +message CanonicalVote { + SignedMsgType type = 1; // type alias for byte + int64 height = 2; + int64 round = 3; + CanonicalBlockID block_id = 5 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 7 [(gogoproto.customname) = "ChainID"]; +} diff --git a/proto/types/types.pb.go b/proto/types/types.pb.go index 68d7d927e..be75cbcb8 100644 --- a/proto/types/types.pb.go +++ b/proto/types/types.pb.go @@ -54,6 +54,10 @@ var BlockIDFlag_value = map[string]int32{ "BLOCK_ID_FLAG_NIL": 3, } +func (x BlockIDFlag) String() string { + return proto.EnumName(BlockIDFlag_name, int32(x)) +} + func (BlockIDFlag) EnumDescriptor() ([]byte, []int) { return fileDescriptor_ff06f8095857fb18, []int{0} } @@ -82,6 +86,10 @@ var SignedMsgType_value = map[string]int32{ "PROPOSAL_TYPE": 3, } +func (x SignedMsgType) String() string { + return proto.EnumName(SignedMsgType_name, int32(x)) +} + func (SignedMsgType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_ff06f8095857fb18, []int{1} } @@ -951,86 +959,86 @@ func init() { proto.RegisterFile("proto/types/types.proto", fileDescriptor_ff06f var fileDescriptor_ff06f8095857fb18 = []byte{ // 1274 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4f, 0x6f, 0x1a, 0x47, - 0x14, 0x67, 0x61, 0x31, 0xf0, 0x00, 0x1b, 0xaf, 0xdc, 0x84, 0xe2, 0x16, 0x13, 0xdc, 0xa4, 0x4e, - 0x1a, 0x41, 0xe5, 0x4a, 0x55, 0x23, 0xf5, 0x02, 0x86, 0x38, 0x28, 0x36, 0xa0, 0x85, 0xa6, 0x6a, - 0x2f, 0xab, 0x81, 0x9d, 0x2c, 0xab, 0x2c, 0xbb, 0xab, 0xdd, 0xc1, 0x32, 0x39, 0xf4, 0x5c, 0xf9, - 0x94, 0x2f, 0xe0, 0x53, 0x5a, 0xa9, 0xdf, 0xa2, 0x3d, 0xe6, 0x54, 0xe5, 0xd8, 0x53, 0x5a, 0xd9, - 0xdf, 0xa0, 0xea, 0x07, 0xa8, 0xe6, 0xcf, 0x2e, 0x10, 0x4c, 0x1b, 0x35, 0x51, 0x2f, 0xf6, 0xce, - 0x7b, 0xbf, 0xdf, 0x9b, 0x79, 0xbf, 0xf9, 0xcd, 0x8c, 0x80, 0xeb, 0xae, 0xe7, 0x10, 0xa7, 0x4a, - 0xa6, 0x2e, 0xf6, 0xf9, 0xdf, 0x0a, 0x8b, 0x28, 0xd7, 0x08, 0xb6, 0x75, 0xec, 0x8d, 0x4d, 0x9b, - 0xf0, 0x48, 0x85, 0x65, 0x0b, 0xb7, 0xc8, 0xc8, 0xf4, 0x74, 0xcd, 0x45, 0x1e, 0x99, 0x56, 0x39, - 0xd9, 0x70, 0x0c, 0x67, 0xf6, 0xc5, 0xd1, 0x85, 0x1d, 0xc3, 0x71, 0x0c, 0x0b, 0x73, 0xc8, 0x60, - 0xf2, 0xb8, 0x4a, 0xcc, 0x31, 0xf6, 0x09, 0x1a, 0xbb, 0x02, 0xb0, 0xcd, 0x29, 0x96, 0x39, 0xf0, - 0xab, 0x03, 0x93, 0x2c, 0xcc, 0x5e, 0xd8, 0xe1, 0xc9, 0xa1, 0x37, 0x75, 0x89, 0x53, 0x1d, 0x63, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1a, 0x47, + 0x18, 0xf6, 0xc2, 0x62, 0xe0, 0x05, 0x6c, 0xbc, 0x72, 0x13, 0x8a, 0x5b, 0x4c, 0x70, 0x93, 0x3a, + 0x69, 0x04, 0x95, 0x2b, 0x55, 0x8d, 0xd4, 0x0b, 0x5f, 0x71, 0x50, 0x6c, 0x40, 0x0b, 0x4d, 0xd5, + 0x5e, 0x56, 0x03, 0x3b, 0x59, 0x56, 0x59, 0x76, 0x57, 0xbb, 0x83, 0x65, 0x72, 0xe8, 0xb9, 0xf2, + 0x29, 0x7f, 0xc0, 0xa7, 0xb4, 0x52, 0xff, 0x45, 0x7b, 0xcc, 0xa9, 0xca, 0xb1, 0xa7, 0xb4, 0xb2, + 0xff, 0x41, 0xd5, 0x1f, 0x50, 0xcd, 0xc7, 0x2e, 0x10, 0x4c, 0x1b, 0x35, 0x51, 0x2f, 0xf6, 0xce, + 0xfb, 0x3e, 0xcf, 0x3b, 0xf3, 0x3e, 0xf3, 0xcc, 0x8c, 0x80, 0xeb, 0xae, 0xe7, 0x10, 0xa7, 0x42, + 0xa6, 0x2e, 0xf6, 0xf9, 0xdf, 0x32, 0x8b, 0x28, 0xd7, 0x08, 0xb6, 0x75, 0xec, 0x8d, 0x4d, 0x9b, + 0xf0, 0x48, 0x99, 0x65, 0xf3, 0xb7, 0xc8, 0xc8, 0xf4, 0x74, 0xcd, 0x45, 0x1e, 0x99, 0x56, 0x38, + 0xd9, 0x70, 0x0c, 0x67, 0xf6, 0xc5, 0xd1, 0xf9, 0x5d, 0xc3, 0x71, 0x0c, 0x0b, 0x73, 0xc8, 0x60, + 0xf2, 0xb8, 0x42, 0xcc, 0x31, 0xf6, 0x09, 0x1a, 0xbb, 0x02, 0xb0, 0xc3, 0x29, 0x96, 0x39, 0xf0, + 0x2b, 0x03, 0x93, 0x2c, 0xcc, 0x9e, 0xdf, 0xe5, 0xc9, 0xa1, 0x37, 0x75, 0x89, 0x53, 0x19, 0x63, 0xef, 0x89, 0x85, 0x17, 0x00, 0x82, 0x7d, 0x82, 0x3d, 0xdf, 0x74, 0xec, 0xe0, 0x3f, 0x4f, 0x96, - 0xef, 0x41, 0xb6, 0x8b, 0x3c, 0xd2, 0xc3, 0xe4, 0x01, 0x46, 0x3a, 0xf6, 0x94, 0x2d, 0x88, 0x13, - 0x87, 0x20, 0x2b, 0x2f, 0x95, 0xa4, 0xbd, 0xac, 0xca, 0x07, 0x8a, 0x02, 0xf2, 0x08, 0xf9, 0xa3, - 0x7c, 0xb4, 0x24, 0xed, 0x65, 0x54, 0xf6, 0x5d, 0x9e, 0x80, 0x4c, 0xa9, 0x94, 0x61, 0xda, 0x3a, - 0x3e, 0x0d, 0x18, 0x6c, 0x40, 0xa3, 0x83, 0x29, 0xc1, 0xbe, 0xa0, 0xf0, 0x81, 0x52, 0x83, 0xb8, - 0xeb, 0x39, 0xce, 0xe3, 0x7c, 0xac, 0x24, 0xed, 0xa5, 0xf7, 0x6f, 0x56, 0x96, 0xa4, 0xe3, 0x7d, - 0x54, 0x78, 0x1f, 0x95, 0x2e, 0x05, 0xd7, 0xe5, 0x17, 0xaf, 0x76, 0x22, 0x2a, 0x67, 0x96, 0xc7, - 0x90, 0xa8, 0x5b, 0xce, 0xf0, 0x49, 0xab, 0x11, 0xae, 0x4a, 0x9a, 0xad, 0x4a, 0x69, 0x43, 0x86, - 0x0a, 0xee, 0x6b, 0x23, 0xd6, 0x0f, 0x9b, 0xfe, 0xca, 0x89, 0xb8, 0x44, 0x0b, 0xcd, 0x8b, 0x89, - 0xd2, 0xac, 0x00, 0x0f, 0x95, 0xff, 0x94, 0x61, 0x4d, 0x48, 0x73, 0x00, 0x09, 0x21, 0x1e, 0x9b, - 0x31, 0xbd, 0xbf, 0xbb, 0x5c, 0x35, 0x50, 0xf7, 0xc0, 0xb1, 0x7d, 0x6c, 0xfb, 0x13, 0x5f, 0xd4, - 0x0c, 0x98, 0xca, 0x2d, 0x48, 0x0e, 0x47, 0xc8, 0xb4, 0x35, 0x53, 0x67, 0x6b, 0x4b, 0xd5, 0xd3, - 0x17, 0xaf, 0x76, 0x12, 0x07, 0x34, 0xd6, 0x6a, 0xa8, 0x09, 0x96, 0x6c, 0xe9, 0xca, 0x35, 0x58, - 0x1b, 0x61, 0xd3, 0x18, 0x11, 0x26, 0x55, 0x4c, 0x15, 0x23, 0xe5, 0x0b, 0x90, 0xa9, 0x3d, 0xf2, - 0x32, 0x5b, 0x41, 0xa1, 0xc2, 0xbd, 0x53, 0x09, 0xbc, 0x53, 0xe9, 0x07, 0xde, 0xa9, 0x27, 0xe9, - 0xc4, 0xcf, 0x7e, 0xdf, 0x91, 0x54, 0xc6, 0x50, 0x5a, 0x90, 0xb5, 0x90, 0x4f, 0xb4, 0x01, 0x55, - 0x8f, 0x4e, 0x1f, 0x67, 0x25, 0x76, 0x56, 0x49, 0x23, 0x54, 0x0e, 0x44, 0xa1, 0x5c, 0x1e, 0xd2, - 0x95, 0x3d, 0xc8, 0xb1, 0x52, 0x43, 0x67, 0x3c, 0x36, 0x89, 0xc6, 0x36, 0x61, 0x8d, 0x6d, 0xc2, - 0x3a, 0x8d, 0x1f, 0xb0, 0xf0, 0x03, 0xba, 0x1d, 0xdb, 0x90, 0xd2, 0x11, 0x41, 0x1c, 0x92, 0x60, - 0x90, 0x24, 0x0d, 0xb0, 0xe4, 0xc7, 0xb0, 0x71, 0x82, 0x2c, 0x53, 0x47, 0xc4, 0xf1, 0x7c, 0x0e, - 0x49, 0xf2, 0x2a, 0xb3, 0x30, 0x03, 0x7e, 0x0a, 0x5b, 0x36, 0x3e, 0x25, 0xda, 0xeb, 0xe8, 0x14, - 0x43, 0x2b, 0x34, 0xf7, 0x68, 0x91, 0x71, 0x13, 0xd6, 0x87, 0xc1, 0x16, 0x70, 0x2c, 0x30, 0x6c, - 0x36, 0x8c, 0x32, 0xd8, 0xfb, 0x90, 0x44, 0xae, 0xcb, 0x01, 0x69, 0x06, 0x48, 0x20, 0xd7, 0x65, - 0xa9, 0x3b, 0xb0, 0xc9, 0x7a, 0xf4, 0xb0, 0x3f, 0xb1, 0x88, 0x28, 0x92, 0x61, 0x98, 0x0d, 0x9a, - 0x50, 0x79, 0x9c, 0x61, 0x77, 0x21, 0x8b, 0x4f, 0x4c, 0x1d, 0xdb, 0x43, 0xcc, 0x71, 0x59, 0x86, - 0xcb, 0x04, 0x41, 0x06, 0xba, 0x0d, 0x39, 0xd7, 0x73, 0x5c, 0xc7, 0xc7, 0x9e, 0x86, 0x74, 0xdd, - 0xc3, 0xbe, 0x9f, 0x5f, 0xe7, 0xf5, 0x82, 0x78, 0x8d, 0x87, 0xcb, 0x77, 0x41, 0x6e, 0x20, 0x82, - 0x94, 0x1c, 0xc4, 0xc8, 0xa9, 0x9f, 0x97, 0x4a, 0xb1, 0xbd, 0x8c, 0x4a, 0x3f, 0xaf, 0x3c, 0x88, - 0x7f, 0x45, 0x41, 0x7e, 0xe4, 0x10, 0xac, 0xdc, 0x03, 0x99, 0x6e, 0x1d, 0x73, 0xe7, 0xfa, 0x6a, - 0xcf, 0xf7, 0x4c, 0xc3, 0xc6, 0xfa, 0xb1, 0x6f, 0xf4, 0xa7, 0x2e, 0x56, 0x19, 0x65, 0xce, 0x6e, - 0xd1, 0x05, 0xbb, 0x6d, 0x41, 0xdc, 0x73, 0x26, 0xb6, 0xce, 0x5c, 0x18, 0x57, 0xf9, 0x40, 0x79, - 0x08, 0xc9, 0xd0, 0x45, 0xf2, 0x9b, 0xb9, 0x68, 0x83, 0xba, 0x88, 0x3a, 0x5d, 0x04, 0xd4, 0xc4, - 0x40, 0x98, 0xa9, 0x0e, 0xa9, 0xf0, 0xc2, 0x13, 0x9e, 0x7c, 0x33, 0x5b, 0xcf, 0x68, 0xca, 0x27, - 0xb0, 0x19, 0x7a, 0x23, 0x14, 0x97, 0x3b, 0x32, 0x17, 0x26, 0x84, 0xba, 0x0b, 0xb6, 0xd3, 0xf8, - 0xd5, 0x95, 0x60, 0xdd, 0xcd, 0x6c, 0xd7, 0x62, 0x77, 0xd8, 0x07, 0x90, 0xf2, 0x4d, 0xc3, 0x46, - 0x64, 0xe2, 0x61, 0xe1, 0xcc, 0x59, 0xa0, 0xfc, 0x3c, 0x0a, 0x6b, 0xdc, 0xe9, 0x73, 0xea, 0x49, - 0x57, 0xab, 0x17, 0x5d, 0xa5, 0x5e, 0xec, 0x6d, 0xd5, 0x3b, 0x04, 0x08, 0x97, 0xe4, 0xe7, 0xe5, - 0x52, 0x6c, 0x2f, 0xbd, 0x7f, 0x63, 0x55, 0x39, 0xbe, 0xdc, 0x9e, 0x69, 0x88, 0x43, 0x3d, 0x47, - 0x0d, 0x9d, 0x15, 0x9f, 0xbb, 0x4c, 0x6b, 0x90, 0x1a, 0x98, 0x44, 0x43, 0x9e, 0x87, 0xa6, 0x4c, - 0xce, 0xf4, 0xfe, 0x47, 0xcb, 0xb5, 0xe9, 0xbb, 0x54, 0xa1, 0xef, 0x52, 0xa5, 0x6e, 0x92, 0x1a, - 0xc5, 0xaa, 0xc9, 0x81, 0xf8, 0x2a, 0x5f, 0x4a, 0x90, 0x0a, 0xa7, 0x55, 0x0e, 0x21, 0x1b, 0xb4, - 0xae, 0x3d, 0xb6, 0x90, 0x21, 0xac, 0xba, 0xfb, 0x2f, 0xfd, 0xdf, 0xb7, 0x90, 0xa1, 0xa6, 0x45, - 0xcb, 0x74, 0x70, 0xf5, 0x86, 0x47, 0x57, 0x6c, 0xf8, 0x82, 0xc3, 0x62, 0xff, 0xcd, 0x61, 0x0b, - 0x5e, 0x90, 0x5f, 0xf7, 0xc2, 0xcf, 0x51, 0x48, 0x76, 0xd9, 0x21, 0x46, 0xd6, 0xff, 0x77, 0x0c, - 0xb7, 0x21, 0xe5, 0x3a, 0x96, 0xc6, 0x33, 0x32, 0xcb, 0x24, 0x5d, 0xc7, 0x52, 0x97, 0x5c, 0x16, - 0x7f, 0xa7, 0x67, 0x74, 0xed, 0x1d, 0x28, 0x98, 0x78, 0x5d, 0xc1, 0xef, 0x20, 0xc3, 0x05, 0x11, - 0x8f, 0xed, 0xe7, 0x54, 0x09, 0xf6, 0x82, 0xf3, 0xb7, 0xb6, 0xb8, 0x6a, 0xf1, 0x1c, 0xaf, 0x0a, - 0x34, 0xe5, 0xf1, 0x57, 0x49, 0xbc, 0xfc, 0xc5, 0x7f, 0x3e, 0x0b, 0xaa, 0x40, 0x97, 0x7f, 0x95, - 0x20, 0xc5, 0xda, 0x3e, 0xc6, 0x04, 0x2d, 0x88, 0x27, 0xbd, 0xad, 0x78, 0x1f, 0x02, 0xf0, 0x62, - 0xbe, 0xf9, 0x14, 0x8b, 0x8d, 0x4d, 0xb1, 0x48, 0xcf, 0x7c, 0x8a, 0x95, 0x2f, 0xc3, 0x4e, 0x63, - 0x6f, 0xd2, 0xa9, 0x38, 0xba, 0x41, 0xbf, 0xd7, 0x21, 0x61, 0x4f, 0xc6, 0x1a, 0x7d, 0x26, 0x64, - 0x6e, 0x19, 0x7b, 0x32, 0xee, 0x9f, 0xfa, 0x77, 0x7e, 0x91, 0x20, 0x3d, 0x77, 0x7c, 0x94, 0x02, - 0x5c, 0xab, 0x1f, 0x75, 0x0e, 0x1e, 0x36, 0xb4, 0x56, 0x43, 0xbb, 0x7f, 0x54, 0x3b, 0xd4, 0xbe, - 0x6a, 0x3f, 0x6c, 0x77, 0xbe, 0x6e, 0xe7, 0x22, 0x4a, 0x15, 0xb6, 0x58, 0x2e, 0x4c, 0xd5, 0xea, - 0xbd, 0x66, 0xbb, 0x9f, 0x93, 0x0a, 0xef, 0x9d, 0x9d, 0x97, 0x36, 0xe7, 0xca, 0xd4, 0x06, 0x3e, - 0xb6, 0xc9, 0x32, 0xe1, 0xa0, 0x73, 0x7c, 0xdc, 0xea, 0xe7, 0xa2, 0x4b, 0x04, 0x71, 0x43, 0xde, - 0x86, 0xcd, 0x45, 0x42, 0xbb, 0x75, 0x94, 0x8b, 0x15, 0x94, 0xb3, 0xf3, 0xd2, 0xfa, 0x1c, 0xba, - 0x6d, 0x5a, 0x85, 0xe4, 0xf7, 0xcf, 0x8b, 0x91, 0x9f, 0x7e, 0x28, 0x46, 0xee, 0xfc, 0x28, 0x41, - 0x76, 0xe1, 0x94, 0x28, 0xdb, 0x70, 0xbd, 0xd7, 0x3a, 0x6c, 0x37, 0x1b, 0xda, 0x71, 0xef, 0x50, - 0xeb, 0x7f, 0xd3, 0x6d, 0xce, 0x75, 0x71, 0x03, 0x32, 0x5d, 0xb5, 0xf9, 0xa8, 0xd3, 0x6f, 0xb2, - 0x4c, 0x4e, 0x2a, 0x6c, 0x9c, 0x9d, 0x97, 0xd2, 0x5d, 0x0f, 0x9f, 0x38, 0x04, 0x33, 0xfe, 0x4d, - 0x58, 0xef, 0xaa, 0x4d, 0xbe, 0x58, 0x0e, 0x8a, 0x16, 0x36, 0xcf, 0xce, 0x4b, 0xd9, 0xae, 0x87, - 0xb9, 0x11, 0x18, 0x6c, 0x17, 0xb2, 0x5d, 0xb5, 0xd3, 0xed, 0xf4, 0x6a, 0x47, 0x1c, 0x15, 0x2b, - 0xe4, 0xce, 0xce, 0x4b, 0x99, 0xe0, 0x88, 0x53, 0xd0, 0x6c, 0x9d, 0xf5, 0xfb, 0x2f, 0x2e, 0x8a, - 0xd2, 0xcb, 0x8b, 0xa2, 0xf4, 0xc7, 0x45, 0x51, 0x7a, 0x76, 0x59, 0x8c, 0xbc, 0xbc, 0x2c, 0x46, - 0x7e, 0xbb, 0x2c, 0x46, 0xbe, 0xbd, 0x6b, 0x98, 0x64, 0x34, 0x19, 0x54, 0x86, 0xce, 0xb8, 0x3a, - 0xdb, 0xd5, 0xf9, 0xcf, 0xb9, 0x1f, 0x15, 0x83, 0x35, 0x36, 0xf8, 0xec, 0xef, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x5f, 0xad, 0x08, 0x71, 0x6a, 0x0c, 0x00, 0x00, + 0xee, 0x41, 0xa6, 0x8b, 0x3c, 0xd2, 0xc3, 0xe4, 0x01, 0x46, 0x3a, 0xf6, 0x94, 0x6d, 0x88, 0x11, + 0x87, 0x20, 0x2b, 0x27, 0x15, 0xa5, 0xfd, 0x8c, 0xca, 0x07, 0x8a, 0x02, 0xf2, 0x08, 0xf9, 0xa3, + 0x5c, 0xa4, 0x28, 0xed, 0xa7, 0x55, 0xf6, 0x5d, 0x9a, 0x80, 0x4c, 0xa9, 0x94, 0x61, 0xda, 0x3a, + 0x3e, 0x0d, 0x18, 0x6c, 0x40, 0xa3, 0x83, 0x29, 0xc1, 0xbe, 0xa0, 0xf0, 0x81, 0x52, 0x85, 0x98, + 0xeb, 0x39, 0xce, 0xe3, 0x5c, 0xb4, 0x28, 0xed, 0xa7, 0x0e, 0x6e, 0x96, 0x97, 0xa4, 0xe3, 0x7d, + 0x94, 0x79, 0x1f, 0xe5, 0x2e, 0x05, 0xd7, 0xe4, 0x17, 0xaf, 0x76, 0xd7, 0x54, 0xce, 0x2c, 0x8d, + 0x21, 0x5e, 0xb3, 0x9c, 0xe1, 0x93, 0x56, 0x23, 0x5c, 0x95, 0x34, 0x5b, 0x95, 0xd2, 0x86, 0x34, + 0x15, 0xdc, 0xd7, 0x46, 0xac, 0x1f, 0x36, 0xfd, 0x95, 0x13, 0x71, 0x89, 0x16, 0x9a, 0x17, 0x13, + 0xa5, 0x58, 0x01, 0x1e, 0x2a, 0xfd, 0x29, 0xc3, 0xba, 0x90, 0xa6, 0x0e, 0x71, 0x21, 0x1e, 0x9b, + 0x31, 0x75, 0xb0, 0xb7, 0x5c, 0x35, 0x50, 0xb7, 0xee, 0xd8, 0x3e, 0xb6, 0xfd, 0x89, 0x2f, 0x6a, + 0x06, 0x4c, 0xe5, 0x16, 0x24, 0x86, 0x23, 0x64, 0xda, 0x9a, 0xa9, 0xb3, 0xb5, 0x25, 0x6b, 0xa9, + 0x8b, 0x57, 0xbb, 0xf1, 0x3a, 0x8d, 0xb5, 0x1a, 0x6a, 0x9c, 0x25, 0x5b, 0xba, 0x72, 0x0d, 0xd6, + 0x47, 0xd8, 0x34, 0x46, 0x84, 0x49, 0x15, 0x55, 0xc5, 0x48, 0xf9, 0x02, 0x64, 0x6a, 0x8f, 0x9c, + 0xcc, 0x56, 0x90, 0x2f, 0x73, 0xef, 0x94, 0x03, 0xef, 0x94, 0xfb, 0x81, 0x77, 0x6a, 0x09, 0x3a, + 0xf1, 0xb3, 0xdf, 0x77, 0x25, 0x95, 0x31, 0x94, 0x16, 0x64, 0x2c, 0xe4, 0x13, 0x6d, 0x40, 0xd5, + 0xa3, 0xd3, 0xc7, 0x58, 0x89, 0xdd, 0x55, 0xd2, 0x08, 0x95, 0x03, 0x51, 0x28, 0x97, 0x87, 0x74, + 0x65, 0x1f, 0xb2, 0xac, 0xd4, 0xd0, 0x19, 0x8f, 0x4d, 0xa2, 0xb1, 0x4d, 0x58, 0x67, 0x9b, 0xb0, + 0x41, 0xe3, 0x75, 0x16, 0x7e, 0x40, 0xb7, 0x63, 0x07, 0x92, 0x3a, 0x22, 0x88, 0x43, 0xe2, 0x0c, + 0x92, 0xa0, 0x01, 0x96, 0xfc, 0x18, 0x36, 0x4f, 0x90, 0x65, 0xea, 0x88, 0x38, 0x9e, 0xcf, 0x21, + 0x09, 0x5e, 0x65, 0x16, 0x66, 0xc0, 0x4f, 0x61, 0xdb, 0xc6, 0xa7, 0x44, 0x7b, 0x1d, 0x9d, 0x64, + 0x68, 0x85, 0xe6, 0x1e, 0x2d, 0x32, 0x6e, 0xc2, 0xc6, 0x30, 0xd8, 0x02, 0x8e, 0x05, 0x86, 0xcd, + 0x84, 0x51, 0x06, 0x7b, 0x1f, 0x12, 0xc8, 0x75, 0x39, 0x20, 0xc5, 0x00, 0x71, 0xe4, 0xba, 0x2c, + 0x75, 0x07, 0xb6, 0x58, 0x8f, 0x1e, 0xf6, 0x27, 0x16, 0x11, 0x45, 0xd2, 0x0c, 0xb3, 0x49, 0x13, + 0x2a, 0x8f, 0x33, 0xec, 0x1e, 0x64, 0xf0, 0x89, 0xa9, 0x63, 0x7b, 0x88, 0x39, 0x2e, 0xc3, 0x70, + 0xe9, 0x20, 0xc8, 0x40, 0xb7, 0x21, 0xeb, 0x7a, 0x8e, 0xeb, 0xf8, 0xd8, 0xd3, 0x90, 0xae, 0x7b, + 0xd8, 0xf7, 0x73, 0x1b, 0xbc, 0x5e, 0x10, 0xaf, 0xf2, 0x70, 0xe9, 0x2e, 0xc8, 0x0d, 0x44, 0x90, + 0x92, 0x85, 0x28, 0x39, 0xf5, 0x73, 0x52, 0x31, 0xba, 0x9f, 0x56, 0xe9, 0xe7, 0x95, 0x07, 0xf1, + 0xaf, 0x08, 0xc8, 0x8f, 0x1c, 0x82, 0x95, 0x7b, 0x20, 0xd3, 0xad, 0x63, 0xee, 0xdc, 0x58, 0xed, + 0xf9, 0x9e, 0x69, 0xd8, 0x58, 0x3f, 0xf6, 0x8d, 0xfe, 0xd4, 0xc5, 0x2a, 0xa3, 0xcc, 0xd9, 0x2d, + 0xb2, 0x60, 0xb7, 0x6d, 0x88, 0x79, 0xce, 0xc4, 0xd6, 0x99, 0x0b, 0x63, 0x2a, 0x1f, 0x28, 0x0f, + 0x21, 0x11, 0xba, 0x48, 0x7e, 0x33, 0x17, 0x6d, 0x52, 0x17, 0x51, 0xa7, 0x8b, 0x80, 0x1a, 0x1f, + 0x08, 0x33, 0xd5, 0x20, 0x19, 0x5e, 0x78, 0xc2, 0x93, 0x6f, 0x66, 0xeb, 0x19, 0x4d, 0xf9, 0x04, + 0xb6, 0x42, 0x6f, 0x84, 0xe2, 0x72, 0x47, 0x66, 0xc3, 0x84, 0x50, 0x77, 0xc1, 0x76, 0x1a, 0xbf, + 0xba, 0xe2, 0xac, 0xbb, 0x99, 0xed, 0x5a, 0xec, 0x0e, 0xfb, 0x00, 0x92, 0xbe, 0x69, 0xd8, 0x88, + 0x4c, 0x3c, 0x2c, 0x9c, 0x39, 0x0b, 0x94, 0x9e, 0x47, 0x60, 0x9d, 0x3b, 0x7d, 0x4e, 0x3d, 0xe9, + 0x6a, 0xf5, 0x22, 0xab, 0xd4, 0x8b, 0xbe, 0xad, 0x7a, 0x87, 0x00, 0xe1, 0x92, 0xfc, 0x9c, 0x5c, + 0x8c, 0xee, 0xa7, 0x0e, 0x6e, 0xac, 0x2a, 0xc7, 0x97, 0xdb, 0x33, 0x0d, 0x71, 0xa8, 0xe7, 0xa8, + 0xa1, 0xb3, 0x62, 0x73, 0x97, 0x69, 0x15, 0x92, 0x03, 0x93, 0x68, 0xc8, 0xf3, 0xd0, 0x94, 0xc9, + 0x99, 0x3a, 0xf8, 0x68, 0xb9, 0x36, 0x7d, 0x97, 0xca, 0xf4, 0x5d, 0x2a, 0xd7, 0x4c, 0x52, 0xa5, + 0x58, 0x35, 0x31, 0x10, 0x5f, 0xa5, 0x4b, 0x09, 0x92, 0xe1, 0xb4, 0xca, 0x21, 0x64, 0x82, 0xd6, + 0xb5, 0xc7, 0x16, 0x32, 0x84, 0x55, 0xf7, 0xfe, 0xa5, 0xff, 0xfb, 0x16, 0x32, 0xd4, 0x94, 0x68, + 0x99, 0x0e, 0xae, 0xde, 0xf0, 0xc8, 0x8a, 0x0d, 0x5f, 0x70, 0x58, 0xf4, 0xbf, 0x39, 0x6c, 0xc1, + 0x0b, 0xf2, 0xeb, 0x5e, 0xf8, 0x39, 0x02, 0x89, 0x2e, 0x3b, 0xc4, 0xc8, 0xfa, 0xff, 0x8e, 0xe1, + 0x0e, 0x24, 0x5d, 0xc7, 0xd2, 0x78, 0x46, 0x66, 0x99, 0x84, 0xeb, 0x58, 0xea, 0x92, 0xcb, 0x62, + 0xef, 0xf4, 0x8c, 0xae, 0xbf, 0x03, 0x05, 0xe3, 0xaf, 0x2b, 0xf8, 0x1d, 0xa4, 0xb9, 0x20, 0xe2, + 0xb1, 0xfd, 0x9c, 0x2a, 0xc1, 0x5e, 0x70, 0xfe, 0xd6, 0x16, 0x56, 0x2d, 0x9e, 0xe3, 0x55, 0x81, + 0xa6, 0x3c, 0xfe, 0x2a, 0x89, 0x97, 0xbf, 0xf0, 0xcf, 0x67, 0x41, 0x15, 0xe8, 0xd2, 0xaf, 0x12, + 0x24, 0x59, 0xdb, 0xc7, 0x98, 0xa0, 0x05, 0xf1, 0xa4, 0xb7, 0x15, 0xef, 0x43, 0x00, 0x5e, 0xcc, + 0x37, 0x9f, 0x62, 0xb1, 0xb1, 0x49, 0x16, 0xe9, 0x99, 0x4f, 0xb1, 0xf2, 0x65, 0xd8, 0x69, 0xf4, + 0x4d, 0x3a, 0x15, 0x47, 0x37, 0xe8, 0xf7, 0x3a, 0xc4, 0xed, 0xc9, 0x58, 0xa3, 0xcf, 0x84, 0xcc, + 0x2d, 0x63, 0x4f, 0xc6, 0xfd, 0x53, 0xff, 0xce, 0x2f, 0x12, 0xa4, 0xe6, 0x8e, 0x8f, 0x92, 0x87, + 0x6b, 0xb5, 0xa3, 0x4e, 0xfd, 0x61, 0x43, 0x6b, 0x35, 0xb4, 0xfb, 0x47, 0xd5, 0x43, 0xed, 0xab, + 0xf6, 0xc3, 0x76, 0xe7, 0xeb, 0x76, 0x76, 0x4d, 0xa9, 0xc0, 0x36, 0xcb, 0x85, 0xa9, 0x6a, 0xad, + 0xd7, 0x6c, 0xf7, 0xb3, 0x52, 0xfe, 0xbd, 0xb3, 0xf3, 0xe2, 0xd6, 0x5c, 0x99, 0xea, 0xc0, 0xc7, + 0x36, 0x59, 0x26, 0xd4, 0x3b, 0xc7, 0xc7, 0xad, 0x7e, 0x36, 0xb2, 0x44, 0x10, 0x37, 0xe4, 0x6d, + 0xd8, 0x5a, 0x24, 0xb4, 0x5b, 0x47, 0xd9, 0x68, 0x5e, 0x39, 0x3b, 0x2f, 0x6e, 0xcc, 0xa1, 0xdb, + 0xa6, 0x95, 0x4f, 0x7c, 0xff, 0xbc, 0xb0, 0xf6, 0xd3, 0x0f, 0x05, 0xe9, 0xce, 0x8f, 0x12, 0x64, + 0x16, 0x4e, 0x89, 0xb2, 0x03, 0xd7, 0x7b, 0xad, 0xc3, 0x76, 0xb3, 0xa1, 0x1d, 0xf7, 0x0e, 0xb5, + 0xfe, 0x37, 0xdd, 0xe6, 0x5c, 0x17, 0x37, 0x20, 0xdd, 0x55, 0x9b, 0x8f, 0x3a, 0xfd, 0x26, 0xcb, + 0x64, 0xa5, 0xfc, 0xe6, 0xd9, 0x79, 0x31, 0xd5, 0xf5, 0xf0, 0x89, 0x43, 0x30, 0xe3, 0xdf, 0x84, + 0x8d, 0xae, 0xda, 0xe4, 0x8b, 0xe5, 0xa0, 0x48, 0x7e, 0xeb, 0xec, 0xbc, 0x98, 0xe9, 0x7a, 0x98, + 0x1b, 0x81, 0xc1, 0xf6, 0x20, 0xd3, 0x55, 0x3b, 0xdd, 0x4e, 0xaf, 0x7a, 0xc4, 0x51, 0xd1, 0x7c, + 0xf6, 0xec, 0xbc, 0x98, 0x0e, 0x8e, 0x38, 0x05, 0xcd, 0xd6, 0x59, 0xbb, 0xff, 0xe2, 0xa2, 0x20, + 0xbd, 0xbc, 0x28, 0x48, 0x7f, 0x5c, 0x14, 0xa4, 0x67, 0x97, 0x85, 0xb5, 0x97, 0x97, 0x85, 0xb5, + 0xdf, 0x2e, 0x0b, 0x6b, 0xdf, 0xde, 0x35, 0x4c, 0x32, 0x9a, 0x0c, 0xca, 0x43, 0x67, 0x5c, 0x99, + 0xed, 0xea, 0xfc, 0xe7, 0xdc, 0x8f, 0x8a, 0xc1, 0x3a, 0x1b, 0x7c, 0xf6, 0x77, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x94, 0x73, 0x22, 0x3b, 0x6a, 0x0c, 0x00, 0x00, } func (m *PartSetHeader) Marshal() (dAtA []byte, err error) { diff --git a/proto/types/types.proto b/proto/types/types.proto index 8663ad6f7..1a16d1a67 100644 --- a/proto/types/types.proto +++ b/proto/types/types.proto @@ -11,7 +11,7 @@ import "proto/version/version.proto"; // BlockIdFlag indicates which BlcokID the signature is for enum BlockIDFlag { - option (gogoproto.goproto_enum_stringer) = false; + option (gogoproto.goproto_enum_stringer) = true; option (gogoproto.goproto_enum_prefix) = false; BLOCKD_ID_FLAG_UNKNOWN = 0; @@ -22,7 +22,7 @@ enum BlockIDFlag { // SignedMsgType is a type of signed message in the consensus. enum SignedMsgType { - option (gogoproto.goproto_enum_stringer) = false; + option (gogoproto.goproto_enum_stringer) = true; option (gogoproto.goproto_enum_prefix) = false; SIGNED_MSG_TYPE_UNKNOWN = 0; diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index 71f6a4b9b..b64753216 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -25,10 +25,14 @@ func newEvidence(t *testing.T, val *privval.FilePV, chainID string) *types.DuplicateVoteEvidence { var err error - vote.Signature, err = val.Key.PrivKey.Sign(vote.SignBytes(chainID)) + + v := vote.ToProto() + v2 := vote2.ToProto() + + vote.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v)) require.NoError(t, err) - vote2.Signature, err = val.Key.PrivKey.Sign(vote2.SignBytes(chainID)) + vote2.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2)) require.NoError(t, err) return types.NewDuplicateVoteEvidence(vote, vote2) @@ -197,8 +201,12 @@ func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) { Type: tmproto.PrecommitType, BlockID: h2.Commit.BlockID, } - signBytes, err := pv.Key.PrivKey.Sign(vote.SignBytes(chainID)) + + v := vote.ToProto() + signBytes, err := pv.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v)) require.NoError(t, err) + vote.Signature = v.Signature + h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time) t.Logf("h1 AppHash: %X", h1.AppHash) diff --git a/state/tx_filter_test.go b/state/tx_filter_test.go index cfa03818a..482db4563 100644 --- a/state/tx_filter_test.go +++ b/state/tx_filter_test.go @@ -26,7 +26,7 @@ func TestTxFilter(t *testing.T) { isErr bool }{ {types.Tx(tmrand.Bytes(1680)), false}, - {types.Tx(tmrand.Bytes(1839)), true}, + {types.Tx(tmrand.Bytes(1853)), true}, {types.Tx(tmrand.Bytes(3000)), true}, } diff --git a/state/validation_test.go b/state/validation_test.go index 89f6e311f..808e9d0d4 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -195,11 +195,17 @@ func TestValidateBlockCommit(t *testing.T) { Type: tmproto.PrecommitType, BlockID: blockID, } - err = badPrivVal.SignVote(chainID, goodVote) + + g := goodVote.ToProto() + b := badVote.ToProto() + + err = badPrivVal.SignVote(chainID, g) require.NoError(t, err, "height %d", height) - err = badPrivVal.SignVote(chainID, badVote) + err = badPrivVal.SignVote(chainID, b) require.NoError(t, err, "height %d", height) + goodVote.Signature, badVote.Signature = g.Signature, b.Signature + wrongSigsCommit = types.NewCommit(goodVote.Height, goodVote.Round, blockID, []types.CommitSig{goodVote.CommitSig(), badVote.CommitSig()}) } @@ -358,10 +364,14 @@ func TestValidateAmnesiaEvidence(t *testing.T) { state, stateDB, vals := makeState(1, int(height)) addr, val := state.Validators.GetByIndex(0) voteA := makeVote(height, 1, 0, addr, blockID) - err := vals[val.Address.String()].SignVote(chainID, voteA) + vA := voteA.ToProto() + err := vals[val.Address.String()].SignVote(chainID, vA) + voteA.Signature = vA.Signature require.NoError(t, err) voteB := makeVote(height, 2, 0, addr, types.BlockID{}) - err = vals[val.Address.String()].SignVote(chainID, voteB) + vB := voteB.ToProto() + err = vals[val.Address.String()].SignVote(chainID, vB) + voteB.Signature = vB.Signature require.NoError(t, err) ae := types.AmnesiaEvidence{ PotentialAmnesiaEvidence: types.PotentialAmnesiaEvidence{ @@ -434,13 +444,19 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) { addr, val := state.Validators.GetByIndex(0) addr2, val2 := state.Validators.GetByIndex(1) voteA := makeVote(height, 1, 0, addr, types.BlockID{}) - err := vals[val.Address.String()].SignVote(chainID, voteA) + vA := voteA.ToProto() + err := vals[val.Address.String()].SignVote(chainID, vA) + voteA.Signature = vA.Signature require.NoError(t, err) voteB := makeVote(height, 2, 0, addr, blockID) - err = vals[val.Address.String()].SignVote(chainID, voteB) + vB := voteB.ToProto() + err = vals[val.Address.String()].SignVote(chainID, vB) + voteB.Signature = vB.Signature require.NoError(t, err) voteC := makeVote(height, 2, 1, addr2, blockID) - err = vals[val2.Address.String()].SignVote(chainID, voteC) + vC := voteC.ToProto() + err = vals[val2.Address.String()].SignVote(chainID, vC) + voteC.Signature = vC.Signature require.NoError(t, err) //var ae types.Evidence badAe := types.AmnesiaEvidence{ @@ -460,11 +476,15 @@ func TestVerifyEvidenceWithAmnesiaEvidence(t *testing.T) { } addr3, val3 := state.Validators.GetByIndex(2) voteD := makeVote(height, 2, 2, addr3, blockID) - err = vals[val3.Address.String()].SignVote(chainID, voteD) + vD := voteD.ToProto() + err = vals[val3.Address.String()].SignVote(chainID, vD) require.NoError(t, err) + voteD.Signature = vD.Signature addr4, val4 := state.Validators.GetByIndex(3) voteE := makeVote(height, 2, 3, addr4, blockID) - err = vals[val4.Address.String()].SignVote(chainID, voteE) + vE := voteE.ToProto() + err = vals[val4.Address.String()].SignVote(chainID, vE) + voteE.Signature = vE.Signature require.NoError(t, err) goodAe := types.AmnesiaEvidence{ @@ -513,7 +533,9 @@ func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) { ProposerAddress: crypto.AddressHash([]byte("proposer_address")), } vote := makeVote(3, 1, 0, addr, blockID) - err := vals[val.Address.String()].SignVote(chainID, vote) + v := vote.ToProto() + err := vals[val.Address.String()].SignVote(chainID, v) + vote.Signature = v.Signature require.NoError(t, err) ev := types.LunaticValidatorEvidence{ Header: h, @@ -533,7 +555,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) { state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1 addr, val := state.Validators.GetByIndex(0) vote := makeVote(3, 1, 0, addr, blockID) - err := vals[val.Address.String()].SignVote(chainID, vote) + v := vote.ToProto() + err := vals[val.Address.String()].SignVote(chainID, v) + vote.Signature = v.Signature require.NoError(t, err) ev := types.PhantomValidatorEvidence{ Vote: vote, @@ -549,7 +573,9 @@ func TestVerifyEvidenceWithPhantomValidatorEvidence(t *testing.T) { privVal := types.NewMockPV() pubKey, _ := privVal.GetPubKey() vote2 := makeVote(3, 1, 0, pubKey.Address(), blockID) - err = privVal.SignVote(chainID, vote2) + v2 := vote2.ToProto() + err = privVal.SignVote(chainID, v2) + vote2.Signature = v2.Signature require.NoError(t, err) ev = types.PhantomValidatorEvidence{ Vote: vote2, diff --git a/tools/tm-signer-harness/internal/test_harness.go b/tools/tm-signer-harness/internal/test_harness.go index 0f3f03628..d1018edca 100644 --- a/tools/tm-signer-harness/internal/test_harness.go +++ b/tools/tm-signer-harness/internal/test_harness.go @@ -229,11 +229,13 @@ func (th *TestHarness) TestSignProposal() error { }, Timestamp: time.Now(), } - propBytes := prop.SignBytes(th.chainID) - if err := th.signerClient.SignProposal(th.chainID, prop); err != nil { + p := prop.ToProto() + propBytes := types.ProposalSignBytes(th.chainID, p) + if err := th.signerClient.SignProposal(th.chainID, p); err != nil { th.logger.Error("FAILED: Signing of proposal", "err", err) return newTestHarnessError(ErrTestSignProposalFailed, err, "") } + prop.Signature = p.Signature th.logger.Debug("Signed proposal", "prop", prop) // first check that it's a basically valid proposal if err := prop.ValidateBasic(); err != nil { @@ -276,12 +278,14 @@ func (th *TestHarness) TestSignVote() error { ValidatorAddress: tmhash.SumTruncated([]byte("addr")), Timestamp: time.Now(), } - voteBytes := vote.SignBytes(th.chainID) + v := vote.ToProto() + voteBytes := types.VoteSignBytes(th.chainID, v) // sign the vote - if err := th.signerClient.SignVote(th.chainID, vote); err != nil { + if err := th.signerClient.SignVote(th.chainID, v); err != nil { th.logger.Error("FAILED: Signing of vote", "err", err) return newTestHarnessError(ErrTestSignVoteFailed, err, fmt.Sprintf("voteType=%d", voteType)) } + vote.Signature = v.Signature th.logger.Debug("Signed vote", "vote", vote) // validate the contents of the vote if err := vote.ValidateBasic(); err != nil { diff --git a/tools/tm-signer-harness/internal/test_harness_test.go b/tools/tm-signer-harness/internal/test_harness_test.go index 28d0d61c4..b18938969 100644 --- a/tools/tm-signer-harness/internal/test_harness_test.go +++ b/tools/tm-signer-harness/internal/test_harness_test.go @@ -23,7 +23,7 @@ const ( "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc=" - }, + }, "priv_key": { "type": "tendermint/PrivKeyEd25519", "value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw==" diff --git a/types/block.go b/types/block.go index 0c3194ac1..78b0e1c94 100644 --- a/types/block.go +++ b/types/block.go @@ -773,7 +773,8 @@ func (commit *Commit) GetVote(valIdx int32) *Vote { // signed over are otherwise the same for all validators. // Panics if valIdx >= commit.Size(). func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte { - return commit.GetVote(valIdx).SignBytes(chainID) + v := commit.GetVote(valIdx).ToProto() + return VoteSignBytes(chainID, v) } // Type returns the vote type of the commit, which is always VoteTypePrecommit diff --git a/types/block_test.go b/types/block_test.go index 5bb0cd18e..1e4e56b80 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -378,9 +378,9 @@ func TestBlockMaxDataBytes(t *testing.T) { }{ 0: {-10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0}, - 2: {849, 1, 0, true, 0}, - 3: {850, 1, 0, false, 0}, - 4: {851, 1, 0, false, 1}, + 2: {846, 1, 0, true, 0}, + 3: {848, 1, 0, false, 0}, + 4: {849, 1, 0, false, 1}, } for i, tc := range testCases { @@ -408,10 +408,10 @@ func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { }{ 0: {-10, 0, 1, true, 0}, 1: {10, 0, 1, true, 0}, - 2: {849, 0, 1, true, 0}, - 3: {850, 0, 1, false, 0}, - 4: {1294, 1, 1, false, 0}, - 5: {1295, 1, 1, false, 1}, + 2: {847, 0, 1, true, 0}, + 3: {848, 0, 1, false, 0}, + 4: {1292, 1, 1, false, 0}, + 5: {1293, 1, 1, false, 1}, } for i, tc := range testCases { diff --git a/types/canonical.go b/types/canonical.go index 72295aad4..a8d552f1b 100644 --- a/types/canonical.go +++ b/types/canonical.go @@ -3,7 +3,6 @@ package types import ( "time" - "github.com/tendermint/tendermint/libs/bytes" tmproto "github.com/tendermint/tendermint/proto/types" tmtime "github.com/tendermint/tendermint/types/time" ) @@ -13,66 +12,37 @@ import ( // TimeFormat is used for generating the sigs const TimeFormat = time.RFC3339Nano -type CanonicalBlockID struct { - Hash bytes.HexBytes - PartsHeader CanonicalPartSetHeader -} - -type CanonicalPartSetHeader struct { - Hash bytes.HexBytes - Total uint32 -} - -type CanonicalProposal struct { - Type tmproto.SignedMsgType // type alias for byte - Height int64 `binary:"fixed64"` - Round int64 `binary:"fixed64"` - POLRound int64 `binary:"fixed64"` - BlockID CanonicalBlockID - Timestamp time.Time - ChainID string -} - -type CanonicalVote struct { - Type tmproto.SignedMsgType // type alias for byte - Height int64 `binary:"fixed64"` - Round int64 `binary:"fixed64"` - BlockID CanonicalBlockID - Timestamp time.Time - ChainID string -} - //----------------------------------- // Canonicalize the structs -func CanonicalizeBlockID(blockID BlockID) CanonicalBlockID { - return CanonicalBlockID{ +func CanonicalizeBlockID(blockID tmproto.BlockID) tmproto.CanonicalBlockID { + return tmproto.CanonicalBlockID{ Hash: blockID.Hash, PartsHeader: CanonicalizePartSetHeader(blockID.PartsHeader), } } -func CanonicalizePartSetHeader(psh PartSetHeader) CanonicalPartSetHeader { - return CanonicalPartSetHeader{ - psh.Hash, - psh.Total, +func CanonicalizePartSetHeader(psh tmproto.PartSetHeader) tmproto.CanonicalPartSetHeader { + return tmproto.CanonicalPartSetHeader{ + Hash: psh.Hash, + Total: psh.Total, } } -func CanonicalizeProposal(chainID string, proposal *Proposal) CanonicalProposal { - return CanonicalProposal{ +func CanonicalizeProposal(chainID string, proposal *tmproto.Proposal) tmproto.CanonicalProposal { + return tmproto.CanonicalProposal{ Type: tmproto.ProposalType, Height: proposal.Height, Round: int64(proposal.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) - POLRound: int64(proposal.POLRound), + POLRound: int64(proposal.PolRound), BlockID: CanonicalizeBlockID(proposal.BlockID), Timestamp: proposal.Timestamp, ChainID: chainID, } } -func CanonicalizeVote(chainID string, vote *Vote) CanonicalVote { - return CanonicalVote{ +func CanonicalizeVote(chainID string, vote *tmproto.Vote) tmproto.CanonicalVote { + return tmproto.CanonicalVote{ Type: vote.Type, Height: vote.Height, Round: int64(vote.Round), // cast int->int64 to make amino encode it fixed64 (does not work for int) diff --git a/types/evidence.go b/types/evidence.go index 15f00950a..7e8adb084 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -463,12 +463,13 @@ func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) e return fmt.Errorf("address (%X) doesn't match pubkey (%v - %X)", addr, pubKey, pubKey.Address()) } - + va := dve.VoteA.ToProto() + vb := dve.VoteB.ToProto() // Signatures must be valid - if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) { + if !pubKey.VerifyBytes(VoteSignBytes(chainID, va), dve.VoteA.Signature) { return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature) } - if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) { + if !pubKey.VerifyBytes(VoteSignBytes(chainID, vb), dve.VoteB.Signature) { return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature) } @@ -841,8 +842,8 @@ func (e PhantomValidatorEvidence) Bytes() []byte { func (e PhantomValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) error { - // signature must be verified to the chain ID - if !pubKey.VerifyBytes(e.Vote.SignBytes(chainID), e.Vote.Signature) { + v := e.Vote.ToProto() + if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), e.Vote.Signature) { return errors.New("invalid signature") } @@ -930,7 +931,8 @@ func (e LunaticValidatorEvidence) Verify(chainID string, pubKey crypto.PubKey) e ) } - if !pubKey.VerifyBytes(e.Vote.SignBytes(chainID), e.Vote.Signature) { + v := e.Vote.ToProto() + if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), e.Vote.Signature) { return errors.New("invalid signature") } @@ -1072,11 +1074,14 @@ func (e PotentialAmnesiaEvidence) Verify(chainID string, pubKey crypto.PubKey) e addr, pubKey, pubKey.Address()) } + va := e.VoteA.ToProto() + vb := e.VoteB.ToProto() + // Signatures must be valid - if !pubKey.VerifyBytes(e.VoteA.SignBytes(chainID), e.VoteA.Signature) { + if !pubKey.VerifyBytes(VoteSignBytes(chainID, va), e.VoteA.Signature) { return fmt.Errorf("verifying VoteA: %w", ErrVoteInvalidSignature) } - if !pubKey.VerifyBytes(e.VoteB.SignBytes(chainID), e.VoteB.Signature) { + if !pubKey.VerifyBytes(VoteSignBytes(chainID, vb), e.VoteB.Signature) { return fmt.Errorf("verifying VoteB: %w", ErrVoteInvalidSignature) } @@ -1247,7 +1252,8 @@ func (e ProofOfLockChange) ValidateVotes(valSet *ValidatorSet, chainID string) e for _, validator := range valSet.Validators { if bytes.Equal(validator.Address, vote.ValidatorAddress) { exists = true - if !validator.PubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) { + v := vote.ToProto() + if !validator.PubKey.VerifyBytes(VoteSignBytes(chainID, v), vote.Signature) { return fmt.Errorf("cannot verify vote (from validator: %d) against signature: %v", vote.ValidatorIndex, vote.Signature) } @@ -1615,7 +1621,13 @@ func NewMockPOLC(height int64, time time.Time, pubKey crypto.PubKey) ProofOfLock pKey, _ := voteVal.GetPubKey() vote := Vote{Type: tmproto.PrecommitType, Height: height, Round: 1, BlockID: BlockID{}, Timestamp: time, ValidatorAddress: pKey.Address(), ValidatorIndex: 1, Signature: []byte{}} - _ = voteVal.SignVote("mock-chain-id", &vote) + + v := vote.ToProto() + if err := voteVal.SignVote("mock-chain-id", v); err != nil { + panic(err) + } + vote.Signature = v.Signature + return ProofOfLockChange{ Votes: []Vote{vote}, PubKey: pubKey, diff --git a/types/evidence_test.go b/types/evidence_test.go index d26919b59..d0aa4a193 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -34,12 +34,17 @@ func TestEvidence(t *testing.T) { const chainID = "mychain" vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime) - err := val.SignVote(chainID, vote1) + v1 := vote1.ToProto() + err := val.SignVote(chainID, v1) require.NoError(t, err) badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID, defaultVoteTime) - err = val2.SignVote(chainID, badVote) + bv := badVote.ToProto() + err = val2.SignVote(chainID, bv) require.NoError(t, err) + vote1.Signature = v1.Signature + badVote.Signature = bv.Signature + cases := []voteData{ {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, defaultVoteTime), true}, // different block ids {vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3, defaultVoteTime), true}, @@ -542,10 +547,13 @@ func makeVote( BlockID: blockID, Timestamp: time, } - err = val.SignVote(chainID, v) + + vpb := v.ToProto() + err = val.SignVote(chainID, vpb) if err != nil { panic(err) } + v.Signature = vpb.Signature return v } diff --git a/types/priv_validator.go b/types/priv_validator.go index de1407150..b3750a58d 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + tmproto "github.com/tendermint/tendermint/proto/types" ) // PrivValidator defines the functionality of a local Tendermint validator @@ -14,8 +15,8 @@ import ( type PrivValidator interface { GetPubKey() (crypto.PubKey, error) - SignVote(chainID string, vote *Vote) error - SignProposal(chainID string, proposal *Proposal) error + SignVote(chainID string, vote *tmproto.Vote) error + SignProposal(chainID string, proposal *tmproto.Proposal) error } type PrivValidatorsByAddress []PrivValidator @@ -71,12 +72,13 @@ func (pv MockPV) GetPubKey() (crypto.PubKey, error) { } // Implements PrivValidator. -func (pv MockPV) SignVote(chainID string, vote *Vote) error { +func (pv MockPV) SignVote(chainID string, vote *tmproto.Vote) error { useChainID := chainID if pv.breakVoteSigning { useChainID = "incorrect-chain-id" } - signBytes := vote.SignBytes(useChainID) + + signBytes := VoteSignBytes(useChainID, vote) sig, err := pv.PrivKey.Sign(signBytes) if err != nil { return err @@ -86,12 +88,13 @@ func (pv MockPV) SignVote(chainID string, vote *Vote) error { } // Implements PrivValidator. -func (pv MockPV) SignProposal(chainID string, proposal *Proposal) error { +func (pv MockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error { useChainID := chainID if pv.breakProposalSigning { useChainID = "incorrect-chain-id" } - signBytes := proposal.SignBytes(useChainID) + + signBytes := ProposalSignBytes(useChainID, proposal) sig, err := pv.PrivKey.Sign(signBytes) if err != nil { return err @@ -128,12 +131,12 @@ type ErroringMockPV struct { var ErroringMockPVErr = errors.New("erroringMockPV always returns an error") // Implements PrivValidator. -func (pv *ErroringMockPV) SignVote(chainID string, vote *Vote) error { +func (pv *ErroringMockPV) SignVote(chainID string, vote *tmproto.Vote) error { return ErroringMockPVErr } // Implements PrivValidator. -func (pv *ErroringMockPV) SignProposal(chainID string, proposal *Proposal) error { +func (pv *ErroringMockPV) SignProposal(chainID string, proposal *tmproto.Proposal) error { return ErroringMockPVErr } diff --git a/types/proposal.go b/types/proposal.go index e71d506ec..f4b6a8f8f 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "github.com/gogo/protobuf/proto" + "github.com/tendermint/tendermint/libs/bytes" tmproto "github.com/tendermint/tendermint/proto/types" tmtime "github.com/tendermint/tendermint/types/time" @@ -71,6 +73,7 @@ func (p *Proposal) ValidateBasic() error { if len(p.Signature) == 0 { return errors.New("signature is missing") } + if len(p.Signature) > MaxSignatureSize { return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) } @@ -88,9 +91,10 @@ func (p *Proposal) String() string { CanonicalTime(p.Timestamp)) } -// SignBytes returns the Proposal bytes for signing -func (p *Proposal) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, p)) +// ProposalSignBytes returns the Proposal bytes for signing +func ProposalSignBytes(chainID string, p *tmproto.Proposal) []byte { + pb := CanonicalizeProposal(chainID, p) + bz, err := proto.Marshal(&pb) if err != nil { panic(err) } @@ -100,7 +104,7 @@ func (p *Proposal) SignBytes(chainID string) []byte { // ToProto converts Proposal to protobuf func (p *Proposal) ToProto() *tmproto.Proposal { if p == nil { - return nil + return &tmproto.Proposal{} } pb := new(tmproto.Proposal) diff --git a/types/proposal_test.go b/types/proposal_test.go index eee6893f9..ba611e9c6 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -5,14 +5,19 @@ import ( "testing" "time" + "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/tmhash" + tmrand "github.com/tendermint/tendermint/libs/rand" tmproto "github.com/tendermint/tendermint/proto/types" ) -var testProposal *Proposal +var ( + testProposal *Proposal + pbp *tmproto.Proposal +) func init() { var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z") @@ -26,13 +31,14 @@ func init() { POLRound: -1, Timestamp: stamp, } + pbp = testProposal.ToProto() } func TestProposalSignable(t *testing.T) { chainID := "test_chain_id" - signBytes := testProposal.SignBytes(chainID) - - expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeProposal(chainID, testProposal)) + signBytes := ProposalSignBytes(chainID, pbp) + pb := CanonicalizeProposal(chainID, pbp) + expected, err := proto.Marshal(&pb) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Proposal") } @@ -52,41 +58,49 @@ func TestProposalVerifySignature(t *testing.T) { prop := NewProposal( 4, 2, 2, - BlockID{[]byte{1, 2, 3}, PartSetHeader{777, []byte("proper")}}) - signBytes := prop.SignBytes("test_chain_id") + BlockID{tmrand.Bytes(tmhash.Size), PartSetHeader{777, tmrand.Bytes(tmhash.Size)}}) + p := prop.ToProto() + signBytes := ProposalSignBytes("test_chain_id", p) // sign it - err = privVal.SignProposal("test_chain_id", prop) + err = privVal.SignProposal("test_chain_id", p) require.NoError(t, err) + prop.Signature = p.Signature // verify the same proposal valid := pubKey.VerifyBytes(signBytes, prop.Signature) require.True(t, valid) // serialize, deserialize and verify again.... - newProp := new(Proposal) - bs, err := cdc.MarshalBinaryLengthPrefixed(prop) + newProp := new(tmproto.Proposal) + pb := prop.ToProto() + + bs, err := proto.Marshal(pb) require.NoError(t, err) - err = cdc.UnmarshalBinaryLengthPrefixed(bs, &newProp) + + err = proto.Unmarshal(bs, newProp) + require.NoError(t, err) + + np, err := ProposalFromProto(newProp) require.NoError(t, err) // verify the transmitted proposal - newSignBytes := newProp.SignBytes("test_chain_id") + newSignBytes := ProposalSignBytes("test_chain_id", pb) require.Equal(t, string(signBytes), string(newSignBytes)) - valid = pubKey.VerifyBytes(newSignBytes, newProp.Signature) + valid = pubKey.VerifyBytes(newSignBytes, np.Signature) require.True(t, valid) } func BenchmarkProposalWriteSignBytes(b *testing.B) { for i := 0; i < b.N; i++ { - testProposal.SignBytes("test_chain_id") + ProposalSignBytes("test_chain_id", pbp) } } func BenchmarkProposalSign(b *testing.B) { privVal := NewMockPV() for i := 0; i < b.N; i++ { - err := privVal.SignProposal("test_chain_id", testProposal) + err := privVal.SignProposal("test_chain_id", pbp) if err != nil { b.Error(err) } @@ -95,13 +109,13 @@ func BenchmarkProposalSign(b *testing.B) { func BenchmarkProposalVerifySignature(b *testing.B) { privVal := NewMockPV() - err := privVal.SignProposal("test_chain_id", testProposal) + err := privVal.SignProposal("test_chain_id", pbp) require.NoError(b, err) pubKey, err := privVal.GetPubKey() require.NoError(b, err) for i := 0; i < b.N; i++ { - pubKey.VerifyBytes(testProposal.SignBytes("test_chain_id"), testProposal.Signature) + pubKey.VerifyBytes(ProposalSignBytes("test_chain_id", pbp), testProposal.Signature) } } @@ -136,7 +150,9 @@ func TestProposalValidateBasic(t *testing.T) { prop := NewProposal( 4, 2, 2, blockID) - err := privVal.SignProposal("test_chain_id", prop) + p := prop.ToProto() + err := privVal.SignProposal("test_chain_id", p) + prop.Signature = p.Signature require.NoError(t, err) tc.malleateProposal(prop) assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") diff --git a/types/test_util.go b/types/test_util.go index ff5ab7381..639987ebf 100644 --- a/types/test_util.go +++ b/types/test_util.go @@ -36,10 +36,12 @@ func MakeCommit(blockID BlockID, height int64, round int32, } func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) { - err = privVal.SignVote(voteSet.ChainID(), vote) + v := vote.ToProto() + err = privVal.SignVote(voteSet.ChainID(), v) if err != nil { return false, err } + vote.Signature = v.Signature return voteSet.AddVote(vote) } @@ -66,9 +68,14 @@ func MakeVote( Type: tmproto.PrecommitType, BlockID: blockID, } - if err := privVal.SignVote(chainID, vote); err != nil { + v := vote.ToProto() + + if err := privVal.SignVote(chainID, v); err != nil { return nil, err } + + vote.Signature = v.Signature + return vote, nil } diff --git a/types/validator_set_test.go b/types/validator_set_test.go index 5e275ed30..cb04177de 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -667,7 +667,9 @@ func TestValidatorSetVerifyCommit(t *testing.T) { Type: tmproto.PrecommitType, BlockID: blockID, } - sig, err := privKey.Sign(vote.SignBytes(chainID)) + + v := vote.ToProto() + sig, err := privKey.Sign(VoteSignBytes(chainID, v)) assert.NoError(t, err) vote.Signature = sig commit := NewCommit(vote.Height, vote.Round, blockID, []CommitSig{vote.CommitSig()}) diff --git a/types/vote.go b/types/vote.go index cbd1429ac..3bab2d707 100644 --- a/types/vote.go +++ b/types/vote.go @@ -6,6 +6,8 @@ import ( "fmt" "time" + "github.com/gogo/protobuf/proto" + "github.com/tendermint/tendermint/crypto" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmproto "github.com/tendermint/tendermint/proto/types" @@ -13,7 +15,7 @@ import ( const ( // MaxVoteBytes is a maximum vote size (including amino overhead). - MaxVoteBytes int64 = 211 + MaxVoteBytes int64 = 209 nilVoteStr string = "nil-Vote" ) @@ -81,8 +83,11 @@ func (vote *Vote) CommitSig() CommitSig { } } -func (vote *Vote) SignBytes(chainID string) []byte { - bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote(chainID, vote)) +//VoteSignBytes take the chainID & a vote, represented in protobuf, and creates a signature. +// If any error arises this will panic +func VoteSignBytes(chainID string, vote *tmproto.Vote) []byte { + pb := CanonicalizeVote(chainID, vote) + bz, err := proto.Marshal(&pb) if err != nil { panic(err) } @@ -126,8 +131,8 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) { return ErrVoteInvalidValidatorAddress } - - if !pubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) { + v := vote.ToProto() + if !pubKey.VerifyBytes(VoteSignBytes(chainID, v), vote.Signature) { return ErrVoteInvalidSignature } return nil @@ -152,11 +157,13 @@ func (vote *Vote) ValidateBasic() error { if err := vote.BlockID.ValidateBasic(); err != nil { return fmt.Errorf("wrong BlockID: %v", err) } + // BlockID.ValidateBasic would not err if we for instance have an empty hash but a // non-empty PartsSetHeader: if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() { return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID) } + if len(vote.ValidatorAddress) != crypto.AddressSize { return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes", crypto.AddressSize, @@ -169,9 +176,11 @@ func (vote *Vote) ValidateBasic() error { if len(vote.Signature) == 0 { return errors.New("signature is missing") } + if len(vote.Signature) > MaxSignatureSize { return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) } + return nil } diff --git a/types/vote_test.go b/types/vote_test.go index b19bc55bb..48e4b9dd4 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -47,9 +48,11 @@ func exampleVote(t byte) *Vote { func TestVoteSignable(t *testing.T) { vote := examplePrecommit() - signBytes := vote.SignBytes("test_chain_id") + v := vote.ToProto() + signBytes := VoteSignBytes("test_chain_id", v) + pb := CanonicalizeVote("test_chain_id", v) - expected, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote("test_chain_id", vote)) + expected, err := proto.Marshal(&pb) require.NoError(t, err) require.Equal(t, expected, signBytes, "Got unexpected sign bytes for Vote.") @@ -65,79 +68,47 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0: { "", &Vote{}, // NOTE: Height and Round are skipped here. This case needs to be considered while parsing. - []byte{0xd, 0x2a, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + []byte{0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8, + 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // with proper (fixed size) height and round (PreCommit): 1: { "", &Vote{Height: 1, Round: 1, Type: tmproto.PrecommitType}, - []byte{ - 0x21, // length - 0x8, // (field_number << 3) | wire_type - 0x2, // PrecommitType - 0x11, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x2a, // (field_number << 3) | wire_type - // remaining fields (timestamp): + []byte{0x8, 0x2, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // with proper (fixed size) height and round (PreVote): 2: { "", &Vote{Height: 1, Round: 1, Type: tmproto.PrevoteType}, - []byte{ - 0x21, // length - 0x8, // (field_number << 3) | wire_type - 0x1, // PrevoteType - 0x11, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - 0x2a, // (field_number << 3) | wire_type - // remaining fields (timestamp): - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + []byte{0x8, 0x1, 0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, + 0x32, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, 3: { "", &Vote{Height: 1, Round: 1}, - []byte{ - 0x1f, // length - 0x11, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - // remaining fields (timestamp): - 0x2a, - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + []byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, + 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, }, // containing non-empty chain_id: 4: { "test_chain_id", &Vote{Height: 1, Round: 1}, - []byte{ - 0x2e, // length - 0x11, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height - 0x19, // (field_number << 3) | wire_type - 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - // remaining fields: - 0x2a, // (field_number << 3) | wire_type - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, // timestamp - // (field_number << 3) | wire_type - 0x32, - 0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, // chainID + []byte{0x10, 0x1, 0x18, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0xb, 0x8, + 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, 0x3a, 0xd, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, }, } for i, tc := range tests { - got := tc.vote.SignBytes(tc.chainID) + v := tc.vote.ToProto() + got := VoteSignBytes(tc.chainID, v) require.Equal(t, tc.want, got, "test case #%v: got unexpected sign bytes for Vote.", i) } } func TestVoteProposalNotEq(t *testing.T) { - cv := CanonicalizeVote("", &Vote{Height: 1, Round: 1}) - p := CanonicalizeProposal("", &Proposal{Height: 1, Round: 1}) - vb, err := cdc.MarshalBinaryLengthPrefixed(cv) + cv := CanonicalizeVote("", &tmproto.Vote{Height: 1, Round: 1}) + p := CanonicalizeProposal("", &tmproto.Proposal{Height: 1, Round: 1}) + vb, err := proto.Marshal(&cv) require.NoError(t, err) - pb, err := cdc.MarshalBinaryLengthPrefixed(p) + pb, err := proto.Marshal(&p) require.NoError(t, err) require.NotEqual(t, vb, pb) } @@ -148,25 +119,26 @@ func TestVoteVerifySignature(t *testing.T) { require.NoError(t, err) vote := examplePrecommit() - signBytes := vote.SignBytes("test_chain_id") + v := vote.ToProto() + signBytes := VoteSignBytes("test_chain_id", v) // sign it - err = privVal.SignVote("test_chain_id", vote) + err = privVal.SignVote("test_chain_id", v) require.NoError(t, err) // verify the same vote - valid := pubkey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature) + valid := pubkey.VerifyBytes(VoteSignBytes("test_chain_id", v), v.Signature) require.True(t, valid) // serialize, deserialize and verify again.... - precommit := new(Vote) - bs, err := cdc.MarshalBinaryLengthPrefixed(vote) + precommit := new(tmproto.Vote) + bs, err := proto.Marshal(v) require.NoError(t, err) - err = cdc.UnmarshalBinaryLengthPrefixed(bs, &precommit) + err = proto.Unmarshal(bs, precommit) require.NoError(t, err) // verify the transmitted vote - newSignBytes := precommit.SignBytes("test_chain_id") + newSignBytes := VoteSignBytes("test_chain_id", precommit) require.Equal(t, string(signBytes), string(newSignBytes)) valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature) require.True(t, valid) @@ -233,11 +205,12 @@ func TestMaxVoteBytes(t *testing.T) { }, } + v := vote.ToProto() privVal := NewMockPV() - err := privVal.SignVote("test_chain_id", vote) + err := privVal.SignVote("test_chain_id", v) require.NoError(t, err) - bz, err := cdc.MarshalBinaryLengthPrefixed(vote) + bz, err := proto.Marshal(v) require.NoError(t, err) assert.EqualValues(t, MaxVoteBytes, len(bz)) @@ -245,13 +218,13 @@ func TestMaxVoteBytes(t *testing.T) { func TestVoteString(t *testing.T) { str := examplePrecommit().String() - expected := `Vote{56789:6AF1F4111082 12345/02/2(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` + expected := `Vote{56789:6AF1F4111082 12345/02/PRECOMMIT_TYPE(Precommit) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests if str != expected { t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str) } str2 := examplePrevote().String() - expected = `Vote{56789:6AF1F4111082 12345/02/1(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` + expected = `Vote{56789:6AF1F4111082 12345/02/PREVOTE_TYPE(Prevote) 8B01023386C3 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests if str2 != expected { t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str2) } @@ -280,7 +253,9 @@ func TestVoteValidateBasic(t *testing.T) { tc := tc t.Run(tc.testName, func(t *testing.T) { vote := examplePrecommit() - err := privVal.SignVote("test_chain_id", vote) + v := vote.ToProto() + err := privVal.SignVote("test_chain_id", v) + vote.Signature = v.Signature require.NoError(t, err) tc.malleateVote(vote) assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result") @@ -291,7 +266,9 @@ func TestVoteValidateBasic(t *testing.T) { func TestVoteProtobuf(t *testing.T) { privVal := NewMockPV() vote := examplePrecommit() - err := privVal.SignVote("test_chain_id", vote) + v := vote.ToProto() + err := privVal.SignVote("test_chain_id", v) + vote.Signature = v.Signature require.NoError(t, err) testCases := []struct { From bdac0818ac877de08e9b4aae036d225f02f46e8e Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 11 Jun 2020 16:37:29 +0200 Subject: [PATCH 12/12] p2p: proto leftover (#4995) ## Description removing codec.go from p2p pkg and some leftover amino encoding Closes: #XXX --- p2p/codec.go | 13 ------- p2p/node_info.go | 66 +++++++++++++++++++++----------- p2p/transport.go | 21 +++++++---- p2p/transport_test.go | 21 +++++++---- proto/p2p/types.pb.go | 87 +++++++++++++++++++++---------------------- proto/p2p/types.proto | 2 +- state/codec.go | 13 ------- 7 files changed, 115 insertions(+), 108 deletions(-) delete mode 100644 p2p/codec.go delete mode 100644 state/codec.go diff --git a/p2p/codec.go b/p2p/codec.go deleted file mode 100644 index 463276318..000000000 --- a/p2p/codec.go +++ /dev/null @@ -1,13 +0,0 @@ -package p2p - -import ( - amino "github.com/tendermint/go-amino" - - cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino" -) - -var cdc = amino.NewCodec() - -func init() { - cryptoamino.RegisterAmino(cdc) -} diff --git a/p2p/node_info.go b/p2p/node_info.go index ea7fc961c..5e6e46e06 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -1,11 +1,13 @@ package p2p import ( + "errors" "fmt" "reflect" "github.com/tendermint/tendermint/libs/bytes" tmstrings "github.com/tendermint/tendermint/libs/strings" + tmp2p "github.com/tendermint/tendermint/proto/p2p" "github.com/tendermint/tendermint/version" ) @@ -220,30 +222,50 @@ func (info DefaultNodeInfo) NetAddress() (*NetAddress, error) { return NewNetAddressString(idAddr) } -//----------------------------------------------------------- -// These methods are for Protobuf Compatibility +func (info DefaultNodeInfo) ToProto() *tmp2p.DefaultNodeInfo { -// Size returns the size of the amino encoding, in bytes. -func (info *DefaultNodeInfo) Size() int { - bs, _ := info.Marshal() - return len(bs) -} - -// Marshal returns the amino encoding. -func (info *DefaultNodeInfo) Marshal() ([]byte, error) { - return cdc.MarshalBinaryBare(info) -} - -// MarshalTo calls Marshal and copies to the given buffer. -func (info *DefaultNodeInfo) MarshalTo(data []byte) (int, error) { - bs, err := info.Marshal() - if err != nil { - return -1, err + dni := new(tmp2p.DefaultNodeInfo) + dni.ProtocolVersion = tmp2p.ProtocolVersion{ + P2P: info.ProtocolVersion.P2P, + Block: info.ProtocolVersion.Block, + App: info.ProtocolVersion.App, } - return copy(data, bs), nil + + dni.DefaultNodeID = string(info.DefaultNodeID) + dni.ListenAddr = info.ListenAddr + dni.Network = info.Network + dni.Version = info.Version + dni.Channels = info.Channels + dni.Moniker = info.Moniker + dni.Other = tmp2p.DefaultNodeInfoOther{ + TxIndex: info.Other.TxIndex, + RPCAddress: info.Other.RPCAddress, + } + + return dni } -// Unmarshal deserializes from amino encoded form. -func (info *DefaultNodeInfo) Unmarshal(bs []byte) error { - return cdc.UnmarshalBinaryBare(bs, info) +func DefaultNodeInfoFromToProto(pb *tmp2p.DefaultNodeInfo) (DefaultNodeInfo, error) { + if pb == nil { + return DefaultNodeInfo{}, errors.New("nil node info") + } + dni := DefaultNodeInfo{ + ProtocolVersion: ProtocolVersion{ + P2P: pb.ProtocolVersion.P2P, + Block: pb.ProtocolVersion.Block, + App: pb.ProtocolVersion.App, + }, + DefaultNodeID: ID(pb.DefaultNodeID), + ListenAddr: pb.ListenAddr, + Network: pb.Network, + Version: pb.Version, + Channels: pb.Channels, + Moniker: pb.Moniker, + Other: DefaultNodeInfoOther{ + TxIndex: pb.Other.TxIndex, + RPCAddress: pb.Other.RPCAddress, + }, + } + + return dni, nil } diff --git a/p2p/transport.go b/p2p/transport.go index 7a962bb16..3d1821744 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -9,7 +9,9 @@ import ( "golang.org/x/net/netutil" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/p2p/conn" + tmp2p "github.com/tendermint/tendermint/proto/p2p" ) const ( @@ -524,20 +526,18 @@ func handshake( var ( errc = make(chan error, 2) - peerNodeInfo DefaultNodeInfo - ourNodeInfo = nodeInfo.(DefaultNodeInfo) + pbpeerNodeInfo tmp2p.DefaultNodeInfo + peerNodeInfo DefaultNodeInfo + ourNodeInfo = nodeInfo.(DefaultNodeInfo) ) go func(errc chan<- error, c net.Conn) { - _, err := cdc.MarshalBinaryLengthPrefixedWriter(c, ourNodeInfo) + _, err := protoio.NewDelimitedWriter(c).WriteMsg(ourNodeInfo.ToProto()) errc <- err }(errc, c) go func(errc chan<- error, c net.Conn) { - _, err := cdc.UnmarshalBinaryLengthPrefixedReader( - c, - &peerNodeInfo, - int64(MaxNodeInfoSize()), - ) + protoReader := protoio.NewDelimitedReader(c, MaxNodeInfoSize()) + err := protoReader.ReadMsg(&pbpeerNodeInfo) errc <- err }(errc, c) @@ -548,6 +548,11 @@ func handshake( } } + peerNodeInfo, err := DefaultNodeInfoFromToProto(&pbpeerNodeInfo) + if err != nil { + return nil, err + } + return peerNodeInfo, c.SetDeadline(time.Time{}) } diff --git a/p2p/transport_test.go b/p2p/transport_test.go index e461c3645..30149b615 100644 --- a/p2p/transport_test.go +++ b/p2p/transport_test.go @@ -11,7 +11,9 @@ import ( "time" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/p2p/conn" + tmp2p "github.com/tendermint/tendermint/proto/p2p" ) var defaultNodeName = "host_peer" @@ -575,19 +577,24 @@ func TestTransportHandshake(t *testing.T) { } go func(c net.Conn) { - _, err := cdc.MarshalBinaryLengthPrefixedWriter(c, peerNodeInfo.(DefaultNodeInfo)) + _, err := protoio.NewDelimitedWriter(c).WriteMsg(peerNodeInfo.(DefaultNodeInfo).ToProto()) if err != nil { t.Error(err) } }(c) go func(c net.Conn) { - var ni DefaultNodeInfo - - _, err := cdc.UnmarshalBinaryLengthPrefixedReader( - c, - &ni, - int64(MaxNodeInfoSize()), + var ( + // ni DefaultNodeInfo + pbni tmp2p.DefaultNodeInfo ) + + protoReader := protoio.NewDelimitedReader(c, MaxNodeInfoSize()) + err := protoReader.ReadMsg(&pbni) + if err != nil { + t.Error(err) + } + + _, err = DefaultNodeInfoFromToProto(&pbni) if err != nil { t.Error(err) } diff --git a/proto/p2p/types.pb.go b/proto/p2p/types.pb.go index 817a81e0b..6533681fa 100644 --- a/proto/p2p/types.pb.go +++ b/proto/p2p/types.pb.go @@ -252,8 +252,8 @@ func (m *DefaultNodeInfo) GetOther() DefaultNodeInfoOther { } type DefaultNodeInfoOther struct { - TxIndex string `protobuf:"bytes,1,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` - RPCAdddress string `protobuf:"bytes,2,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` + TxIndex string `protobuf:"bytes,1,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` + RPCAddress string `protobuf:"bytes,2,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` } func (m *DefaultNodeInfoOther) Reset() { *m = DefaultNodeInfoOther{} } @@ -296,9 +296,9 @@ func (m *DefaultNodeInfoOther) GetTxIndex() string { return "" } -func (m *DefaultNodeInfoOther) GetRPCAdddress() string { +func (m *DefaultNodeInfoOther) GetRPCAddress() string { if m != nil { - return m.RPCAdddress + return m.RPCAddress } return "" } @@ -313,39 +313,38 @@ func init() { func init() { proto.RegisterFile("proto/p2p/types.proto", fileDescriptor_5c4320c1810ca85c) } var fileDescriptor_5c4320c1810ca85c = []byte{ - // 498 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0xcf, 0x6e, 0x1a, 0x3f, - 0x18, 0x64, 0x97, 0xe5, 0x4f, 0x3e, 0x7e, 0x88, 0xfc, 0x2c, 0x5a, 0x6d, 0x72, 0xd8, 0x45, 0x48, - 0xad, 0x50, 0x0e, 0x50, 0xd1, 0x53, 0x8f, 0xa1, 0xa8, 0x12, 0x97, 0x14, 0x59, 0x55, 0x0e, 0xbd, - 0xac, 0x60, 0xed, 0x80, 0x05, 0xd8, 0x96, 0xd7, 0x69, 0xc9, 0x5b, 0xf4, 0xb1, 0x72, 0xcc, 0xb1, - 0x27, 0x54, 0x2d, 0x0f, 0xd1, 0x6b, 0x65, 0x7b, 0x93, 0x20, 0xc4, 0x6d, 0x66, 0xec, 0xd9, 0xf9, - 0xbe, 0x91, 0x17, 0xde, 0x48, 0x25, 0xb4, 0x18, 0xc8, 0xa1, 0x1c, 0xe8, 0x07, 0x49, 0xb3, 0xbe, - 0xe5, 0xa8, 0xad, 0x29, 0x27, 0x54, 0x6d, 0x18, 0xd7, 0x4e, 0xe9, 0xcb, 0xa1, 0xbc, 0x7c, 0xaf, - 0x97, 0x4c, 0x91, 0x44, 0xce, 0x94, 0x7e, 0x18, 0x38, 0xe3, 0x42, 0x2c, 0xc4, 0x2b, 0x72, 0x77, - 0xbb, 0x73, 0x80, 0x1b, 0xaa, 0xaf, 0x09, 0x51, 0x34, 0xcb, 0xd0, 0x5b, 0xf0, 0x19, 0x09, 0xbd, - 0x8e, 0xd7, 0x3b, 0x1b, 0x55, 0xf3, 0x5d, 0xec, 0x4f, 0xc6, 0xd8, 0x67, 0xc4, 0xea, 0x32, 0xf4, - 0x0f, 0xf4, 0x29, 0xf6, 0x99, 0x44, 0x08, 0x02, 0x29, 0x94, 0x0e, 0xcb, 0x1d, 0xaf, 0xd7, 0xc4, - 0x16, 0xa3, 0x73, 0x28, 0x67, 0x5a, 0x85, 0x81, 0xb9, 0x8c, 0x0d, 0xec, 0x7e, 0x83, 0xd6, 0xd4, - 0x84, 0xa5, 0x62, 0x7d, 0x4b, 0x55, 0xc6, 0x04, 0x47, 0x17, 0x50, 0x96, 0x43, 0x69, 0x93, 0x82, - 0x51, 0x2d, 0xdf, 0xc5, 0xe5, 0xe9, 0x70, 0x8a, 0x8d, 0x86, 0xda, 0x50, 0x99, 0xaf, 0x45, 0xba, - 0xb2, 0x71, 0x01, 0x76, 0xc4, 0x7c, 0x75, 0x26, 0xa5, 0x0d, 0x0a, 0xb0, 0x81, 0xdd, 0xbf, 0x3e, - 0xb4, 0xc6, 0xf4, 0x6e, 0x76, 0xbf, 0xd6, 0x37, 0x82, 0xd0, 0x09, 0xbf, 0x13, 0xe8, 0x16, 0xce, - 0x65, 0x91, 0x94, 0xfc, 0x70, 0x51, 0x36, 0xa3, 0x31, 0x7c, 0xd7, 0x3f, 0x55, 0x53, 0xff, 0x68, - 0xae, 0x51, 0xf0, 0xb8, 0x8b, 0x4b, 0xb8, 0x25, 0x8f, 0xc6, 0xfd, 0x04, 0x2d, 0xe2, 0xa2, 0x12, - 0x2e, 0x08, 0x4d, 0x18, 0x29, 0xca, 0xf8, 0x3f, 0xdf, 0xc5, 0xcd, 0xc3, 0x29, 0xc6, 0xb8, 0x49, - 0x0e, 0x28, 0x41, 0x31, 0x34, 0xd6, 0x2c, 0xd3, 0x94, 0x27, 0x33, 0x42, 0x94, 0x5d, 0xe0, 0x0c, - 0x83, 0x93, 0x4c, 0xed, 0x28, 0x84, 0x1a, 0xa7, 0xfa, 0xa7, 0x50, 0xab, 0xa2, 0xb3, 0x67, 0x6a, - 0x4e, 0x9e, 0x97, 0xa8, 0xb8, 0x93, 0x82, 0xa2, 0x4b, 0xa8, 0xa7, 0xcb, 0x19, 0xe7, 0x74, 0x9d, - 0x85, 0xd5, 0x8e, 0xd7, 0xfb, 0x0f, 0xbf, 0x70, 0xe3, 0xda, 0x08, 0xce, 0x56, 0x54, 0x85, 0x35, - 0xe7, 0x2a, 0x28, 0xfa, 0x02, 0x15, 0xa1, 0x97, 0x54, 0x85, 0x75, 0x5b, 0xc9, 0xd5, 0xe9, 0x4a, - 0x8e, 0x3a, 0xfd, 0x6a, 0x1c, 0x45, 0x2f, 0xce, 0xde, 0x4d, 0xa1, 0x7d, 0xea, 0x12, 0xba, 0x80, - 0xba, 0xde, 0x26, 0x8c, 0x13, 0xba, 0x75, 0x6f, 0x08, 0xd7, 0xf4, 0x76, 0x62, 0x28, 0xfa, 0x00, - 0x0d, 0x25, 0x53, 0x5b, 0x01, 0xcd, 0xb2, 0xa2, 0xbc, 0x56, 0xbe, 0x8b, 0x1b, 0x78, 0xfa, 0xf9, - 0x9a, 0x38, 0x19, 0x83, 0x92, 0x69, 0xf1, 0x14, 0x47, 0xe3, 0xc7, 0x3c, 0xf2, 0x9e, 0xf2, 0xc8, - 0xfb, 0x93, 0x47, 0xde, 0xaf, 0x7d, 0x54, 0x7a, 0xda, 0x47, 0xa5, 0xdf, 0xfb, 0xa8, 0xf4, 0xfd, - 0x6a, 0xc1, 0xf4, 0xf2, 0x7e, 0xde, 0x4f, 0xc5, 0x66, 0xf0, 0xba, 0xc1, 0x21, 0x7c, 0xf9, 0x51, - 0xe6, 0x55, 0x0b, 0x3f, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x48, 0x04, 0xbe, 0xde, 0x3c, 0x03, - 0x00, 0x00, + // 496 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x93, 0x4f, 0x6f, 0xda, 0x30, + 0x18, 0xc6, 0x49, 0x08, 0x7f, 0xfa, 0x32, 0x46, 0x67, 0xb1, 0x29, 0xed, 0x21, 0x41, 0x48, 0x9b, + 0x50, 0x0f, 0x20, 0xb1, 0xd3, 0x8e, 0x63, 0x68, 0x12, 0x97, 0x0e, 0x59, 0x53, 0x0f, 0xbb, 0x44, + 0x10, 0xbb, 0x60, 0x01, 0xb6, 0xe5, 0xb8, 0x1b, 0xfd, 0x16, 0xfb, 0x58, 0x3d, 0xf6, 0xb8, 0x13, + 0x9a, 0xc2, 0x87, 0xd8, 0x75, 0xb2, 0x9d, 0xb6, 0x08, 0x71, 0x7b, 0x9e, 0xd7, 0x7e, 0xf3, 0xbc, + 0xef, 0x4f, 0x0e, 0xbc, 0x95, 0x4a, 0x68, 0x31, 0x90, 0x43, 0x39, 0xd0, 0xf7, 0x92, 0x66, 0x7d, + 0xeb, 0x51, 0x5b, 0x53, 0x4e, 0xa8, 0xda, 0x30, 0xae, 0x5d, 0xa5, 0x2f, 0x87, 0xf2, 0xf2, 0x83, + 0x5e, 0x32, 0x45, 0x12, 0x39, 0x53, 0xfa, 0x7e, 0xe0, 0x1a, 0x17, 0x62, 0x21, 0x5e, 0x94, 0xbb, + 0xdb, 0x9d, 0x03, 0x5c, 0x53, 0xfd, 0x99, 0x10, 0x45, 0xb3, 0x0c, 0xbd, 0x03, 0x9f, 0x91, 0xd0, + 0xeb, 0x78, 0xbd, 0xb3, 0x51, 0x35, 0xdf, 0xc5, 0xfe, 0x64, 0x8c, 0x7d, 0x46, 0x6c, 0x5d, 0x86, + 0xfe, 0x41, 0x7d, 0x8a, 0x7d, 0x26, 0x11, 0x82, 0x40, 0x0a, 0xa5, 0xc3, 0x72, 0xc7, 0xeb, 0x35, + 0xb1, 0xd5, 0xe8, 0x1c, 0xca, 0x99, 0x56, 0x61, 0x60, 0x2e, 0x63, 0x23, 0xbb, 0xdf, 0xa1, 0x35, + 0x35, 0x61, 0xa9, 0x58, 0xdf, 0x50, 0x95, 0x31, 0xc1, 0xd1, 0x05, 0x94, 0xe5, 0x50, 0xda, 0xa4, + 0x60, 0x54, 0xcb, 0x77, 0x71, 0x79, 0x3a, 0x9c, 0x62, 0x53, 0x43, 0x6d, 0xa8, 0xcc, 0xd7, 0x22, + 0x5d, 0xd9, 0xb8, 0x00, 0x3b, 0x63, 0xbe, 0x3a, 0x93, 0xd2, 0x06, 0x05, 0xd8, 0xc8, 0xee, 0x3f, + 0x1f, 0x5a, 0x63, 0x7a, 0x3b, 0xbb, 0x5b, 0xeb, 0x6b, 0x41, 0xe8, 0x84, 0xdf, 0x0a, 0x74, 0x03, + 0xe7, 0xb2, 0x48, 0x4a, 0x7e, 0xba, 0x28, 0x9b, 0xd1, 0x18, 0xbe, 0xef, 0x9f, 0xc2, 0xd4, 0x3f, + 0x9a, 0x6b, 0x14, 0x3c, 0xec, 0xe2, 0x12, 0x6e, 0xc9, 0xa3, 0x71, 0x3f, 0x41, 0x8b, 0xb8, 0xa8, + 0x84, 0x0b, 0x42, 0x13, 0x46, 0x0a, 0x18, 0x6f, 0xf2, 0x5d, 0xdc, 0x3c, 0x9c, 0x62, 0x8c, 0x9b, + 0xe4, 0xc0, 0x12, 0x14, 0x43, 0x63, 0xcd, 0x32, 0x4d, 0x79, 0x32, 0x23, 0x44, 0xd9, 0x05, 0xce, + 0x30, 0xb8, 0x92, 0xc1, 0x8e, 0x42, 0xa8, 0x71, 0xaa, 0x7f, 0x09, 0xb5, 0x2a, 0x98, 0x3d, 0x59, + 0x73, 0xf2, 0xb4, 0x44, 0xc5, 0x9d, 0x14, 0x16, 0x5d, 0x42, 0x3d, 0x5d, 0xce, 0x38, 0xa7, 0xeb, + 0x2c, 0xac, 0x76, 0xbc, 0xde, 0x2b, 0xfc, 0xec, 0x4d, 0xd7, 0x46, 0x70, 0xb6, 0xa2, 0x2a, 0xac, + 0xb9, 0xae, 0xc2, 0xa2, 0xaf, 0x50, 0x11, 0x7a, 0x49, 0x55, 0x58, 0xb7, 0x48, 0xae, 0x4e, 0x23, + 0x39, 0x62, 0xfa, 0xcd, 0x74, 0x14, 0x5c, 0x5c, 0x7b, 0x77, 0x0e, 0xed, 0x53, 0x97, 0xd0, 0x05, + 0xd4, 0xf5, 0x36, 0x61, 0x9c, 0xd0, 0xad, 0x7b, 0x43, 0xb8, 0xa6, 0xb7, 0x13, 0x63, 0xd1, 0x00, + 0x1a, 0x4a, 0xa6, 0x16, 0x01, 0xcd, 0xb2, 0x02, 0xde, 0xeb, 0x7c, 0x17, 0x03, 0x9e, 0x7e, 0x29, + 0x5e, 0x1f, 0x06, 0x25, 0xd3, 0x42, 0x8f, 0xc6, 0x0f, 0x79, 0xe4, 0x3d, 0xe6, 0x91, 0xf7, 0x37, + 0x8f, 0xbc, 0xdf, 0xfb, 0xa8, 0xf4, 0xb8, 0x8f, 0x4a, 0x7f, 0xf6, 0x51, 0xe9, 0xc7, 0xd5, 0x82, + 0xe9, 0xe5, 0xdd, 0xbc, 0x9f, 0x8a, 0xcd, 0xe0, 0x65, 0x81, 0x43, 0xf9, 0xfc, 0x9f, 0xcc, 0xab, + 0x56, 0x7e, 0xfc, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x57, 0xdb, 0x7b, 0x33, 0x3b, 0x03, 0x00, 0x00, } func (m *NetAddress) Marshal() (dAtA []byte, err error) { @@ -540,10 +539,10 @@ func (m *DefaultNodeInfoOther) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.RPCAdddress) > 0 { - i -= len(m.RPCAdddress) - copy(dAtA[i:], m.RPCAdddress) - i = encodeVarintTypes(dAtA, i, uint64(len(m.RPCAdddress))) + if len(m.RPCAddress) > 0 { + i -= len(m.RPCAddress) + copy(dAtA[i:], m.RPCAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.RPCAddress))) i-- dAtA[i] = 0x12 } @@ -657,7 +656,7 @@ func (m *DefaultNodeInfoOther) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - l = len(m.RPCAdddress) + l = len(m.RPCAddress) if l > 0 { n += 1 + l + sovTypes(uint64(l)) } @@ -1324,7 +1323,7 @@ func (m *DefaultNodeInfoOther) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RPCAdddress", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RPCAddress", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1352,7 +1351,7 @@ func (m *DefaultNodeInfoOther) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.RPCAdddress = string(dAtA[iNdEx:postIndex]) + m.RPCAddress = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex diff --git a/proto/p2p/types.proto b/proto/p2p/types.proto index 542fc4f19..648686571 100644 --- a/proto/p2p/types.proto +++ b/proto/p2p/types.proto @@ -31,5 +31,5 @@ message DefaultNodeInfo { message DefaultNodeInfoOther { string tx_index = 1; - string rpc_address = 2 [(gogoproto.customname) = "RPCAdddress"]; + string rpc_address = 2 [(gogoproto.customname) = "RPCAddress"]; } diff --git a/state/codec.go b/state/codec.go deleted file mode 100644 index df2c15545..000000000 --- a/state/codec.go +++ /dev/null @@ -1,13 +0,0 @@ -package state - -import ( - amino "github.com/tendermint/go-amino" - - cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino" -) - -var cdc = amino.NewCodec() - -func init() { - cryptoamino.RegisterAmino(cdc) -}