diff --git a/Gopkg.lock b/Gopkg.lock index 39bc61be055d7c67415bddc349cbad63666cebbc..f640389d9d3e7f6796090d4aa90d53bb4722ec31 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -487,12 +487,12 @@ version = "0.10.1" [[projects]] - digest = "1:76c7684f6ff9b92dd8f934ad853838e207ab4b7d68927f95f5ba785d8bea56d2" + digest = "1:95454de4bf99bf62e6e3b59724a712e954e1c8d9956e0bc098699179ad1168c6" name = "github.com/tendermint/iavl" packages = ["."] pruneopts = "NUT" - revision = "e5726c0066ccdd299a2ec9262f93c7896cdfcd87" - version = "v0.10.0" + revision = "3acc91fb8811db2c5409a855ae1f8e441fe98e2d" + version = "v0.11.0" [[projects]] digest = "1:77fa9bc72848b93790fdad4f728f4ae36a905a51d6056dc72752889157fc37c0" diff --git a/Gopkg.toml b/Gopkg.toml index 6b27396f3916bd79b9cef92f69777ba7e76fd5e1..a31c4f7eeb5d5709c5447c029f611e0dd11e19fb 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -20,7 +20,7 @@ [[constraint]] name = "github.com/tendermint/iavl" - version = "=0.10.0" + version = "=0.11.0" # Haven't made a release since 2016. [[constraint]] diff --git a/txs/tx.go b/txs/tx.go index ea5c374288a6f9d13c7ae41f918a31820e85bf1e..cc2005218704a18270633c31335e06fcc61eb27c 100644 --- a/txs/tx.go +++ b/txs/tx.go @@ -18,7 +18,7 @@ import ( "encoding/json" "fmt" - "github.com/tendermint/tmlibs/merkle/tmhash" + "github.com/tendermint/tendermint/crypto/tmhash" "github.com/hyperledger/burrow/acm" "github.com/hyperledger/burrow/acm/state" diff --git a/vendor/github.com/tendermint/iavl/immutable_tree.go b/vendor/github.com/tendermint/iavl/immutable_tree.go index e334ef52b36b1946e65a08164a34c6e5fa2e0130..5abc91823adbf2636c7c679afd9f9652a1b049c8 100644 --- a/vendor/github.com/tendermint/iavl/immutable_tree.go +++ b/vendor/github.com/tendermint/iavl/immutable_tree.go @@ -39,11 +39,7 @@ func (t *ImmutableTree) String() string { } // Size returns the number of leaf nodes in the tree. -func (t *ImmutableTree) Size() int { - return int(t.Size64()) -} - -func (t *ImmutableTree) Size64() int64 { +func (t *ImmutableTree) Size() int64 { if t.root == nil { return 0 } @@ -51,20 +47,12 @@ func (t *ImmutableTree) Size64() int64 { } // Version returns the version of the tree. -func (t *ImmutableTree) Version() int { - return int(t.Version64()) -} - -func (t *ImmutableTree) Version64() int64 { +func (t *ImmutableTree) Version() int64 { return t.version } // Height returns the height of the tree. -func (t *ImmutableTree) Height() int { - return int(t.Height8()) -} - -func (t *ImmutableTree) Height8() int8 { +func (t *ImmutableTree) Height() int8 { if t.root == nil { return 0 } @@ -98,12 +86,7 @@ func (t *ImmutableTree) hashWithCount() ([]byte, int64) { // Get returns the index and value of the specified key if it exists, or nil // and the next index, if it doesn't. -func (t *ImmutableTree) Get(key []byte) (index int, value []byte) { - index64, value := t.Get64(key) - return int(index64), value -} - -func (t *ImmutableTree) Get64(key []byte) (index int64, value []byte) { +func (t *ImmutableTree) Get(key []byte) (index int64, value []byte) { if t.root == nil { return 0, nil } @@ -111,11 +94,7 @@ func (t *ImmutableTree) Get64(key []byte) (index int64, value []byte) { } // GetByIndex gets the key and value at the specified index. -func (t *ImmutableTree) GetByIndex(index int) (key []byte, value []byte) { - return t.GetByIndex64(int64(index)) -} - -func (t *ImmutableTree) GetByIndex64(index int64) (key []byte, value []byte) { +func (t *ImmutableTree) GetByIndex(index int64) (key []byte, value []byte) { if t.root == nil { return nil, nil } diff --git a/vendor/github.com/tendermint/iavl/key_format.go b/vendor/github.com/tendermint/iavl/key_format.go new file mode 100644 index 0000000000000000000000000000000000000000..b63f9ea7b3896305e68246f7a2fa4d544346a2ba --- /dev/null +++ b/vendor/github.com/tendermint/iavl/key_format.go @@ -0,0 +1,144 @@ +package iavl + +import ( + "encoding/binary" + "fmt" +) + +// Provides a fixed-width lexicographically sortable []byte key format +type KeyFormat struct { + prefix byte + layout []int + length int +} + +// Create a []byte key format based on a single byte prefix and fixed width key segments each of whose length is +// specified by by the corresponding element of layout. +// +// For example, to store keys that could index some objects by a version number and their SHA256 hash using the form: +// 'c<version uint64><hash [32]byte>' then you would define the KeyFormat with: +// +// var keyFormat = NewKeyFormat('c', 8, 32) +// +// Then you can create a key with: +// +// func ObjectKey(version uint64, objectBytes []byte) []byte { +// hasher := sha256.New() +// hasher.Sum(nil) +// return keyFormat.Key(version, hasher.Sum(nil)) +// } +func NewKeyFormat(prefix byte, layout ...int) *KeyFormat { + // For prefix byte + length := 1 + for _, l := range layout { + length += int(l) + } + return &KeyFormat{ + prefix: prefix, + layout: layout, + length: length, + } +} + +// Format the byte segments into the key format - will panic if the segment lengths do not match the layout. +func (kf *KeyFormat) KeyBytes(segments ...[]byte) []byte { + key := make([]byte, kf.length) + key[0] = kf.prefix + n := 1 + for i, s := range segments { + l := kf.layout[i] + if len(s) > l { + panic(fmt.Errorf("length of segment %X provided to KeyFormat.KeyBytes() is longer than the %d bytes "+ + "required by layout for segment %d", s, l, i)) + } + n += l + // Big endian so pad on left if not given the full width for this segment + copy(key[n-len(s):n], s) + } + return key[:n] +} + +// Format the args passed into the key format - will panic if the arguments passed do not match the length +// of the segment to which they correspond. When called with no arguments returns the raw prefix (useful as a start +// element of the entire keys space when sorted lexicographically). +func (kf *KeyFormat) Key(args ...interface{}) []byte { + if len(args) > len(kf.layout) { + panic(fmt.Errorf("KeyFormat.Key() is provided with %d args but format only has %d segments", + len(args), len(kf.layout))) + } + segments := make([][]byte, len(args)) + for i, a := range args { + segments[i] = format(a) + } + return kf.KeyBytes(segments...) +} + +// Reads out the bytes associated with each segment of the key format from key. +func (kf *KeyFormat) ScanBytes(key []byte) [][]byte { + segments := make([][]byte, len(kf.layout)) + n := 1 + for i, l := range kf.layout { + n += l + if n > len(key) { + return segments[:i] + } + segments[i] = key[n-l : n] + } + return segments +} + +// Extracts the segments into the values pointed to by each of args. Each arg must be a pointer to int64, uint64, or +// []byte, and the width of the args must match layout. +func (kf *KeyFormat) Scan(key []byte, args ...interface{}) { + segments := kf.ScanBytes(key) + if len(args) > len(segments) { + panic(fmt.Errorf("KeyFormat.Scan() is provided with %d args but format only has %d segments in key %X", + len(args), len(segments), key)) + } + for i, a := range args { + scan(a, segments[i]) + } +} + +// Return the prefix as a string. +func (kf *KeyFormat) Prefix() string { + return string([]byte{kf.prefix}) +} + +func scan(a interface{}, value []byte) { + switch v := a.(type) { + case *int64: + // Negative values will be mapped correctly when read in as uint64 and then type converted + *v = int64(binary.BigEndian.Uint64(value)) + case *uint64: + *v = binary.BigEndian.Uint64(value) + case *[]byte: + *v = value + default: + panic(fmt.Errorf("KeyFormat scan() does not support scanning value of type %T: %v", a, a)) + } +} + +func format(a interface{}) []byte { + switch v := a.(type) { + case uint64: + return formatUint64(v) + case int64: + return formatUint64(uint64(v)) + // Provide formatting from int,uint as a convenience to avoid casting arguments + case uint: + return formatUint64(uint64(v)) + case int: + return formatUint64(uint64(v)) + case []byte: + return v + default: + panic(fmt.Errorf("KeyFormat format() does not support formatting value of type %T: %v", a, a)) + } +} + +func formatUint64(v uint64) []byte { + bs := make([]byte, 8) + binary.BigEndian.PutUint64(bs, v) + return bs +} diff --git a/vendor/github.com/tendermint/iavl/mutable_tree.go b/vendor/github.com/tendermint/iavl/mutable_tree.go index 8ad073345ce40c6957d6f5ec0c81efccb5b7cd8d..05b89cc32dbe76c303528d26884936e83b65a446 100644 --- a/vendor/github.com/tendermint/iavl/mutable_tree.go +++ b/vendor/github.com/tendermint/iavl/mutable_tree.go @@ -294,7 +294,7 @@ func (tree *MutableTree) Rollback() { // GetVersioned gets the value at the specified key and version. func (tree *MutableTree) GetVersioned(key []byte, version int64) ( - index int, value []byte, + index int64, value []byte, ) { if tree.versions[version] { t, err := tree.GetImmutable(version) diff --git a/vendor/github.com/tendermint/iavl/nodedb.go b/vendor/github.com/tendermint/iavl/nodedb.go index a933b26628dcbd8fbfee84f86c64e2f0048e7bf3..1844ded057c0eccd319191a064b1473242d2cbfc 100644 --- a/vendor/github.com/tendermint/iavl/nodedb.go +++ b/vendor/github.com/tendermint/iavl/nodedb.go @@ -7,27 +7,29 @@ import ( "sort" "sync" + "github.com/tendermint/tendermint/crypto/tmhash" dbm "github.com/tendermint/tendermint/libs/db" ) +const ( + int64Size = 8 + hashSize = tmhash.Size +) + var ( - // All node keys are prefixed with this. This ensures no collision is - // possible with the other keys, and makes them easier to traverse. - nodePrefix = "n/" - nodeKeyFmt = "n/%X" + // All node keys are prefixed with the byte 'n'. This ensures no collision is + // possible with the other keys, and makes them easier to traverse. They are indexed by the node hash. + nodeKeyFormat = NewKeyFormat('n', hashSize) // n<hash> // Orphans are keyed in the database by their expected lifetime. // The first number represents the *last* version at which the orphan needs // to exist, while the second number represents the *earliest* version at // which it is expected to exist - which starts out by being the version // of the node being orphaned. - orphanPrefix = "o/" - orphanPrefixFmt = "o/%010d/" // o/<last-version>/ - orphanKeyFmt = "o/%010d/%010d/%X" // o/<last-version>/<first-version>/<hash> + orphanKeyFormat = NewKeyFormat('o', int64Size, int64Size, hashSize) // o<last-version><first-version><hash> - // r/<version> - rootPrefix = "r/" - rootPrefixFmt = "r/%010d" + // Root nodes are indexed separately by their version + rootKeyFormat = NewKeyFormat('r', int64Size) // r<version> ) type nodeDB struct { @@ -196,7 +198,7 @@ func (ndb *nodeDB) deleteOrphans(version int64) { // See comment on `orphanKeyFmt`. Note that here, `version` and // `toVersion` are always equal. - fmt.Sscanf(string(key), orphanKeyFmt, &toVersion, &fromVersion) + orphanKeyFormat.Scan(key, &toVersion, &fromVersion) // Delete orphan key and reverse-lookup key. ndb.batch.Delete(key) @@ -218,15 +220,15 @@ func (ndb *nodeDB) deleteOrphans(version int64) { } func (ndb *nodeDB) nodeKey(hash []byte) []byte { - return []byte(fmt.Sprintf(nodeKeyFmt, hash)) + return nodeKeyFormat.KeyBytes(hash) } func (ndb *nodeDB) orphanKey(fromVersion, toVersion int64, hash []byte) []byte { - return []byte(fmt.Sprintf(orphanKeyFmt, toVersion, fromVersion, hash)) + return orphanKeyFormat.Key(toVersion, fromVersion, hash) } func (ndb *nodeDB) rootKey(version int64) []byte { - return []byte(fmt.Sprintf(rootPrefixFmt, version)) + return rootKeyFormat.Key(version) } func (ndb *nodeDB) getLatestVersion() int64 { @@ -244,20 +246,16 @@ func (ndb *nodeDB) updateLatestVersion(version int64) { func (ndb *nodeDB) getPreviousVersion(version int64) int64 { itr := ndb.db.ReverseIterator( - []byte(fmt.Sprintf(rootPrefixFmt, version-1)), - []byte(fmt.Sprintf(rootPrefixFmt, 0)), + rootKeyFormat.Key(version-1), + rootKeyFormat.Key(0), ) defer itr.Close() pversion := int64(-1) for ; itr.Valid(); itr.Next() { k := itr.Key() - _, err := fmt.Sscanf(string(k), rootPrefixFmt, &pversion) - if err != nil { - panic(err) - } else { - return pversion - } + rootKeyFormat.Scan(k, &pversion) + return pversion } return 0 @@ -274,13 +272,12 @@ func (ndb *nodeDB) deleteRoot(version int64) { } func (ndb *nodeDB) traverseOrphans(fn func(k, v []byte)) { - ndb.traversePrefix([]byte(orphanPrefix), fn) + ndb.traversePrefix(orphanKeyFormat.Key(), fn) } // Traverse orphans ending at a certain version. func (ndb *nodeDB) traverseOrphansVersion(version int64, fn func(k, v []byte)) { - prefix := fmt.Sprintf(orphanPrefixFmt, version) - ndb.traversePrefix([]byte(prefix), fn) + ndb.traversePrefix(orphanKeyFormat.Key(version), fn) } // Traverse all keys. @@ -339,9 +336,9 @@ func (ndb *nodeDB) getRoot(version int64) []byte { func (ndb *nodeDB) getRoots() (map[int64][]byte, error) { roots := map[int64][]byte{} - ndb.traversePrefix([]byte(rootPrefix), func(k, v []byte) { + ndb.traversePrefix(rootKeyFormat.Key(), func(k, v []byte) { var version int64 - fmt.Sscanf(string(k), rootPrefixFmt, &version) + rootKeyFormat.Scan(k, &version) roots[version] = v }) return roots, nil @@ -426,12 +423,12 @@ func (ndb *nodeDB) size() int { func (ndb *nodeDB) traverseNodes(fn func(hash []byte, node *Node)) { nodes := []*Node{} - ndb.traversePrefix([]byte(nodePrefix), func(key, value []byte) { + ndb.traversePrefix(nodeKeyFormat.Key(), func(key, value []byte) { node, err := MakeNode(value) if err != nil { panic(fmt.Sprintf("Couldn't decode node from database: %v", err)) } - fmt.Sscanf(string(key), nodeKeyFmt, &node.hash) + nodeKeyFormat.Scan(key, &node.hash) nodes = append(nodes, node) }) @@ -448,7 +445,7 @@ func (ndb *nodeDB) String() string { var str string index := 0 - ndb.traversePrefix([]byte(rootPrefix), func(key, value []byte) { + ndb.traversePrefix(rootKeyFormat.Key(), func(key, value []byte) { str += fmt.Sprintf("%s: %x\n", string(key), value) }) str += "\n" @@ -462,11 +459,13 @@ func (ndb *nodeDB) String() string { if len(hash) == 0 { str += fmt.Sprintf("<nil>\n") } else if node == nil { - str += fmt.Sprintf("%s%40x: <nil>\n", nodePrefix, hash) + str += fmt.Sprintf("%s%40x: <nil>\n", nodeKeyFormat.Prefix(), hash) } else if node.value == nil && node.height > 0 { - str += fmt.Sprintf("%s%40x: %s %-16s h=%d version=%d\n", nodePrefix, hash, node.key, "", node.height, node.version) + str += fmt.Sprintf("%s%40x: %s %-16s h=%d version=%d\n", + nodeKeyFormat.Prefix(), hash, node.key, "", node.height, node.version) } else { - str += fmt.Sprintf("%s%40x: %s = %-16s h=%d version=%d\n", nodePrefix, hash, node.key, node.value, node.height, node.version) + str += fmt.Sprintf("%s%40x: %s = %-16s h=%d version=%d\n", + nodeKeyFormat.Prefix(), hash, node.key, node.value, node.height, node.version) } index++ }) diff --git a/vendor/github.com/tendermint/iavl/version.go b/vendor/github.com/tendermint/iavl/version.go index f88f00abc7e5508da298d8235043a0446fc11839..aa993f09b624a595df384fabd6454100b086a894 100644 --- a/vendor/github.com/tendermint/iavl/version.go +++ b/vendor/github.com/tendermint/iavl/version.go @@ -1,4 +1,4 @@ package iavl // Version of iavl. -const Version = "0.10.0" +const Version = "0.11.0"