From e5d34befdec2733b9ed9817edacbe0d2c0c2f980 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 14 Apr 2015 15:57:16 -0700 Subject: [PATCH] Remote TypeByte() --- account/privkey.go | 5 +- account/pubkey.go | 5 +- account/signature.go | 5 +- binary/README.md | 8 +- binary/reflect.go | 172 ++++++++++++++----------------------- binary/reflect_test.go | 16 +--- blockchain/reactor.go | 39 ++++----- cmd/barak/types/command.go | 29 +++---- consensus/reactor.go | 49 ++++------- mempool/reactor.go | 26 +++--- p2p/pex_reactor.go | 36 +++----- types/tx.go | 24 ++---- 12 files changed, 148 insertions(+), 266 deletions(-) diff --git a/account/privkey.go b/account/privkey.go index bf088b5ea..32743604e 100644 --- a/account/privkey.go +++ b/account/privkey.go @@ -8,7 +8,6 @@ import ( // PrivKey is part of PrivAccount and state.PrivValidator. type PrivKey interface { - TypeByte() byte Sign(msg []byte) Signature PubKey() PubKey } @@ -21,7 +20,7 @@ const ( // for binary.readReflect var _ = binary.RegisterInterface( struct{ PrivKey }{}, - binary.ConcreteType{PrivKeyEd25519{}}, + binary.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, ) //------------------------------------- @@ -29,8 +28,6 @@ var _ = binary.RegisterInterface( // Implements PrivKey type PrivKeyEd25519 []byte -func (privKey PrivKeyEd25519) TypeByte() byte { return PrivKeyTypeEd25519 } - func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { pubKey := privKey.PubKey().(PubKeyEd25519) privKeyBytes := new([64]byte) diff --git a/account/pubkey.go b/account/pubkey.go index d416374ab..1800ec914 100644 --- a/account/pubkey.go +++ b/account/pubkey.go @@ -9,7 +9,6 @@ import ( // PubKey is part of Account and Validator. type PubKey interface { - TypeByte() byte IsNil() bool Address() []byte VerifyBytes(msg []byte, sig Signature) bool @@ -23,7 +22,7 @@ const ( // for binary.readReflect var _ = binary.RegisterInterface( struct{ PubKey }{}, - binary.ConcreteType{PubKeyEd25519{}}, + binary.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, ) //------------------------------------- @@ -31,8 +30,6 @@ var _ = binary.RegisterInterface( // Implements PubKey type PubKeyEd25519 []byte -func (pubKey PubKeyEd25519) TypeByte() byte { return PubKeyTypeEd25519 } - func (pubKey PubKeyEd25519) IsNil() bool { return false } // TODO: Or should this just be BinaryRipemd160(key)? (The difference is the TypeByte.) diff --git a/account/signature.go b/account/signature.go index c085225d0..d51535e7c 100644 --- a/account/signature.go +++ b/account/signature.go @@ -9,7 +9,6 @@ import ( // Signature is a part of Txs and consensus Votes. type Signature interface { - TypeByte() byte } // Types of Signature implementations @@ -20,7 +19,7 @@ const ( // for binary.readReflect var _ = binary.RegisterInterface( struct{ Signature }{}, - binary.ConcreteType{SignatureEd25519{}}, + binary.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519}, ) //------------------------------------- @@ -28,8 +27,6 @@ var _ = binary.RegisterInterface( // Implements Signature type SignatureEd25519 []byte -func (sig SignatureEd25519) TypeByte() byte { return SignatureTypeEd25519 } - func (sig SignatureEd25519) IsNil() bool { return false } func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } diff --git a/binary/README.md b/binary/README.md index 118314bd4..2dfa79192 100644 --- a/binary/README.md +++ b/binary/README.md @@ -1,3 +1,9 @@ +### NOTICE + +This documentation is out of date. +* 0x00 is reserved as a nil byte for RegisterInterface +* moved TypeByte() into RegisterInterface/ConcreteType + # `tendermint/binary` The `binary` submodule encodes primary types and structs into bytes. @@ -127,4 +133,4 @@ is encoded or decoded directly: WriteBinary(Dog{}, buf, n, err) // Writes GreeterTypeDog byte dog_ := ReadBinary(Dog{}, buf, n, err) // Expects to read GreeterTypeDog byte dog := dog_.(Dog) // ok if *err != nil, otherwise dog_ == nil. -``` \ No newline at end of file +``` diff --git a/binary/reflect.go b/binary/reflect.go index e1fd3c24e..a05539d84 100644 --- a/binary/reflect.go +++ b/binary/reflect.go @@ -17,12 +17,11 @@ type TypeInfo struct { // If Type is kind reflect.Interface, is registered IsRegisteredInterface bool - ConcreteTypes map[byte]reflect.Type - ConcreteTypeBytes map[reflect.Type]byte + ByteToType map[byte]reflect.Type + TypeToByte map[reflect.Type]byte // If Type is concrete - HasTypeByte bool - TypeByte byte + Byte byte // If Type is kind reflect.Struct Fields []StructFieldInfo @@ -47,12 +46,15 @@ func GetTypeFromStructDeclaration(o interface{}) reflect.Type { return rt.Field(0).Type } -// If o implements HasTypeByte, returns (true, typeByte) -func GetTypeByteFromStruct(o interface{}) (hasTypeByte bool, typeByte byte) { - if _, ok := o.(HasTypeByte); ok { - return true, o.(HasTypeByte).TypeByte() - } else { - return false, byte(0x00) +func SetByteForType(typeByte byte, rt reflect.Type) { + typeInfo := GetTypeInfo(rt) + if typeInfo.Byte != 0x00 && typeInfo.Byte != typeByte { + panic(Fmt("Type %v already registered with type byte %X", rt, typeByte)) + } + typeInfo.Byte = typeByte + // If pointer, we need to set it for the concrete type as well. + if rt.Kind() == reflect.Ptr { + SetByteForType(typeByte, rt.Elem()) } } @@ -65,14 +67,6 @@ const ( rfc2822 = "Mon Jan 02 15:04:05 -0700 2006" ) -// If a type implements TypeByte, the byte is included -// as the first byte for encoding and decoding. -// This is primarily used to encode interfaces types. -// The interface should be declared with RegisterInterface() -type HasTypeByte interface { - TypeByte() byte -} - // NOTE: do not access typeInfos directly, but call GetTypeInfo() var typeInfosMtx sync.Mutex var typeInfos = map[reflect.Type]*TypeInfo{} @@ -82,96 +76,52 @@ func GetTypeInfo(rt reflect.Type) *TypeInfo { defer typeInfosMtx.Unlock() info := typeInfos[rt] if info == nil { - info = &TypeInfo{Type: rt} - RegisterType(info) + info = MakeTypeInfo(rt) + typeInfos[rt] = info } return info } // For use with the RegisterInterface declaration type ConcreteType struct { - O interface{} + O interface{} + Byte byte } // Must use this to register an interface to properly decode the // underlying concrete type. -func RegisterInterface(o interface{}, args ...interface{}) *TypeInfo { +func RegisterInterface(o interface{}, ctypes ...ConcreteType) *TypeInfo { it := GetTypeFromStructDeclaration(o) if it.Kind() != reflect.Interface { panic("RegisterInterface expects an interface") } - concreteTypes := make(map[byte]reflect.Type, 0) - concreteTypesReversed := make(map[reflect.Type]byte, 0) - for _, arg := range args { - switch arg.(type) { - case ConcreteType: - concreteTypeInfo := arg.(ConcreteType) - concreteType := reflect.TypeOf(concreteTypeInfo.O) - hasTypeByte, typeByte := GetTypeByteFromStruct(concreteTypeInfo.O) - //fmt.Println(Fmt("HasTypeByte: %v typeByte: %X type: %X", hasTypeByte, typeByte, concreteType)) - if !hasTypeByte { - panic(Fmt("Expected concrete type %v to implement HasTypeByte", concreteType)) - } - if typeByte == 0x00 { - panic(Fmt("TypeByte of 0x00 is reserved for nil (%v)", concreteType)) - } - if concreteTypes[typeByte] != nil { - panic(Fmt("Duplicate TypeByte for type %v and %v", concreteType, concreteTypes[typeByte])) - } - concreteTypes[typeByte] = concreteType - concreteTypesReversed[concreteType] = typeByte - default: - panic(Fmt("Unexpected argument type %v", reflect.TypeOf(arg))) + toType := make(map[byte]reflect.Type, 0) + toByte := make(map[reflect.Type]byte, 0) + for _, ctype := range ctypes { + crt := reflect.TypeOf(ctype.O) + typeByte := ctype.Byte + SetByteForType(typeByte, crt) + if typeByte == 0x00 { + panic(Fmt("Byte of 0x00 is reserved for nil (%v)", ctype)) + } + if toType[typeByte] != nil { + panic(Fmt("Duplicate Byte for type %v and %v", ctype, toType[typeByte])) } + toType[typeByte] = crt + toByte[crt] = typeByte } typeInfo := &TypeInfo{ Type: it, IsRegisteredInterface: true, - ConcreteTypes: concreteTypes, - ConcreteTypeBytes: concreteTypesReversed, + ByteToType: toType, + TypeToByte: toByte, } typeInfos[it] = typeInfo return typeInfo } -// Registers and possibly modifies the TypeInfo. -// NOTE: not goroutine safe, so only call upon program init. -func RegisterType(info *TypeInfo) *TypeInfo { - - // Also register the dereferenced struct if info.Type is a pointer. - // Or, if info.Type is not a pointer, register the pointer. - var rt, ptrRt reflect.Type - if info.Type.Kind() == reflect.Ptr { - rt, ptrRt = info.Type.Elem(), info.Type - } else { - rt, ptrRt = info.Type, reflect.PtrTo(info.Type) - } - - // Register the type info - typeInfos[rt] = info - typeInfos[ptrRt] = info - - // See if the type implements HasTypeByte - if rt.Kind() != reflect.Interface && - rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) { - zero := reflect.Zero(rt) - typeByte := zero.Interface().(HasTypeByte).TypeByte() - if info.HasTypeByte && info.TypeByte != typeByte { - panic(Fmt("Type %v expected TypeByte of %X", rt, typeByte)) - } else { - info.HasTypeByte = true - info.TypeByte = typeByte - } - } else if ptrRt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) { - zero := reflect.Zero(ptrRt) - typeByte := zero.Interface().(HasTypeByte).TypeByte() - if info.HasTypeByte && info.TypeByte != typeByte { - panic(Fmt("Type %v expected TypeByte of %X", ptrRt, typeByte)) - } else { - info.HasTypeByte = true - info.TypeByte = typeByte - } - } +func MakeTypeInfo(rt reflect.Type) *TypeInfo { + info := &TypeInfo{Type: rt} // If struct, register field name options if rt.Kind() == reflect.Struct { @@ -218,7 +168,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err * if typeByte == 0x00 { return // nil } - crt, ok := typeInfo.ConcreteTypes[typeByte] + crt, ok := typeInfo.ByteToType[typeByte] if !ok { *err = errors.New(Fmt("Unexpected type byte %X for type %v", typeByte, crt)) return @@ -247,17 +197,17 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err * // Dereference pointer rv, rt = rv.Elem(), rt.Elem() typeInfo = GetTypeInfo(rt) - if typeInfo.HasTypeByte { + if typeInfo.Byte != 0x00 { r = NewPrefixedReader([]byte{typeByte}, r) } // continue... } - // Read TypeByte prefix - if typeInfo.HasTypeByte { + // Read Byte prefix + if typeInfo.Byte != 0x00 { typeByte := ReadByte(r, n, err) - if typeByte != typeInfo.TypeByte { - *err = errors.New(Fmt("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte)) + if typeByte != typeInfo.Byte { + *err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, typeByte)) return } } @@ -384,7 +334,7 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err if typeInfo.IsRegisteredInterface { // See if the crt is registered. // If so, we're more restrictive. - _, ok := typeInfo.ConcreteTypeBytes[crt] + _, ok := typeInfo.TypeToByte[crt] if !ok { switch crt.Kind() { case reflect.Ptr: @@ -408,11 +358,12 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err if rt.Kind() == reflect.Ptr { // Dereference pointer rv, rt = rv.Elem(), rt.Elem() + typeInfo = GetTypeInfo(rt) if !rv.IsValid() { WriteByte(0x00, w, n, err) return } - if !typeInfo.HasTypeByte { + if typeInfo.Byte == 0x00 { WriteByte(0x01, w, n, err) // continue... } else { @@ -421,8 +372,8 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err } // Write type byte - if typeInfo.HasTypeByte { - WriteByte(typeInfo.TypeByte, w, n, err) + if typeInfo.Byte != 0x00 { + WriteByte(typeInfo.Byte, w, n, err) } // All other types @@ -507,14 +458,14 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err //----------------------------------------------------------------------------- -func readTypeByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) { +func readByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) { oSlice, ok := o.([]interface{}) if !ok { - err = errors.New(Fmt("Expected type [TypeByte,?] but got type %v", reflect.TypeOf(o))) + err = errors.New(Fmt("Expected type [Byte,?] but got type %v", reflect.TypeOf(o))) return } if len(oSlice) != 2 { - err = errors.New(Fmt("Expected [TypeByte,?] len 2 but got len %v", len(oSlice))) + err = errors.New(Fmt("Expected [Byte,?] len 2 but got len %v", len(oSlice))) return } typeByte_, ok := oSlice[0].(float64) @@ -537,14 +488,14 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro if o == nil { return // nil } - typeByte, _, err_ := readTypeByteJSON(o) + typeByte, _, err_ := readByteJSON(o) if err_ != nil { *err = err_ return } - crt, ok := typeInfo.ConcreteTypes[typeByte] + crt, ok := typeInfo.ByteToType[typeByte] if !ok { - *err = errors.New(Fmt("TypeByte %X not registered for interface %v", typeByte, rt)) + *err = errors.New(Fmt("Byte %X not registered for interface %v", typeByte, rt)) return } crv := reflect.New(crt).Elem() @@ -565,18 +516,19 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro } // Dereference pointer rv, rt = rv.Elem(), rt.Elem() + typeInfo = GetTypeInfo(rt) // continue... } - // Read TypeByte prefix - if typeInfo.HasTypeByte { - typeByte, rest, err_ := readTypeByteJSON(o) + // Read Byte prefix + if typeInfo.Byte != 0x00 { + typeByte, rest, err_ := readByteJSON(o) if err_ != nil { *err = err_ return } - if typeByte != typeInfo.TypeByte { - *err = errors.New(Fmt("Expected TypeByte of %X but got %X", typeInfo.TypeByte, byte(typeByte))) + if typeByte != typeInfo.Byte { + *err = errors.New(Fmt("Expected Byte of %X but got %X", typeInfo.Byte, byte(typeByte))) return } o = rest @@ -697,6 +649,7 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro } func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) { + log.Debug(Fmt("writeReflectJSON(%v, %v, %v, %v, %v)", rv, rt, w, n, err)) // Get typeInfo typeInfo := GetTypeInfo(rt) @@ -712,7 +665,7 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, if typeInfo.IsRegisteredInterface { // See if the crt is registered. // If so, we're more restrictive. - _, ok := typeInfo.ConcreteTypeBytes[crt] + _, ok := typeInfo.TypeToByte[crt] if !ok { switch crt.Kind() { case reflect.Ptr: @@ -736,6 +689,7 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, if rt.Kind() == reflect.Ptr { // Dereference pointer rv, rt = rv.Elem(), rt.Elem() + typeInfo = GetTypeInfo(rt) if !rv.IsValid() { WriteTo([]byte("null"), w, n, err) return @@ -743,9 +697,9 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, // continue... } - // Write TypeByte - if typeInfo.HasTypeByte { - WriteTo([]byte(Fmt("[%v,", typeInfo.TypeByte)), w, n, err) + // Write Byte + if typeInfo.Byte != 0x00 { + WriteTo([]byte(Fmt("[%v,", typeInfo.Byte)), w, n, err) defer WriteTo([]byte("]"), w, n, err) } diff --git a/binary/reflect_test.go b/binary/reflect_test.go index 1f78acbf1..9b854f513 100644 --- a/binary/reflect_test.go +++ b/binary/reflect_test.go @@ -30,33 +30,25 @@ type Cat struct { SimpleStruct } -func (cat Cat) TypeByte() byte { return AnimalTypeCat } - // Implements Animal type Dog struct { SimpleStruct } -func (dog Dog) TypeByte() byte { return AnimalTypeDog } - // Implements Animal type Snake []byte -func (snake Snake) TypeByte() byte { return AnimalTypeSnake } - // Implements Animal type Viper struct { Bytes []byte } -func (viper *Viper) TypeByte() byte { return AnimalTypeViper } - var _ = RegisterInterface( struct{ Animal }{}, - ConcreteType{Cat{}}, - ConcreteType{Dog{}}, - ConcreteType{Snake{}}, - ConcreteType{&Viper{}}, + ConcreteType{Cat{}, AnimalTypeCat}, + ConcreteType{Dog{}, AnimalTypeDog}, + ConcreteType{Snake{}, AnimalTypeSnake}, + ConcreteType{&Viper{}, AnimalTypeViper}, ) func TestAnimalInterface(t *testing.T) { diff --git a/blockchain/reactor.go b/blockchain/reactor.go index ef2ff3da2..4c0a03e72 100644 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -116,15 +116,15 @@ func (bcR *BlockchainReactor) RemovePeer(peer *p2p.Peer, reason interface{}) { // Implements Reactor func (bcR *BlockchainReactor) Receive(chId byte, src *p2p.Peer, msgBytes []byte) { - _, msg_, err := DecodeMessage(msgBytes) + _, msg, err := DecodeMessage(msgBytes) if err != nil { log.Warn("Error decoding message", "error", err) return } - log.Info("Received message", "msg", msg_) + log.Info("Received message", "msg", msg) - switch msg := msg_.(type) { + switch msg := msg.(type) { case bcBlockRequestMessage: // Got a request for a block. Respond with block if we have it. block := bcR.store.LoadBlock(msg.Height) @@ -251,28 +251,25 @@ func (bcR *BlockchainReactor) SetEventSwitch(evsw *events.EventSwitch) { // Messages const ( - msgTypeUnknown = byte(0x00) msgTypeBlockRequest = byte(0x10) msgTypeBlockResponse = byte(0x11) msgTypePeerStatus = byte(0x20) ) -// TODO: check for unnecessary extra bytes at the end. -func DecodeMessage(bz []byte) (msgType byte, msg interface{}, err error) { - n := new(int64) +type BlockchainMessage interface{} + +var _ = binary.RegisterInterface( + struct{ BlockchainMessage }{}, + binary.ConcreteType{bcBlockRequestMessage{}, msgTypeBlockRequest}, + binary.ConcreteType{bcBlockResponseMessage{}, msgTypeBlockResponse}, + binary.ConcreteType{bcPeerStatusMessage{}, msgTypePeerStatus}, +) + +func DecodeMessage(bz []byte) (msgType byte, msg BlockchainMessage, err error) { msgType = bz[0] + n := new(int64) r := bytes.NewReader(bz) - switch msgType { - case msgTypeBlockRequest: - msg = binary.ReadBinary(bcBlockRequestMessage{}, r, n, &err) - case msgTypeBlockResponse: - msg = binary.ReadBinary(bcBlockResponseMessage{}, r, n, &err) - case msgTypePeerStatus: - msg = binary.ReadBinary(bcPeerStatusMessage{}, r, n, &err) - default: - log.Warn(Fmt("Ignoring unknown message %X", bz)) - msg = nil - } + msg = binary.ReadBinary(&msg, r, n, &err) return } @@ -282,8 +279,6 @@ type bcBlockRequestMessage struct { Height uint } -func (m bcBlockRequestMessage) TypeByte() byte { return msgTypeBlockRequest } - func (m bcBlockRequestMessage) String() string { return fmt.Sprintf("[bcBlockRequestMessage %v]", m.Height) } @@ -294,8 +289,6 @@ type bcBlockResponseMessage struct { Block *types.Block } -func (m bcBlockResponseMessage) TypeByte() byte { return msgTypeBlockResponse } - func (m bcBlockResponseMessage) String() string { return fmt.Sprintf("[bcBlockResponseMessage %v]", m.Block.Height) } @@ -306,8 +299,6 @@ type bcPeerStatusMessage struct { Height uint } -func (m bcPeerStatusMessage) TypeByte() byte { return msgTypePeerStatus } - func (m bcPeerStatusMessage) String() string { return fmt.Sprintf("[bcPeerStatusMessage %v]", m.Height) } diff --git a/cmd/barak/types/command.go b/cmd/barak/types/command.go index ff32702b5..077ec24eb 100644 --- a/cmd/barak/types/command.go +++ b/cmd/barak/types/command.go @@ -17,29 +17,22 @@ type NoncedCommand struct { type Command interface{} +const ( + commandTypeRunProcess = 0x01 + commandTypeStopProcess = 0x02 + commandTypeListProcesses = 0x03 + commandTypeServeFile = 0x04 +) + // for binary.readReflect var _ = binary.RegisterInterface( struct{ Command }{}, - binary.ConcreteType{CommandRunProcess{}}, - binary.ConcreteType{CommandStopProcess{}}, - binary.ConcreteType{CommandListProcesses{}}, - binary.ConcreteType{CommandServeFile{}}, + binary.ConcreteType{CommandRunProcess{}, commandTypeRunProcess}, + binary.ConcreteType{CommandStopProcess{}, commandTypeStopProcess}, + binary.ConcreteType{CommandListProcesses{}, commandTypeListProcesses}, + binary.ConcreteType{CommandServeFile{}, commandTypeServeFile}, ) -const ( - typeByteRunProcess = 0x01 - typeByteStopProcess = 0x02 - typeByteListProcesses = 0x03 - typeByteServeFile = 0x04 -) - -// TODO: This is actually not cleaner than a method call. -// In fact, this is stupid. -func (_ CommandRunProcess) TypeByte() byte { return typeByteRunProcess } -func (_ CommandStopProcess) TypeByte() byte { return typeByteStopProcess } -func (_ CommandListProcesses) TypeByte() byte { return typeByteListProcesses } -func (_ CommandServeFile) TypeByte() byte { return typeByteServeFile } - type CommandRunProcess struct { Wait bool Label string diff --git a/consensus/reactor.go b/consensus/reactor.go index 3f006b0cd..4ca4a7a18 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -763,31 +763,24 @@ const ( msgTypeHasVote = byte(0x14) ) +type ConsensusMessage interface{} + +var _ = binary.RegisterInterface( + struct{ ConsensusMessage }{}, + binary.ConcreteType{NewRoundStepMessage{}, msgTypeNewRoundStep}, + binary.ConcreteType{CommitStepMessage{}, msgTypeCommitStep}, + binary.ConcreteType{ProposalMessage{}, msgTypeProposal}, + binary.ConcreteType{PartMessage{}, msgTypePart}, + binary.ConcreteType{VoteMessage{}, msgTypeVote}, + binary.ConcreteType{HasVoteMessage{}, msgTypeHasVote}, +) + // TODO: check for unnecessary extra bytes at the end. -func DecodeMessage(bz []byte) (msgType byte, msg interface{}, err error) { - n := new(int64) - // log.Debug(Fmt("decoding msg bytes: %X", bz)) +func DecodeMessage(bz []byte) (msgType byte, msg ConsensusMessage, err error) { msgType = bz[0] + n := new(int64) r := bytes.NewReader(bz) - switch msgType { - // Messages for communicating state changes - case msgTypeNewRoundStep: - msg = binary.ReadBinary(&NewRoundStepMessage{}, r, n, &err) - case msgTypeCommitStep: - msg = binary.ReadBinary(&CommitStepMessage{}, r, n, &err) - // Messages of data - case msgTypeProposal: - msg = binary.ReadBinary(&ProposalMessage{}, r, n, &err) - case msgTypePart: - msg = binary.ReadBinary(&PartMessage{}, r, n, &err) - case msgTypeVote: - msg = binary.ReadBinary(&VoteMessage{}, r, n, &err) - case msgTypeHasVote: - msg = binary.ReadBinary(&HasVoteMessage{}, r, n, &err) - default: - log.Warn(Fmt("Ignoring unknown message %X", bz)) - msg = nil - } + msg = binary.ReadBinary(&msg, r, n, &err) return } @@ -800,8 +793,6 @@ type NewRoundStepMessage struct { SecondsSinceStartTime uint } -func (m *NewRoundStepMessage) TypeByte() byte { return msgTypeNewRoundStep } - func (m *NewRoundStepMessage) String() string { return fmt.Sprintf("[NewRoundStep H:%v R:%v S:%v]", m.Height, m.Round, m.Step) } @@ -814,8 +805,6 @@ type CommitStepMessage struct { BlockBitArray BitArray } -func (m *CommitStepMessage) TypeByte() byte { return msgTypeCommitStep } - func (m *CommitStepMessage) String() string { return fmt.Sprintf("[CommitStep H:%v BP:%v BA:%v]", m.Height, m.BlockParts, m.BlockBitArray) } @@ -826,8 +815,6 @@ type ProposalMessage struct { Proposal *Proposal } -func (m *ProposalMessage) TypeByte() byte { return msgTypeProposal } - func (m *ProposalMessage) String() string { return fmt.Sprintf("[Proposal %v]", m.Proposal) } @@ -846,8 +833,6 @@ type PartMessage struct { Part *types.Part } -func (m *PartMessage) TypeByte() byte { return msgTypePart } - func (m *PartMessage) String() string { return fmt.Sprintf("[Part H:%v R:%v T:%X P:%v]", m.Height, m.Round, m.Type, m.Part) } @@ -859,8 +844,6 @@ type VoteMessage struct { Vote *types.Vote } -func (m *VoteMessage) TypeByte() byte { return msgTypeVote } - func (m *VoteMessage) String() string { return fmt.Sprintf("[Vote VI:%v V:%v]", m.ValidatorIndex, m.Vote) } @@ -874,8 +857,6 @@ type HasVoteMessage struct { Index uint } -func (m *HasVoteMessage) TypeByte() byte { return msgTypeHasVote } - func (m *HasVoteMessage) String() string { return fmt.Sprintf("[HasVote %v/%v T:%X]", m.Height, m.Round, m.Type) } diff --git a/mempool/reactor.go b/mempool/reactor.go index 9d9b1f427..389380627 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -6,7 +6,6 @@ import ( "sync/atomic" "github.com/tendermint/tendermint/binary" - . "github.com/tendermint/tendermint/common" "github.com/tendermint/tendermint/events" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/types" @@ -123,22 +122,21 @@ func (memR *MempoolReactor) SetEventSwitch(evsw *events.EventSwitch) { // Messages const ( - msgTypeUnknown = byte(0x00) - msgTypeTx = byte(0x01) + msgTypeTx = byte(0x01) ) -// TODO: check for unnecessary extra bytes at the end. -func DecodeMessage(bz []byte) (msgType byte, msg interface{}, err error) { - n := new(int64) +type MempoolMessage interface{} + +var _ = binary.RegisterInterface( + struct{ MempoolMessage }{}, + binary.ConcreteType{TxMessage{}, msgTypeTx}, +) + +func DecodeMessage(bz []byte) (msgType byte, msg MempoolMessage, err error) { msgType = bz[0] + n := new(int64) r := bytes.NewReader(bz) - switch msgType { - case msgTypeTx: - msg = binary.ReadBinary(&TxMessage{}, r, n, &err) - default: - log.Warn(Fmt("Ignoring unknown message %X", bz)) - msg = nil - } + msg = binary.ReadBinary(&msg, r, n, &err) return } @@ -148,8 +146,6 @@ type TxMessage struct { Tx types.Tx } -func (m *TxMessage) TypeByte() byte { return msgTypeTx } - func (m *TxMessage) String() string { return fmt.Sprintf("[TxMessage %v]", m.Tx) } diff --git a/p2p/pex_reactor.go b/p2p/pex_reactor.go index c62e12515..a8bb98ba4 100644 --- a/p2p/pex_reactor.go +++ b/p2p/pex_reactor.go @@ -92,7 +92,7 @@ func (pexR *PEXReactor) RemovePeer(peer *Peer, reason interface{}) { func (pexR *PEXReactor) Receive(chId byte, src *Peer, msgBytes []byte) { // decode message - msg, err := DecodeMessage(msgBytes) + _, msg, err := DecodeMessage(msgBytes) if err != nil { log.Warn("Error decoding message", "error", err) return @@ -219,29 +219,25 @@ func (pexR *PEXReactor) SetEventSwitch(evsw *events.EventSwitch) { // Messages const ( - msgTypeUnknown = byte(0x00) msgTypeRequest = byte(0x01) msgTypeAddrs = byte(0x02) msgTypeHandshake = byte(0x03) ) -// TODO: check for unnecessary extra bytes at the end. -func DecodeMessage(bz []byte) (msg interface{}, err error) { +type PexMessage interface{} + +var _ = binary.RegisterInterface( + struct{ PexMessage }{}, + binary.ConcreteType{pexHandshakeMessage{}, msgTypeHandshake}, + binary.ConcreteType{pexRequestMessage{}, msgTypeRequest}, + binary.ConcreteType{pexAddrsMessage{}, msgTypeAddrs}, +) + +func DecodeMessage(bz []byte) (msgType byte, msg PexMessage, err error) { + msgType = bz[0] n := new(int64) - msgType := bz[0] r := bytes.NewReader(bz) - // log.Debug(Fmt("decoding msg bytes: %X", bz)) - switch msgType { - case msgTypeHandshake: - msg = binary.ReadBinary(&pexHandshakeMessage{}, r, n, &err) - case msgTypeRequest: - msg = &pexRequestMessage{} - case msgTypeAddrs: - msg = binary.ReadBinary(&pexAddrsMessage{}, r, n, &err) - default: - log.Warn(Fmt("Ignoring unknown message %X", bz)) - msg = nil - } + msg = binary.ReadBinary(&msg, r, n, &err) return } @@ -252,8 +248,6 @@ type pexHandshakeMessage struct { Network string } -func (m *pexHandshakeMessage) TypeByte() byte { return msgTypeHandshake } - func (m *pexHandshakeMessage) String() string { return "[pexHandshake]" } @@ -264,8 +258,6 @@ A pexRequestMessage requests additional peer addresses. type pexRequestMessage struct { } -func (m *pexRequestMessage) TypeByte() byte { return msgTypeRequest } - func (m *pexRequestMessage) String() string { return "[pexRequest]" } @@ -277,8 +269,6 @@ type pexAddrsMessage struct { Addrs []*NetAddress } -func (m *pexAddrsMessage) TypeByte() byte { return msgTypeAddrs } - func (m *pexAddrsMessage) String() string { return fmt.Sprintf("[pexAddrs %v]", m.Addrs) } diff --git a/types/tx.go b/types/tx.go index 1e62522a2..a924f3822 100644 --- a/types/tx.go +++ b/types/tx.go @@ -61,12 +61,12 @@ const ( // for binary.readReflect var _ = binary.RegisterInterface( struct{ Tx }{}, - binary.ConcreteType{&SendTx{}}, - binary.ConcreteType{&CallTx{}}, - binary.ConcreteType{&BondTx{}}, - binary.ConcreteType{&UnbondTx{}}, - binary.ConcreteType{&RebondTx{}}, - binary.ConcreteType{&DupeoutTx{}}, + binary.ConcreteType{&SendTx{}, TxTypeSend}, + binary.ConcreteType{&CallTx{}, TxTypeCall}, + binary.ConcreteType{&BondTx{}, TxTypeBond}, + binary.ConcreteType{&UnbondTx{}, TxTypeUnbond}, + binary.ConcreteType{&RebondTx{}, TxTypeRebond}, + binary.ConcreteType{&DupeoutTx{}, TxTypeDupeout}, ) //----------------------------------------------------------------------------- @@ -132,8 +132,6 @@ type SendTx struct { Outputs []*TxOutput } -func (tx *SendTx) TypeByte() byte { return TxTypeSend } - func (tx *SendTx) WriteSignBytes(w io.Writer, n *int64, err *error) { binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err) for _, in := range tx.Inputs { @@ -159,8 +157,6 @@ type CallTx struct { Data []byte } -func (tx *CallTx) TypeByte() byte { return TxTypeCall } - func (tx *CallTx) WriteSignBytes(w io.Writer, n *int64, err *error) { tx.Input.WriteSignBytes(w, n, err) binary.WriteByteSlice(tx.Address, w, n, err) @@ -181,8 +177,6 @@ type BondTx struct { UnbondTo []*TxOutput } -func (tx *BondTx) TypeByte() byte { return TxTypeBond } - func (tx *BondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { binary.WriteBinary(tx.PubKey, w, n, err) binary.WriteUvarint(uint(len(tx.Inputs)), w, n, err) @@ -207,8 +201,6 @@ type UnbondTx struct { Signature account.SignatureEd25519 } -func (tx *UnbondTx) TypeByte() byte { return TxTypeUnbond } - func (tx *UnbondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { binary.WriteByteSlice(tx.Address, w, n, err) binary.WriteUvarint(tx.Height, w, n, err) @@ -226,8 +218,6 @@ type RebondTx struct { Signature account.SignatureEd25519 } -func (tx *RebondTx) TypeByte() byte { return TxTypeRebond } - func (tx *RebondTx) WriteSignBytes(w io.Writer, n *int64, err *error) { binary.WriteByteSlice(tx.Address, w, n, err) binary.WriteUvarint(tx.Height, w, n, err) @@ -245,8 +235,6 @@ type DupeoutTx struct { VoteB Vote } -func (tx *DupeoutTx) TypeByte() byte { return TxTypeDupeout } - func (tx *DupeoutTx) WriteSignBytes(w io.Writer, n *int64, err *error) { panic("DupeoutTx has no sign bytes") }