From 6d6f061f193e96c8db3c2b7d3552067b608ea76a Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 12 Apr 2015 17:46:16 -0700 Subject: [PATCH] Support nil pointers for Binary. If the thing does not already have a typebyte declared, a fake one will be given (0x01). A TypeByte of 0x00 is reserved for nil things. No nil-dogs. --- account/pubkey.go | 38 +---- account/signature.go | 13 -- binary/binary.go | 6 + binary/reflect.go | 270 +++++++++++++++++++----------- binary/reflect_test.go | 50 +++++- binary/util.go | 8 +- consensus/pol_test.go | 2 +- mempool/reactor.go | 2 +- node/node.go | 3 +- p2p/connection.go | 6 +- rpc/core/accounts.go | 2 +- rpc/core_client/client_methods.go | 10 +- rpc/handlers.go | 2 + rpc/http_server.go | 39 ++++- rpc/test/helpers.go | 2 +- state/execution.go | 12 +- state/genesis.go | 2 +- state/tx_cache.go | 2 +- types/tx.go | 2 +- types/vote.go | 6 +- 20 files changed, 299 insertions(+), 178 deletions(-) diff --git a/account/pubkey.go b/account/pubkey.go index fa8dce578..d416374ab 100644 --- a/account/pubkey.go +++ b/account/pubkey.go @@ -2,7 +2,6 @@ package account import ( "errors" - "github.com/tendermint/ed25519" "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" @@ -18,47 +17,17 @@ type PubKey interface { // Types of PubKey implementations const ( - PubKeyTypeNil = byte(0x00) PubKeyTypeEd25519 = byte(0x01) ) // for binary.readReflect var _ = binary.RegisterInterface( struct{ PubKey }{}, - binary.ConcreteType{PubKeyNil{}}, binary.ConcreteType{PubKeyEd25519{}}, ) //------------------------------------- -// Implements PubKey -type PubKeyNil struct{} - -func (key PubKeyNil) TypeByte() byte { return PubKeyTypeNil } - -func (key PubKeyNil) IsNil() bool { return true } - -func (key PubKeyNil) Address() []byte { - panic("PubKeyNil has no address") -} - -func (key PubKeyNil) VerifyBytes(msg []byte, sig_ Signature) bool { - panic("PubKeyNil cannot verify messages") -} - -func (key PubKeyEd25519) ValidateBasic() error { - if len(key) != ed25519.PublicKeySize { - return errors.New("Invalid PubKeyEd25519 key size") - } - return nil -} - -func (key PubKeyNil) String() string { - return "PubKeyNil{}" -} - -//------------------------------------- - // Implements PubKey type PubKeyEd25519 []byte @@ -81,6 +50,13 @@ func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { return ed25519.Verify(pubKeyBytes, msg, sigBytes) } +func (pubKey PubKeyEd25519) ValidateBasic() error { + if len(pubKey) != ed25519.PublicKeySize { + return errors.New("Invalid PubKeyEd25519 key size") + } + return nil +} + func (pubKey PubKeyEd25519) String() string { return Fmt("PubKeyEd25519{%X}", []byte(pubKey)) } diff --git a/account/signature.go b/account/signature.go index 53678f723..c085225d0 100644 --- a/account/signature.go +++ b/account/signature.go @@ -14,30 +14,17 @@ type Signature interface { // Types of Signature implementations const ( - SignatureTypeNil = byte(0x00) SignatureTypeEd25519 = byte(0x01) ) // for binary.readReflect var _ = binary.RegisterInterface( struct{ Signature }{}, - binary.ConcreteType{SignatureNil{}}, binary.ConcreteType{SignatureEd25519{}}, ) //------------------------------------- -// Implements Signature -type SignatureNil struct{} - -func (sig SignatureNil) TypeByte() byte { return SignatureTypeNil } - -func (sig SignatureNil) IsNil() bool { return true } - -func (sig SignatureNil) String() string { return "SignatureNil{}" } - -//------------------------------------- - // Implements Signature type SignatureEd25519 []byte diff --git a/binary/binary.go b/binary/binary.go index 5632ac69b..de1b3b260 100644 --- a/binary/binary.go +++ b/binary/binary.go @@ -21,6 +21,9 @@ func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} { func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) { rv := reflect.ValueOf(o) rt := reflect.TypeOf(o) + if rv.Kind() == reflect.Ptr { + rv, rt = rv.Elem(), rt.Elem() + } writeReflect(rv, rt, w, n, err) } @@ -49,6 +52,9 @@ func ReadJSONFromObject(o interface{}, object interface{}, err *error) interface func WriteJSON(o interface{}, w io.Writer, n *int64, err *error) { rv := reflect.ValueOf(o) rt := reflect.TypeOf(o) + if rv.Kind() == reflect.Ptr { + rv, rt = rv.Elem(), rt.Elem() + } writeReflectJSON(rv, rt, w, n, err) } diff --git a/binary/reflect.go b/binary/reflect.go index 345a6f384..b82728423 100644 --- a/binary/reflect.go +++ b/binary/reflect.go @@ -15,13 +15,10 @@ import ( type TypeInfo struct { Type reflect.Type // The type - // Custom encoder/decoder - // NOTE: Not used. - BinaryEncoder Encoder - BinaryDecoder Decoder - - // If Type is kind reflect.Interface - ConcreteTypes map[byte]reflect.Type + // If Type is kind reflect.Interface, is registered + IsRegisteredInterface bool + ConcreteTypes map[byte]reflect.Type + ConcreteTypeBytes map[reflect.Type]byte // If Type is concrete HasTypeByte bool @@ -104,6 +101,7 @@ func RegisterInterface(o interface{}, args ...interface{}) *TypeInfo { 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: @@ -114,17 +112,23 @@ func RegisterInterface(o interface{}, args ...interface{}) *TypeInfo { 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))) } } typeInfo := &TypeInfo{ - Type: it, - ConcreteTypes: concreteTypes, + Type: it, + IsRegisteredInterface: true, + ConcreteTypes: concreteTypes, + ConcreteTypeBytes: concreteTypesReversed, } typeInfos[it] = typeInfo return typeInfo @@ -148,7 +152,8 @@ func RegisterType(info *TypeInfo) *TypeInfo { typeInfos[ptrRt] = info // See if the type implements HasTypeByte - if rt.Kind() != reflect.Interface && rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) { + 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 { @@ -197,35 +202,60 @@ func RegisterType(info *TypeInfo) *TypeInfo { func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) { - log.Debug("Read reflect", "type", rt) - // Get typeInfo typeInfo := GetTypeInfo(rt) - // Custom decoder - if typeInfo.BinaryDecoder != nil { - decoded := typeInfo.BinaryDecoder(r, n, err) - rv.Set(reflect.ValueOf(decoded)) + if rt.Kind() == reflect.Interface { + if !typeInfo.IsRegisteredInterface { + // There's no way we can read such a thing. + *err = errors.New(Fmt("Cannot read unregistered interface type %v", rt)) + return + } + typeByte := ReadByte(r, n, err) + if *err != nil { + return + } + if typeByte == 0x00 { + return // nil + } + crt, ok := typeInfo.ConcreteTypes[typeByte] + if !ok { + *err = errors.New(Fmt("Unexpected type byte %X for type %v", typeByte, crt)) + return + } + crv := reflect.New(crt).Elem() + r = NewPrefixedReader([]byte{typeByte}, r) + readReflect(crv, crt, r, n, err) + rv.Set(crv) // NOTE: orig rv is ignored. return } - // Create a new struct if rv is nil pointer. - if rt.Kind() == reflect.Ptr && rv.IsNil() { - newRv := reflect.New(rt.Elem()) - rv.Set(newRv) - rv = newRv - } - - // Dereference pointer - // Still addressable, thus settable! - if rv.Kind() == reflect.Ptr { + if rt.Kind() == reflect.Ptr { + typeByte := ReadByte(r, n, err) + if *err != nil { + return + } + if typeByte == 0x00 { + return // nil + } + // Create new if rv is nil. + if rv.IsNil() { + newRv := reflect.New(rt.Elem()) + rv.Set(newRv) + rv = newRv + } + // Dereference pointer rv, rt = rv.Elem(), rt.Elem() + typeInfo = GetTypeInfo(rt) + if typeInfo.HasTypeByte { + r = NewPrefixedReader([]byte{typeByte}, r) + } + // continue... } // Read TypeByte prefix if typeInfo.HasTypeByte { typeByte := ReadByte(r, n, err) - log.Debug("Read typebyte", "typeByte", typeByte) if typeByte != typeInfo.TypeByte { *err = errors.New(Fmt("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte)) return @@ -233,19 +263,6 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err * } switch rt.Kind() { - case reflect.Interface: - typeByte := ReadByte(r, n, err) - if *err != nil { - return - } - concreteType, ok := typeInfo.ConcreteTypes[typeByte] - if !ok { - panic(Fmt("TypeByte %X not registered for interface %v", typeByte, rt)) - } - newRv := reflect.New(concreteType) - readReflect(newRv.Elem(), concreteType, NewPrefixedReader([]byte{typeByte}, r), n, err) - rv.Set(newRv.Elem()) - case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { @@ -349,36 +366,66 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err * } } +// rv: the reflection value of the thing to write +// rt: the type of rv as declared in the container, not necessarily rv.Type(). func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) { // Get typeInfo typeInfo := GetTypeInfo(rt) - // Custom encoder, say for an interface type rt. - if typeInfo.BinaryEncoder != nil { - typeInfo.BinaryEncoder(rv.Interface(), w, n, err) - return - } - - // Dereference interface if rt.Kind() == reflect.Interface { - rv = rv.Elem() - rt = rv.Type() - // If interface type, get typeInfo of underlying type. - typeInfo = GetTypeInfo(rt) + if rv.IsNil() { + // XXX ensure that typeByte 0 is reserved. + WriteByte(0x00, w, n, err) + return + } + crv := rv.Elem() // concrete reflection value + crt := crv.Type() // concrete reflection type + if typeInfo.IsRegisteredInterface { + // See if the crt is registered. + // If so, we're more restrictive. + _, ok := typeInfo.ConcreteTypeBytes[crt] + if !ok { + switch crt.Kind() { + case reflect.Ptr: + *err = errors.New(Fmt("Unexpected pointer type %v. Was it registered as a value receiver rather than as a pointer receiver?", crt)) + case reflect.Struct: + *err = errors.New(Fmt("Unexpected struct type %v. Was it registered as a pointer receiver rather than as a value receiver?", crt)) + default: + *err = errors.New(Fmt("Unexpected type %v.", crt)) + } + return + } + } else { + // We support writing unsafely for convenience. + } + // We don't have to write the typeByte here, + // the writeReflect() call below will write it. + writeReflect(crv, crt, w, n, err) + return } - // Dereference pointer if rt.Kind() == reflect.Ptr { - rt = rt.Elem() - rv = rv.Elem() + // Dereference pointer + rv, rt = rv.Elem(), rt.Elem() + if !rv.IsValid() { + WriteByte(0x00, w, n, err) + return + } + if !typeInfo.HasTypeByte { + WriteByte(0x01, w, n, err) + // continue... + } else { + // continue... + } } - // Write TypeByte prefix + // Write type byte if typeInfo.HasTypeByte { WriteByte(typeInfo.TypeByte, w, n, err) } + // All other types switch rt.Kind() { case reflect.Slice: elemRt := rt.Elem() @@ -478,22 +525,47 @@ func readTypeByteJSON(o interface{}) (typeByte byte, rest interface{}, err error func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) { - log.Debug("Read reflect json", "type", rt) - // Get typeInfo typeInfo := GetTypeInfo(rt) - // Create a new struct if rv is nil pointer. - if rt.Kind() == reflect.Ptr && rv.IsNil() { - newRv := reflect.New(rt.Elem()) - rv.Set(newRv) - rv = newRv + if rt.Kind() == reflect.Interface { + if !typeInfo.IsRegisteredInterface { + // There's no way we can read such a thing. + *err = errors.New(Fmt("Cannot read unregistered interface type %v", rt)) + return + } + if o == nil { + return // nil + } + typeByte, _, err_ := readTypeByteJSON(o) + if err_ != nil { + *err = err_ + return + } + crt, ok := typeInfo.ConcreteTypes[typeByte] + if !ok { + *err = errors.New(Fmt("TypeByte %X not registered for interface %v", typeByte, rt)) + return + } + crv := reflect.New(crt).Elem() + readReflectJSON(crv, crt, o, err) + rv.Set(crv) // NOTE: orig rv is ignored. + return } - // Dereference pointer - // Still addressable, thus settable! - if rv.Kind() == reflect.Ptr { + if rt.Kind() == reflect.Ptr { + if o == nil { + return // nil + } + // Create new struct if rv is nil. + if rv.IsNil() { + newRv := reflect.New(rt.Elem()) + rv.Set(newRv) + rv = newRv + } + // Dereference pointer rv, rt = rv.Elem(), rt.Elem() + // continue... } // Read TypeByte prefix @@ -511,20 +583,6 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro } switch rt.Kind() { - case reflect.Interface: - typeByte, _, err_ := readTypeByteJSON(o) - if err_ != nil { - *err = err_ - return - } - concreteType, ok := typeInfo.ConcreteTypes[typeByte] - if !ok { - panic(Fmt("TypeByte %X not registered for interface %v", typeByte, rt)) - } - newRv := reflect.New(concreteType) - readReflectJSON(newRv.Elem(), concreteType, o, err) - rv.Set(newRv.Elem()) - case reflect.Slice: elemRt := rt.Elem() if elemRt.Kind() == reflect.Uint8 { @@ -643,25 +701,55 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, // Get typeInfo typeInfo := GetTypeInfo(rt) - // Dereference interface if rt.Kind() == reflect.Interface { - rv = rv.Elem() - rt = rv.Type() - // If interface type, get typeInfo of underlying type. - typeInfo = GetTypeInfo(rt) + if rv.IsNil() { + // XXX ensure that typeByte 0 is reserved. + WriteTo([]byte("null"), w, n, err) + return + } + crv := rv.Elem() // concrete reflection value + crt := crv.Type() // concrete reflection type + if typeInfo.IsRegisteredInterface { + // See if the crt is registered. + // If so, we're more restrictive. + _, ok := typeInfo.ConcreteTypeBytes[crt] + if !ok { + switch crt.Kind() { + case reflect.Ptr: + *err = errors.New(Fmt("Unexpected pointer type %v. Was it registered as a value receiver rather than as a pointer receiver?", crt)) + case reflect.Struct: + *err = errors.New(Fmt("Unexpected struct type %v. Was it registered as a pointer receiver rather than as a value receiver?", crt)) + default: + *err = errors.New(Fmt("Unexpected type %v.", crt)) + } + return + } + } else { + // We support writing unsafely for convenience. + } + // We don't have to write the typeByte here, + // the writeReflectJSON() call below will write it. + writeReflectJSON(crv, crt, w, n, err) + return } - // Dereference pointer if rt.Kind() == reflect.Ptr { - rt = rt.Elem() - rv = rv.Elem() + // Dereference pointer + rv, rt = rv.Elem(), rt.Elem() + if !rv.IsValid() { + WriteTo([]byte("null"), w, n, err) + return + } + // continue... } - // Write TypeByte prefix + // Write TypeByte if typeInfo.HasTypeByte { WriteTo([]byte(Fmt("[%v,", typeInfo.TypeByte)), w, n, err) + defer WriteTo([]byte("]"), w, n, err) } + // All other types switch rt.Kind() { case reflect.Slice: elemRt := rt.Elem() @@ -730,10 +818,4 @@ func writeReflectJSON(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, panic(Fmt("Unknown field type %v", rt.Kind())) } - // Write TypeByte close bracket - if typeInfo.HasTypeByte { - WriteTo([]byte("]"), w, n, err) - } } - -//----------------------------------------------------------------------------- diff --git a/binary/reflect_test.go b/binary/reflect_test.go index 9220d8fa6..1f78acbf1 100644 --- a/binary/reflect_test.go +++ b/binary/reflect_test.go @@ -120,13 +120,42 @@ func instantiateBasic() (interface{}, interface{}) { func validateBasic(o interface{}, t *testing.T) { cat := o.(Cat) if cat.String != "String" { - t.Errorf("Expected cat2.String == 'String', got %v", cat.String) + t.Errorf("Expected cat.String == 'String', got %v", cat.String) } if string(cat.Bytes) != "Bytes" { - t.Errorf("Expected cat2.Bytes == 'Bytes', got %X", cat.Bytes) + t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes) } if cat.Time.Unix() != 123 { - t.Errorf("Expected cat2.Time == 'Unix(123)', got %v", cat.Time) + t.Errorf("Expected cat.Time == 'Unix(123)', got %v", cat.Time) + } +} + +//------------------------------------- + +type NilTestStruct struct { + IntPtr *int + CatPtr *Cat + Animal Animal +} + +func constructNilTestStruct() interface{} { + return NilTestStruct{} +} + +func instantiateNilTestStruct() (interface{}, interface{}) { + return NilTestStruct{}, &NilTestStruct{} +} + +func validateNilTestStruct(o interface{}, t *testing.T) { + nts := o.(NilTestStruct) + if nts.IntPtr != nil { + t.Errorf("Expected nts.IntPtr to be nil, got %v", nts.IntPtr) + } + if nts.CatPtr != nil { + t.Errorf("Expected nts.CatPtr to be nil, got %v", nts.CatPtr) + } + if nts.Animal != nil { + t.Errorf("Expected nts.Animal to be nil, got %v", nts.Animal) } } @@ -252,7 +281,7 @@ func constructComplexArray() interface{} { Bytes: []byte("Bytes"), }, }, - &Dog{ // Even though it's a *Dog, we'll get a Dog{} back. + Dog{ SimpleStruct{ String: "Woof", Bytes: []byte("Bark"), @@ -321,11 +350,14 @@ func init() { testCases = append(testCases, TestCase{constructComplex, instantiateComplex, validateComplex}) testCases = append(testCases, TestCase{constructComplex2, instantiateComplex2, validateComplex2}) testCases = append(testCases, TestCase{constructComplexArray, instantiateComplexArray, validateComplexArray}) + testCases = append(testCases, TestCase{constructNilTestStruct, instantiateNilTestStruct, validateNilTestStruct}) } func TestBinary(t *testing.T) { - for _, testCase := range testCases { + for i, testCase := range testCases { + + log.Info(fmt.Sprintf("Running test case %v", i)) // Construct an object o := testCase.Constructor() @@ -340,7 +372,7 @@ func TestBinary(t *testing.T) { n, err := new(int64), new(error) res := ReadBinary(instance, bytes.NewReader(data), n, err) if *err != nil { - t.Fatalf("Failed to read cat: %v", *err) + t.Fatalf("Failed to read into instance: %v", *err) } // Validate object @@ -350,7 +382,7 @@ func TestBinary(t *testing.T) { n, err = new(int64), new(error) res = ReadBinary(instancePtr, bytes.NewReader(data), n, err) if *err != nil { - t.Fatalf("Failed to read cat: %v", *err) + t.Fatalf("Failed to read into instance: %v", *err) } if res != instancePtr { @@ -365,7 +397,9 @@ func TestBinary(t *testing.T) { func TestJSON(t *testing.T) { - for _, testCase := range testCases { + for i, testCase := range testCases { + + log.Info(fmt.Sprintf("Running test case %v", i)) // Construct an object o := testCase.Constructor() diff --git a/binary/util.go b/binary/util.go index d27e28bd0..a516a54ca 100644 --- a/binary/util.go +++ b/binary/util.go @@ -10,7 +10,7 @@ func BinaryBytes(o interface{}) []byte { w, n, err := new(bytes.Buffer), new(int64), new(error) WriteBinary(o, w, n, err) if *err != nil { - panic(err) + panic(*err) } return w.Bytes() } @@ -19,7 +19,7 @@ func JSONBytes(o interface{}) []byte { w, n, err := new(bytes.Buffer), new(int64), new(error) WriteJSON(o, w, n, err) if *err != nil { - panic(err) + panic(*err) } return w.Bytes() } @@ -42,7 +42,7 @@ func BinarySha256(o interface{}) []byte { hasher, n, err := sha256.New(), new(int64), new(error) WriteBinary(o, hasher, n, err) if *err != nil { - panic(err) + panic(*err) } return hasher.Sum(nil) } @@ -51,7 +51,7 @@ func BinaryRipemd160(o interface{}) []byte { hasher, n, err := ripemd160.New(), new(int64), new(error) WriteBinary(o, hasher, n, err) if *err != nil { - panic(err) + panic(*err) } return hasher.Sum(nil) } diff --git a/consensus/pol_test.go b/consensus/pol_test.go index e1d67e4dd..ee18ae871 100644 --- a/consensus/pol_test.go +++ b/consensus/pol_test.go @@ -202,7 +202,7 @@ func TestReadWrite(t *testing.T) { // Read from buffer. pol2 := binary.ReadBinary(&POL{}, buf, n, err).(*POL) if *err != nil { - t.Fatalf("Failed to read POL") + t.Fatalf("Failed to read POL: %v", *err) } // Check that validation succeeds. diff --git a/mempool/reactor.go b/mempool/reactor.go index ae469da41..9d662bc90 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -123,7 +123,7 @@ func (memR *MempoolReactor) SetEventSwitch(evsw *events.EventSwitch) { const ( msgTypeUnknown = byte(0x00) - msgTypeTx = byte(0x10) + msgTypeTx = byte(0x01) ) // TODO: check for unnecessary extra bytes at the end. diff --git a/node/node.go b/node/node.go index f7749a800..1d46405f7 100644 --- a/node/node.go +++ b/node/node.go @@ -152,7 +152,8 @@ func (n *Node) StartRPC() { mux := http.NewServeMux() rpc.RegisterEventsHandler(mux, n.evsw) rpc.RegisterRPCFuncs(mux, core.Routes) - rpc.StartHTTPServer(listenAddr, mux) + handler := rpc.AuthenticateHandler(mux) + rpc.StartHTTPServer(listenAddr, handler) } func (n *Node) Switch() *p2p.Switch { diff --git a/p2p/connection.go b/p2p/connection.go index 4de0a159f..85d6e88ea 100644 --- a/p2p/connection.go +++ b/p2p/connection.go @@ -588,9 +588,9 @@ func (ch *Channel) updateStats() { const ( maxMsgPacketSize = 1024 - packetTypePing = byte(0x00) - packetTypePong = byte(0x01) - packetTypeMsg = byte(0x10) + packetTypePing = byte(0x01) + packetTypePong = byte(0x02) + packetTypeMsg = byte(0x03) ) // Messages in channels are chopped into smaller msgPackets for multiplexing. diff --git a/rpc/core/accounts.go b/rpc/core/accounts.go index 4edd17631..b6206fd9e 100644 --- a/rpc/core/accounts.go +++ b/rpc/core/accounts.go @@ -17,7 +17,7 @@ func GetAccount(address []byte) (*ctypes.ResponseGetAccount, error) { if account == nil { account = &acm.Account{ Address: address, - PubKey: acm.PubKeyNil{}, + PubKey: nil, Sequence: 0, Balance: 0, Code: nil, diff --git a/rpc/core_client/client_methods.go b/rpc/core_client/client_methods.go index c62d7b388..391358615 100644 --- a/rpc/core_client/client_methods.go +++ b/rpc/core_client/client_methods.go @@ -18,7 +18,7 @@ type Client interface { BroadcastTx(tx types.Tx) (*ctypes.ResponseBroadcastTx, error) Call(address []byte, data []byte) (*ctypes.ResponseCall, error) CallCode(code []byte, data []byte) (*ctypes.ResponseCall, error) - DumpStorage(addr []byte) (*ctypes.ResponseDumpStorage, error) + DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) GenPrivAccount() (*ctypes.ResponseGenPrivAccount, error) GetAccount(address []byte) (*ctypes.ResponseGetAccount, error) GetBlock(height uint) (*ctypes.ResponseGetBlock, error) @@ -150,8 +150,8 @@ func (c *ClientHTTP) CallCode(code []byte, data []byte) (*ctypes.ResponseCall, e return response.Result, nil } -func (c *ClientHTTP) DumpStorage(addr []byte) (*ctypes.ResponseDumpStorage, error) { - values, err := argsToURLValues([]string{"addr"}, addr) +func (c *ClientHTTP) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) { + values, err := argsToURLValues([]string{"address"}, address) if err != nil { return nil, err } @@ -558,11 +558,11 @@ func (c *ClientJSON) CallCode(code []byte, data []byte) (*ctypes.ResponseCall, e return response.Result, nil } -func (c *ClientJSON) DumpStorage(addr []byte) (*ctypes.ResponseDumpStorage, error) { +func (c *ClientJSON) DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) { request := rpc.RPCRequest{ JSONRPC: "2.0", Method: reverseFuncMap["DumpStorage"], - Params: []interface{}{addr}, + Params: []interface{}{address}, Id: 0, } body, err := c.RequestResponse(request) diff --git a/rpc/handlers.go b/rpc/handlers.go index 933329162..fc60cb4a1 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -101,6 +101,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc) http.HandlerFunc { return } returns := rpcFunc.f.Call(args) + log.Debug("HTTPJSONRPC", "method", request.Method, "args", args, "returns", returns) response, err := unreflectResponse(returns) if err != nil { WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) @@ -148,6 +149,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc) func(http.ResponseWriter, *http.Request) return } returns := rpcFunc.f.Call(args) + log.Debug("HTTPRestRPC", "method", r.URL.Path, "args", args, "returns", returns) response, err := unreflectResponse(returns) if err != nil { WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) diff --git a/rpc/http_server.go b/rpc/http_server.go index 03f805440..c86e0087b 100644 --- a/rpc/http_server.go +++ b/rpc/http_server.go @@ -4,6 +4,7 @@ package rpc import ( "bytes" "fmt" + "io/ioutil" "net/http" "runtime/debug" "time" @@ -12,12 +13,12 @@ import ( . "github.com/tendermint/tendermint/common" ) -func StartHTTPServer(listenAddr string, mux *http.ServeMux) { +func StartHTTPServer(listenAddr string, handler http.Handler) { log.Info(Fmt("Starting RPC HTTP server on %s", listenAddr)) go func() { res := http.ListenAndServe( listenAddr, - RecoverAndLogHandler(mux), + RecoverAndLogHandler(handler), ) log.Crit("RPC HTTPServer stopped", "result", res) }() @@ -37,8 +38,40 @@ func WriteRPCResponse(w http.ResponseWriter, res RPCResponse) { //----------------------------------------------------------------------------- +func AuthenticateHandler(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // from https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361 + // Read the content + var bodyBytes []byte + if r.Body != nil { + bodyBytes, _ = ioutil.ReadAll(r.Body) + } + // Restore the io.ReadCloser to its original state + r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + // Get body string + bodyString := string(bodyBytes) + // Also read the path+"?"+query + pathQuery := Fmt("%v?%v", r.URL.Path, r.URL.RawQuery) + // Concatenate into tuple + tuple := struct { + Body string + Path string + }{bodyString, pathQuery} + // Get sign bytes + signBytes := binary.BinaryBytes(tuple) + // Validate the sign bytes. + // XXX + log.Debug("Should sign", "bytes", signBytes) + // If validation fails + // XXX + // If validation passes + handler.ServeHTTP(w, r) + }) +} + +//----------------------------------------------------------------------------- + // Wraps an HTTP handler, adding error logging. -// // If the inner function panics, the outer function recovers, logs, sends an // HTTP 500 error response. func RecoverAndLogHandler(handler http.Handler) http.Handler { diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index 8fb594da4..2921303d9 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -258,7 +258,7 @@ func checkTx(t *testing.T, fromAddr []byte, priv *account.PrivAccount, tx *types } // Check signatures // acc := getAccount(t, byteAddr) - // NOTE: using the acc here instead of the in fails; its PubKeyNil ... ? + // NOTE: using the acc here instead of the in fails; it is nil. if !in.PubKey.VerifyBytes(signBytes, in.Signature) { t.Fatal(types.ErrTxInvalidSignature) } diff --git a/state/execution.go b/state/execution.go index d7b3b78f7..3c771f8bd 100644 --- a/state/execution.go +++ b/state/execution.go @@ -159,9 +159,9 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade } // The accounts from the TxInputs must either already have -// account.PubKey.(type) != PubKeyNil, (it must be known), +// account.PubKey.(type) != nil, (it must be known), // or it must be specified in the TxInput. If redeclared, -// the TxInput is modified and input.PubKey set to PubKeyNil. +// the TxInput is modified and input.PubKey set to nil. func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types.TxOutput) (map[string]*account.Account, error) { accounts := map[string]*account.Account{} for _, in := range ins { @@ -189,7 +189,7 @@ func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types. if acc == nil { acc = &account.Account{ Address: out.Address, - PubKey: account.PubKeyNil{}, + PubKey: nil, Sequence: 0, Balance: 0, } @@ -200,8 +200,8 @@ func getOrMakeAccounts(state AccountGetter, ins []*types.TxInput, outs []*types. } func checkInputPubKey(acc *account.Account, in *types.TxInput) error { - if _, isNil := acc.PubKey.(account.PubKeyNil); isNil { - if _, isNil := in.PubKey.(account.PubKeyNil); isNil { + if acc.PubKey == nil { + if in.PubKey == nil { return types.ErrTxUnknownPubKey } if !bytes.Equal(in.PubKey.Address(), acc.Address) { @@ -209,7 +209,7 @@ func checkInputPubKey(acc *account.Account, in *types.TxInput) error { } acc.PubKey = in.PubKey } else { - in.PubKey = account.PubKeyNil{} + in.PubKey = nil } return nil } diff --git a/state/genesis.go b/state/genesis.go index 9b75db976..30825536e 100644 --- a/state/genesis.go +++ b/state/genesis.go @@ -61,7 +61,7 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State { for _, genAcc := range genDoc.Accounts { acc := &account.Account{ Address: genAcc.Address, - PubKey: account.PubKeyNil{}, + PubKey: nil, Sequence: 0, Balance: genAcc.Amount, } diff --git a/state/tx_cache.go b/state/tx_cache.go index d4188db3c..fa6065cb4 100644 --- a/state/tx_cache.go +++ b/state/tx_cache.go @@ -163,7 +163,7 @@ func toVMAccount(acc *ac.Account) *vm.Account { func toStateAccount(acc *vm.Account) *ac.Account { pubKey, ok := acc.Other.(ac.PubKey) if !ok { - pubKey = ac.PubKeyNil{} + pubKey = nil } var storageRoot []byte if acc.StorageRoot.IsZero() { diff --git a/types/tx.go b/types/tx.go index 31af05b7a..1e62522a2 100644 --- a/types/tx.go +++ b/types/tx.go @@ -76,7 +76,7 @@ type TxInput struct { Amount uint64 // Must not exceed account balance Sequence uint // Must be 1 greater than the last committed TxInput Signature account.Signature // Depends on the PubKey type and the whole Tx - PubKey account.PubKey // Must not be nil, may be PubKeyNil. + PubKey account.PubKey // Must not be nil, may be nil } func (txIn *TxInput) ValidateBasic() error { diff --git a/types/vote.go b/types/vote.go index 3e3a30e08..4bbe3fb73 100644 --- a/types/vote.go +++ b/types/vote.go @@ -40,9 +40,9 @@ type Vote struct { // Types of votes const ( - VoteTypePrevote = byte(0x00) - VoteTypePrecommit = byte(0x01) - VoteTypeCommit = byte(0x02) + VoteTypePrevote = byte(0x01) + VoteTypePrecommit = byte(0x02) + VoteTypeCommit = byte(0x03) ) func (vote *Vote) WriteSignBytes(w io.Writer, n *int64, err *error) {