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.
This commit is contained in:
parent
1364770cbe
commit
6d6f061f19
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
if rt.Kind() == reflect.Interface {
|
||||
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 interface
|
||||
if rt.Kind() == reflect.Interface {
|
||||
rv = rv.Elem()
|
||||
rt = rv.Type()
|
||||
// If interface type, get typeInfo of underlying type.
|
||||
typeInfo = GetTypeInfo(rt)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue