From 1c4f5e2506a935cbb11fc7f21e11b2a5e1a23c37 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 4 Jun 2014 01:39:50 -0700 Subject: [PATCH] refactor out binary --- binary/binary.go | 9 +++++++++ merkle/binary.go => binary/codec.go | 2 +- {merkle => binary}/int.go | 24 +++++++++++------------ {merkle => binary}/string.go | 6 +++--- merkle/iavl.go | 30 +++++++++++++++-------------- merkle/iavl_test.go | 1 + merkle/types.go | 10 ++-------- merkle/util.go | 24 +++++++++++++++++++++++ 8 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 binary/binary.go rename merkle/binary.go => binary/codec.go (99%) rename {merkle => binary}/int.go (91%) rename {merkle => binary}/string.go (93%) diff --git a/binary/binary.go b/binary/binary.go new file mode 100644 index 000000000..f13e38b12 --- /dev/null +++ b/binary/binary.go @@ -0,0 +1,9 @@ +package binary + +import "io" + +type Binary interface { + ByteSize() int + WriteTo(io.Writer) (int64, error) + Equals(Binary) bool +} diff --git a/merkle/binary.go b/binary/codec.go similarity index 99% rename from merkle/binary.go rename to binary/codec.go index bddb9ae68..96e73e248 100644 --- a/merkle/binary.go +++ b/binary/codec.go @@ -1,4 +1,4 @@ -package merkle +package binary const ( TYPE_NIL = byte(0x00) diff --git a/merkle/int.go b/binary/int.go similarity index 91% rename from merkle/int.go rename to binary/int.go index cf12326ea..f7de9cd4d 100644 --- a/merkle/int.go +++ b/binary/int.go @@ -1,4 +1,4 @@ -package merkle +package binary import ( "io" @@ -24,7 +24,7 @@ func (self Byte) Equals(other Binary) bool { return self == other } -func (self Byte) Less(other Key) bool { +func (self Byte) Less(other Binary) bool { if o, ok := other.(Byte); ok { return self < o } else { @@ -52,7 +52,7 @@ func (self Int8) Equals(other Binary) bool { return self == other } -func (self Int8) Less(other Key) bool { +func (self Int8) Less(other Binary) bool { if o, ok := other.(Int8); ok { return self < o } else { @@ -80,7 +80,7 @@ func (self UInt8) Equals(other Binary) bool { return self == other } -func (self UInt8) Less(other Key) bool { +func (self UInt8) Less(other Binary) bool { if o, ok := other.(UInt8); ok { return self < o } else { @@ -108,7 +108,7 @@ func (self Int16) Equals(other Binary) bool { return self == other } -func (self Int16) Less(other Key) bool { +func (self Int16) Less(other Binary) bool { if o, ok := other.(Int16); ok { return self < o } else { @@ -136,7 +136,7 @@ func (self UInt16) Equals(other Binary) bool { return self == other } -func (self UInt16) Less(other Key) bool { +func (self UInt16) Less(other Binary) bool { if o, ok := other.(UInt16); ok { return self < o } else { @@ -164,7 +164,7 @@ func (self Int32) Equals(other Binary) bool { return self == other } -func (self Int32) Less(other Key) bool { +func (self Int32) Less(other Binary) bool { if o, ok := other.(Int32); ok { return self < o } else { @@ -192,7 +192,7 @@ func (self UInt32) Equals(other Binary) bool { return self == other } -func (self UInt32) Less(other Key) bool { +func (self UInt32) Less(other Binary) bool { if o, ok := other.(UInt32); ok { return self < o } else { @@ -220,7 +220,7 @@ func (self Int64) Equals(other Binary) bool { return self == other } -func (self Int64) Less(other Key) bool { +func (self Int64) Less(other Binary) bool { if o, ok := other.(Int64); ok { return self < o } else { @@ -248,7 +248,7 @@ func (self UInt64) Equals(other Binary) bool { return self == other } -func (self UInt64) Less(other Key) bool { +func (self UInt64) Less(other Binary) bool { if o, ok := other.(UInt64); ok { return self < o } else { @@ -276,7 +276,7 @@ func (self Int) Equals(other Binary) bool { return self == other } -func (self Int) Less(other Key) bool { +func (self Int) Less(other Binary) bool { if o, ok := other.(Int); ok { return self < o } else { @@ -303,7 +303,7 @@ func (self UInt) Equals(other Binary) bool { return self == other } -func (self UInt) Less(other Key) bool { +func (self UInt) Less(other Binary) bool { if o, ok := other.(UInt); ok { return self < o } else { diff --git a/merkle/string.go b/binary/string.go similarity index 93% rename from merkle/string.go rename to binary/string.go index a7dc35092..3dd91cbe0 100644 --- a/merkle/string.go +++ b/binary/string.go @@ -1,4 +1,4 @@ -package merkle +package binary import "io" import "bytes" @@ -12,7 +12,7 @@ func (self String) Equals(other Binary) bool { return self == other } -func (self String) Less(other Key) bool { +func (self String) Less(other Binary) bool { if o, ok := other.(String); ok { return self < o } else { @@ -49,7 +49,7 @@ func (self ByteSlice) Equals(other Binary) bool { } } -func (self ByteSlice) Less(other Key) bool { +func (self ByteSlice) Less(other Binary) bool { if o, ok := other.(ByteSlice); ok { return bytes.Compare(self, o) < 0 // -1 if a < b } else { diff --git a/merkle/iavl.go b/merkle/iavl.go index 008383b51..44680df0d 100644 --- a/merkle/iavl.go +++ b/merkle/iavl.go @@ -1,7 +1,7 @@ package merkle import ( - //"fmt" + . "github.com/tendermint/tendermint/binary" "bytes" "io" "crypto/sha256" @@ -195,7 +195,7 @@ func (self *IAVLNode) Hash() (ByteSlice, uint64) { } hasher := sha256.New() - _, hashCount, err := self.saveToCountHashes(hasher) + _, hashCount, err := self.saveToCountHashes(hasher, false) if err != nil { panic(err) } self.hash = hasher.Sum(nil) @@ -325,24 +325,26 @@ func (self *IAVLNode) ByteSize() int { } func (self *IAVLNode) WriteTo(w io.Writer) (n int64, err error) { - n, _, err = self.saveToCountHashes(w) + n, _, err = self.saveToCountHashes(w, true) return } -func (self *IAVLNode) saveToCountHashes(w io.Writer) (n int64, hashCount uint64, err error) { +func (self *IAVLNode) saveToCountHashes(w io.Writer, meta bool) (n int64, hashCount uint64, err error) { var _n int64 - // height & size - _n, err = UInt8(self.height).WriteTo(w) - if err != nil { return } else { n += _n } - _n, err = UInt64(self.size).WriteTo(w) - if err != nil { return } else { n += _n } + if meta { + // height & size + _n, err = UInt8(self.height).WriteTo(w) + if err != nil { return } else { n += _n } + _n, err = UInt64(self.size).WriteTo(w) + if err != nil { return } else { n += _n } - // key - _n, err = Byte(GetBinaryType(self.key)).WriteTo(w) - if err != nil { return } else { n += _n } - _n, err = self.key.WriteTo(w) - if err != nil { return } else { n += _n } + // key + _n, err = Byte(GetBinaryType(self.key)).WriteTo(w) + if err != nil { return } else { n += _n } + _n, err = self.key.WriteTo(w) + if err != nil { return } else { n += _n } + } if self.height == 0 { // value diff --git a/merkle/iavl_test.go b/merkle/iavl_test.go index 9a6c11bed..c81f7298b 100644 --- a/merkle/iavl_test.go +++ b/merkle/iavl_test.go @@ -1,6 +1,7 @@ package merkle import ( + . "github.com/tendermint/tendermint/binary" "testing" "fmt" "os" diff --git a/merkle/types.go b/merkle/types.go index 3e2fbaa92..b379adba2 100644 --- a/merkle/types.go +++ b/merkle/types.go @@ -1,23 +1,17 @@ package merkle import ( - "io" + . "github.com/tendermint/tendermint/binary" "fmt" ) -type Binary interface { - ByteSize() int - WriteTo(io.Writer) (int64, error) - Equals(Binary) bool -} - type Value interface { Binary } type Key interface { Binary - Less(b Key) bool + Less(b Binary) bool } type Db interface { diff --git a/merkle/util.go b/merkle/util.go index f2183d913..0b5b7ebcf 100644 --- a/merkle/util.go +++ b/merkle/util.go @@ -1,10 +1,34 @@ package merkle import ( + . "github.com/tendermint/tendermint/binary" "os" "fmt" + "crypto/sha256" ) +/* +Compute a deterministic merkle hash from a list of byteslices. +*/ +func HashFromBinarySlice(items []Binary) ByteSlice { + switch len(items) { + case 0: + panic("Cannot compute hash of empty slice") + case 1: + hasher := sha256.New() + _, err := items[0].WriteTo(hasher) + if err != nil { panic(err) } + return ByteSlice(hasher.Sum(nil)) + default: + hasher := sha256.New() + _, err := HashFromBinarySlice(items[0:len(items)/2]).WriteTo(hasher) + if err != nil { panic(err) } + _, err = HashFromBinarySlice(items[len(items)/2:]).WriteTo(hasher) + if err != nil { panic(err) } + return ByteSlice(hasher.Sum(nil)) + } +} + func PrintIAVLNode(node *IAVLNode) { fmt.Println("==== NODE") if node != nil {