Refactor Tx, Validator, and Account structure

This commit is contained in:
Jae Kwon
2014-12-09 18:49:04 -08:00
parent 4424a85fbd
commit 83d313cbe5
56 changed files with 1922 additions and 2027 deletions

View File

@@ -1,23 +1,31 @@
package binary
import "io"
import (
"io"
"reflect"
)
type Binary interface {
WriteTo(w io.Writer) (int64, error)
func ReadBinary(o interface{}, r io.Reader, n *int64, err *error) interface{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {
readReflect(rv.Elem(), rt.Elem(), r, n, err)
return o
} else {
ptrRv := reflect.New(rt)
readReflect(ptrRv.Elem(), rt, r, n, err)
return ptrRv.Elem()
}
}
func WriteBinary(w io.Writer, b Binary, n *int64, err *error) {
if *err != nil {
return
}
n_, err_ := b.WriteTo(w)
*n += int64(n_)
*err = err_
func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) {
rv := reflect.ValueOf(o)
rt := reflect.TypeOf(o)
writeReflect(rv, rt, w, n, err)
}
// Write all of bz to w
// Increment n and set err accordingly.
func WriteTo(w io.Writer, bz []byte, n *int64, err *error) {
func WriteTo(bz []byte, w io.Writer, n *int64, err *error) {
if *err != nil {
return
}
@@ -28,7 +36,7 @@ func WriteTo(w io.Writer, bz []byte, n *int64, err *error) {
// Read len(buf) from r
// Increment n and set err accordingly.
func ReadFull(r io.Reader, buf []byte, n *int64, err *error) {
func ReadFull(buf []byte, r io.Reader, n *int64, err *error) {
if *err != nil {
return
}

View File

@@ -4,27 +4,27 @@ import (
"io"
)
func WriteByteSlice(w io.Writer, bz []byte, n *int64, err *error) {
WriteUInt32(w, uint32(len(bz)), n, err)
WriteTo(w, bz, n, err)
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
WriteUVarInt(uint(len(bz)), w, n, err)
WriteTo(bz, w, n, err)
}
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
length := ReadUInt32(r, n, err)
length := ReadUVarInt(r, n, err)
if *err != nil {
return nil
}
buf := make([]byte, int(length))
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return buf
}
//-----------------------------------------------------------------------------
func WriteByteSlices(w io.Writer, bzz [][]byte, n *int64, err *error) {
WriteUInt32(w, uint32(len(bzz)), n, err)
func WriteByteSlices(bzz [][]byte, w io.Writer, n *int64, err *error) {
WriteUVarInt(uint(len(bzz)), w, n, err)
for _, bz := range bzz {
WriteByteSlice(w, bz, n, err)
WriteByteSlice(bz, w, n, err)
if *err != nil {
return
}
@@ -32,12 +32,12 @@ func WriteByteSlices(w io.Writer, bzz [][]byte, n *int64, err *error) {
}
func ReadByteSlices(r io.Reader, n *int64, err *error) [][]byte {
length := ReadUInt32(r, n, err)
length := ReadUVarInt(r, n, err)
if *err != nil {
return nil
}
bzz := make([][]byte, length)
for i := uint32(0); i < length; i++ {
for i := uint(0); i < length; i++ {
bz := ReadByteSlice(r, n, err)
if *err != nil {
return nil

View File

@@ -6,10 +6,14 @@ import (
"time"
)
type Codec interface {
Encode(o interface{}, w io.Writer, n *int64, err *error)
Decode(r io.Reader, n *int64, err *error) interface{}
Compare(o1 interface{}, o2 interface{}) int
type Encoder func(o interface{}, w io.Writer, n *int64, err *error)
type Decoder func(r io.Reader, n *int64, err *error) interface{}
type Comparator func(o1 interface{}, o2 interface{}) int
type Codec struct {
Encode Encoder
Decode Decoder
Compare Comparator
}
const (
@@ -29,62 +33,58 @@ const (
typeTime = byte(0x20)
)
var BasicCodec = basicCodec{}
type basicCodec struct{}
func (bc basicCodec) Encode(o interface{}, w io.Writer, n *int64, err *error) {
func BasicCodecEncoder(o interface{}, w io.Writer, n *int64, err *error) {
switch o.(type) {
case nil:
panic("nil type unsupported")
case byte:
WriteByte(w, typeByte, n, err)
WriteByte(w, o.(byte), n, err)
WriteByte(typeByte, w, n, err)
WriteByte(o.(byte), w, n, err)
case int8:
WriteByte(w, typeInt8, n, err)
WriteInt8(w, o.(int8), n, err)
WriteByte(typeInt8, w, n, err)
WriteInt8(o.(int8), w, n, err)
//case uint8:
// WriteByte(w, typeUInt8, n, err)
// WriteUInt8(w, o.(uint8), n, err)
// WriteByte( typeUInt8, w, n, err)
// WriteUInt8( o.(uint8), w, n, err)
case int16:
WriteByte(w, typeInt16, n, err)
WriteInt16(w, o.(int16), n, err)
WriteByte(typeInt16, w, n, err)
WriteInt16(o.(int16), w, n, err)
case uint16:
WriteByte(w, typeUInt16, n, err)
WriteUInt16(w, o.(uint16), n, err)
WriteByte(typeUInt16, w, n, err)
WriteUInt16(o.(uint16), w, n, err)
case int32:
WriteByte(w, typeInt32, n, err)
WriteInt32(w, o.(int32), n, err)
WriteByte(typeInt32, w, n, err)
WriteInt32(o.(int32), w, n, err)
case uint32:
WriteByte(w, typeUInt32, n, err)
WriteUInt32(w, o.(uint32), n, err)
WriteByte(typeUInt32, w, n, err)
WriteUInt32(o.(uint32), w, n, err)
case int64:
WriteByte(w, typeInt64, n, err)
WriteInt64(w, o.(int64), n, err)
WriteByte(typeInt64, w, n, err)
WriteInt64(o.(int64), w, n, err)
case uint64:
WriteByte(w, typeUInt64, n, err)
WriteUInt64(w, o.(uint64), n, err)
WriteByte(typeUInt64, w, n, err)
WriteUInt64(o.(uint64), w, n, err)
case int:
WriteByte(w, typeVarInt, n, err)
WriteVarInt(w, o.(int), n, err)
WriteByte(typeVarInt, w, n, err)
WriteVarInt(o.(int), w, n, err)
case uint:
WriteByte(w, typeUVarInt, n, err)
WriteUVarInt(w, o.(uint), n, err)
WriteByte(typeUVarInt, w, n, err)
WriteUVarInt(o.(uint), w, n, err)
case string:
WriteByte(w, typeString, n, err)
WriteString(w, o.(string), n, err)
WriteByte(typeString, w, n, err)
WriteString(o.(string), w, n, err)
case []byte:
WriteByte(w, typeByteSlice, n, err)
WriteByteSlice(w, o.([]byte), n, err)
WriteByte(typeByteSlice, w, n, err)
WriteByteSlice(o.([]byte), w, n, err)
case time.Time:
WriteByte(w, typeTime, n, err)
WriteTime(w, o.(time.Time), n, err)
WriteByte(typeTime, w, n, err)
WriteTime(o.(time.Time), w, n, err)
default:
panic("Unsupported type")
}
}
func (bc basicCodec) Decode(r io.Reader, n *int64, err *error) (o interface{}) {
func BasicCodecDecoder(r io.Reader, n *int64, err *error) (o interface{}) {
type_ := ReadByte(r, n, err)
switch type_ {
case typeByte:
@@ -121,7 +121,7 @@ func (bc basicCodec) Decode(r io.Reader, n *int64, err *error) (o interface{}) {
return o
}
func (bc basicCodec) Compare(o1 interface{}, o2 interface{}) int {
func BasicCodecComparator(o1 interface{}, o2 interface{}) int {
switch o1.(type) {
case byte:
return int(o1.(byte) - o2.(byte))
@@ -154,3 +154,9 @@ func (bc basicCodec) Compare(o1 interface{}, o2 interface{}) int {
panic("Unsupported type")
}
}
var BasicCodec = Codec{
Encode: BasicCodecEncoder,
Decode: BasicCodecDecoder,
Compare: BasicCodecComparator,
}

View File

@@ -8,20 +8,20 @@ import (
// Byte
func WriteByte(w io.Writer, b byte, n *int64, err *error) {
WriteTo(w, []byte{b}, n, err)
func WriteByte(b byte, w io.Writer, n *int64, err *error) {
WriteTo([]byte{b}, w, n, err)
}
func ReadByte(r io.Reader, n *int64, err *error) byte {
buf := make([]byte, 1)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return buf[0]
}
// Int8
func WriteInt8(w io.Writer, i int8, n *int64, err *error) {
WriteByte(w, byte(i), n, err)
func WriteInt8(i int8, w io.Writer, n *int64, err *error) {
WriteByte(byte(i), w, n, err)
}
func ReadInt8(r io.Reader, n *int64, err *error) int8 {
@@ -30,8 +30,8 @@ func ReadInt8(r io.Reader, n *int64, err *error) int8 {
// UInt8
func WriteUInt8(w io.Writer, i uint8, n *int64, err *error) {
WriteByte(w, byte(i), n, err)
func WriteUInt8(i uint8, w io.Writer, n *int64, err *error) {
WriteByte(byte(i), w, n, err)
}
func ReadUInt8(r io.Reader, n *int64, err *error) uint8 {
@@ -40,40 +40,40 @@ func ReadUInt8(r io.Reader, n *int64, err *error) uint8 {
// Int16
func WriteInt16(w io.Writer, i int16, n *int64, err *error) {
func WriteInt16(i int16, w io.Writer, n *int64, err *error) {
buf := make([]byte, 2)
binary.LittleEndian.PutUint16(buf, uint16(i))
*n += 2
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadInt16(r io.Reader, n *int64, err *error) int16 {
buf := make([]byte, 2)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return int16(binary.LittleEndian.Uint16(buf))
}
// UInt16
func WriteUInt16(w io.Writer, i uint16, n *int64, err *error) {
func WriteUInt16(i uint16, w io.Writer, n *int64, err *error) {
buf := make([]byte, 2)
binary.LittleEndian.PutUint16(buf, uint16(i))
*n += 2
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadUInt16(r io.Reader, n *int64, err *error) uint16 {
buf := make([]byte, 2)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return uint16(binary.LittleEndian.Uint16(buf))
}
// []UInt16
func WriteUInt16s(w io.Writer, iz []uint16, n *int64, err *error) {
WriteUInt32(w, uint32(len(iz)), n, err)
func WriteUInt16s(iz []uint16, w io.Writer, n *int64, err *error) {
WriteUInt32(uint32(len(iz)), w, n, err)
for _, i := range iz {
WriteUInt16(w, i, n, err)
WriteUInt16(i, w, n, err)
if *err != nil {
return
}
@@ -98,71 +98,71 @@ func ReadUInt16s(r io.Reader, n *int64, err *error) []uint16 {
// Int32
func WriteInt32(w io.Writer, i int32, n *int64, err *error) {
func WriteInt32(i int32, w io.Writer, n *int64, err *error) {
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(i))
*n += 4
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadInt32(r io.Reader, n *int64, err *error) int32 {
buf := make([]byte, 4)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return int32(binary.LittleEndian.Uint32(buf))
}
// UInt32
func WriteUInt32(w io.Writer, i uint32, n *int64, err *error) {
func WriteUInt32(i uint32, w io.Writer, n *int64, err *error) {
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(i))
*n += 4
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadUInt32(r io.Reader, n *int64, err *error) uint32 {
buf := make([]byte, 4)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return uint32(binary.LittleEndian.Uint32(buf))
}
// Int64
func WriteInt64(w io.Writer, i int64, n *int64, err *error) {
func WriteInt64(i int64, w io.Writer, n *int64, err *error) {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, uint64(i))
*n += 8
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadInt64(r io.Reader, n *int64, err *error) int64 {
buf := make([]byte, 8)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return int64(binary.LittleEndian.Uint64(buf))
}
// UInt64
func WriteUInt64(w io.Writer, i uint64, n *int64, err *error) {
func WriteUInt64(i uint64, w io.Writer, n *int64, err *error) {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, uint64(i))
*n += 8
WriteTo(w, buf, n, err)
WriteTo(buf, w, n, err)
}
func ReadUInt64(r io.Reader, n *int64, err *error) uint64 {
buf := make([]byte, 8)
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return uint64(binary.LittleEndian.Uint64(buf))
}
// VarInt
func WriteVarInt(w io.Writer, i int, n *int64, err *error) {
func WriteVarInt(i int, w io.Writer, n *int64, err *error) {
buf := make([]byte, 9)
n_ := int64(binary.PutVarint(buf, int64(i)))
*n += n_
WriteTo(w, buf[:n_], n, err)
WriteTo(buf[:n_], w, n, err)
}
func ReadVarInt(r io.Reader, n *int64, err *error) int {
@@ -174,11 +174,11 @@ func ReadVarInt(r io.Reader, n *int64, err *error) int {
// UVarInt
func WriteUVarInt(w io.Writer, i uint, n *int64, err *error) {
func WriteUVarInt(i uint, w io.Writer, n *int64, err *error) {
buf := make([]byte, 9)
n_ := int64(binary.PutUvarint(buf, uint64(i)))
*n += n_
WriteTo(w, buf[:n_], n, err)
WriteTo(buf[:n_], w, n, err)
}
func ReadUVarInt(r io.Reader, n *int64, err *error) uint {

198
binary/reflect.go Normal file
View File

@@ -0,0 +1,198 @@
package binary
import (
"fmt"
"io"
"reflect"
)
type TypeInfo struct {
Type reflect.Type // The type
Encoder Encoder // Optional custom encoder function
Decoder Decoder // Optional custom decoder function
}
// If a type implements TypeByte, the byte is included
// as the first byte for encoding. This is used to encode
// interfaces/union types. In this case the decoding should
// be done manually with a switch statement, and so the
// reflection-based decoder provided here does not expect this
// prefix byte.
// See the reactor implementations for use-cases.
type HasTypeByte interface {
TypeByte() byte
}
var typeInfos = map[reflect.Type]*TypeInfo{}
func RegisterType(info *TypeInfo) bool {
// Register the type info
typeInfos[info.Type] = info
// Also register the underlying struct's info, if info.Type is a pointer.
if info.Type.Kind() == reflect.Ptr {
rt := info.Type.Elem()
typeInfos[rt] = info
}
return true
}
func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *error) {
// First, 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 {
rv, rt = rv.Elem(), rt.Elem()
}
// Custom decoder
typeInfo := typeInfos[rt]
if typeInfo != nil && typeInfo.Decoder != nil {
decoded := typeInfo.Decoder(r, n, err)
decodedRv := reflect.Indirect(reflect.ValueOf(decoded))
rv.Set(decodedRv)
return
}
switch rt.Kind() {
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
byteslice := ReadByteSlice(r, n, err)
rv.Set(reflect.ValueOf(byteslice))
} else {
// Read length
length := int(ReadUVarInt(r, n, err))
sliceRv := reflect.MakeSlice(rt, length, length)
// Read elems
for i := 0; i < length; i++ {
elemRv := sliceRv.Index(i)
readReflect(elemRv, elemRt, r, n, err)
}
rv.Set(sliceRv)
}
case reflect.Struct:
numFields := rt.NumField()
for i := 0; i < numFields; i++ {
field := rt.Field(i)
if field.Anonymous {
continue
}
fieldRv := rv.Field(i)
readReflect(fieldRv, field.Type, r, n, err)
}
case reflect.String:
str := ReadString(r, n, err)
rv.SetString(str)
case reflect.Uint64:
num := ReadUInt64(r, n, err)
rv.SetUint(uint64(num))
case reflect.Uint32:
num := ReadUInt32(r, n, err)
rv.SetUint(uint64(num))
case reflect.Uint16:
num := ReadUInt16(r, n, err)
rv.SetUint(uint64(num))
case reflect.Uint8:
num := ReadUInt8(r, n, err)
rv.SetUint(uint64(num))
case reflect.Uint:
num := ReadUVarInt(r, n, err)
rv.SetUint(uint64(num))
default:
panic(fmt.Sprintf("Unknown field type %v", rt.Kind()))
}
}
func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
// Custom encoder
typeInfo := typeInfos[rt]
if typeInfo != nil && typeInfo.Encoder != nil {
typeInfo.Encoder(rv.Interface(), w, n, err)
return
}
// Dereference pointer or interface
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
rv = rv.Elem()
} else if rt.Kind() == reflect.Interface {
rv = rv.Elem()
rt = rv.Type()
}
// Write TypeByte prefix
if rt.Implements(reflect.TypeOf((*HasTypeByte)(nil)).Elem()) {
WriteByte(rv.Interface().(HasTypeByte).TypeByte(), w, n, err)
}
switch rt.Kind() {
case reflect.Slice:
elemRt := rt.Elem()
if elemRt.Kind() == reflect.Uint8 {
// Special case: Byteslices
byteslice := rv.Interface().([]byte)
WriteByteSlice(byteslice, w, n, err)
} else {
// Write length
length := rv.Len()
WriteUVarInt(uint(length), w, n, err)
// Write elems
for i := 0; i < length; i++ {
elemRv := rv.Index(i)
writeReflect(elemRv, elemRt, w, n, err)
}
}
case reflect.Struct:
numFields := rt.NumField()
for i := 0; i < numFields; i++ {
field := rt.Field(i)
if field.Anonymous {
continue
}
fieldRv := rv.Field(i)
writeReflect(fieldRv, field.Type, w, n, err)
}
case reflect.String:
WriteString(rv.String(), w, n, err)
case reflect.Uint64:
WriteUInt64(rv.Uint(), w, n, err)
case reflect.Uint32:
WriteUInt32(uint32(rv.Uint()), w, n, err)
case reflect.Uint16:
WriteUInt16(uint16(rv.Uint()), w, n, err)
case reflect.Uint8:
WriteUInt8(uint8(rv.Uint()), w, n, err)
case reflect.Uint:
WriteUVarInt(uint(rv.Uint()), w, n, err)
default:
panic(fmt.Sprintf("Unknown field type %v", rt.Kind()))
}
}

View File

@@ -4,9 +4,9 @@ import "io"
// String
func WriteString(w io.Writer, s string, n *int64, err *error) {
WriteUInt32(w, uint32(len(s)), n, err)
WriteTo(w, []byte(s), n, err)
func WriteString(s string, w io.Writer, n *int64, err *error) {
WriteUInt32(uint32(len(s)), w, n, err)
WriteTo([]byte(s), w, n, err)
}
func ReadString(r io.Reader, n *int64, err *error) string {
@@ -15,6 +15,6 @@ func ReadString(r io.Reader, n *int64, err *error) string {
return ""
}
buf := make([]byte, int(length))
ReadFull(r, buf, n, err)
ReadFull(buf, r, n, err)
return string(buf)
}

View File

@@ -7,8 +7,8 @@ import (
// Time
func WriteTime(w io.Writer, t time.Time, n *int64, err *error) {
WriteInt64(w, t.UnixNano(), n, err)
func WriteTime(t time.Time, w io.Writer, n *int64, err *error) {
WriteInt64(t.UnixNano(), w, n, err)
}
func ReadTime(r io.Reader, n *int64, err *error) time.Time {

View File

@@ -2,36 +2,46 @@ package binary
import (
"bytes"
"code.google.com/p/go.crypto/ripemd160"
"crypto/sha256"
)
func BinaryBytes(b Binary) []byte {
buf := bytes.NewBuffer(nil)
_, err := b.WriteTo(buf)
if err != nil {
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)
}
return buf.Bytes()
return w.Bytes()
}
// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b Binary) bool {
func BinaryEqual(a, b interface{}) bool {
aBytes := BinaryBytes(a)
bBytes := BinaryBytes(b)
return bytes.Equal(aBytes, bBytes)
}
// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b Binary) int {
func BinaryCompare(a, b interface{}) int {
aBytes := BinaryBytes(a)
bBytes := BinaryBytes(b)
return bytes.Compare(aBytes, bBytes)
}
func BinaryHash(b Binary) []byte {
hasher := sha256.New()
_, err := b.WriteTo(hasher)
if err != nil {
func BinarySha256(o interface{}) []byte {
hasher, n, err := sha256.New(), new(int64), new(error)
WriteBinary(o, hasher, n, err)
if *err != nil {
panic(err)
}
return hasher.Sum(nil)
}
func BinaryRipemd160(o interface{}) []byte {
hasher, n, err := ripemd160.New(), new(int64), new(error)
WriteBinary(o, hasher, n, err)
if *err != nil {
panic(err)
}
return hasher.Sum(nil)