mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
Use errors (instead of error codes)
This commit is contained in:
parent
44a9a39c84
commit
fe85196dd6
2 changed files with 49 additions and 97 deletions
|
|
@ -58,9 +58,9 @@ func (t BTree) Root() []byte {
|
||||||
// if incorrectly built or modified.
|
// if incorrectly built or modified.
|
||||||
// Checks the rep invariants
|
// Checks the rep invariants
|
||||||
func (t BTree) Validate() error {
|
func (t BTree) Validate() error {
|
||||||
count, height, error := t.root.validate()
|
count, height, err := t.root.validate()
|
||||||
if error != nil {
|
if err != nil {
|
||||||
return error
|
return err
|
||||||
}
|
}
|
||||||
if count != t.count {
|
if count != t.count {
|
||||||
return fmt.Errorf("Incorrect count. Was %d, should be %d", t.count, count)
|
return fmt.Errorf("Incorrect count. Was %d, should be %d", t.count, count)
|
||||||
|
|
@ -122,7 +122,7 @@ func rootHash(count uint64, data []byte) []byte {
|
||||||
h.Reset()
|
h.Reset()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
binary.Write(h, binary.LittleEndian, count)
|
binary.Write(h, binary.LittleEndian, count)
|
||||||
return h.Sum(make([]byte, 0))
|
return h.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHash(left, right *node) []byte {
|
func makeHash(left, right *node) []byte {
|
||||||
|
|
@ -156,21 +156,21 @@ func GetHeight(count uint64) int {
|
||||||
// BMT - The BMT Representation of the data
|
// BMT - The BMT Representation of the data
|
||||||
// ROOT - BMT Root
|
// ROOT - BMT Root
|
||||||
// Count - Numers of leafs at the BMT
|
// Count - Numers of leafs at the BMT
|
||||||
// error - if exist validation(-1) count(-2) ok(0)
|
// error -
|
||||||
func BuildBMT(h Hasher, data []byte, segmentsize int) (bmt *BTree, roor *Root, count int, errorcode int) {
|
func BuildBMT(h Hasher, data []byte, segmentsize int) (bmt *BTree, roor *Root, count int, err error) {
|
||||||
blocks := splitData(data, segmentsize)
|
blocks := splitData(data, segmentsize)
|
||||||
hashFunc = h
|
hashFunc = h
|
||||||
leafcount := len(blocks)
|
leafcount := len(blocks)
|
||||||
tree := Build(blocks)
|
tree := Build(blocks)
|
||||||
err := tree.Validate()
|
err = tree.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, -1
|
return nil, nil, 0, errors.New("Validation error")
|
||||||
}
|
}
|
||||||
if tree.Count() != uint64(leafcount) {
|
if tree.Count() != uint64(leafcount) {
|
||||||
return nil, nil, 0, -2
|
return nil, nil, 0, errors.New("Validation count error")
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree, &Root{uint64(leafcount), tree.Root()}, leafcount, 0
|
return tree, &Root{uint64(leafcount), tree.Root()}, leafcount, nil
|
||||||
//r := Root{uint64(count), tree.Root()}
|
//r := Root{uint64(count), tree.Root()}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -260,30 +260,29 @@ type Root struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proves the inclusion of an element at the given index with the value thats the first entry in proof
|
// Proves the inclusion of an element at the given index with the value thats the first entry in proof
|
||||||
func (r *Root) CheckProof(h Hasher, proof [][]byte, index int) bool {
|
func (r *Root) CheckProof(h Hasher, proof [][]byte, index int) (bool, error) {
|
||||||
hashFunc = h
|
hashFunc = h
|
||||||
t_height := GetHeight(r.Count)
|
theight := GetHeight(r.Count)
|
||||||
root, ok := checkNode(t_height, proof, uint64(index), r.Count)
|
var root, ok, err = checkNode(theight, proof, uint64(index), r.Count)
|
||||||
base := rootHash(r.Count, root)
|
base := rootHash(r.Count, root)
|
||||||
return ok && bytes.Equal(r.Base, base)
|
return ok && bytes.Equal(r.Base, base), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkNode(height int, proof [][]byte, index, count uint64) ([]byte, bool) {
|
func checkNode(height int, proof [][]byte, index uint64, count uint64) (hash []byte, ok bool, err error) {
|
||||||
if len(proof) == 0 {
|
if len(proof) == 0 {
|
||||||
fmt.Println("Empty")
|
return nil, false, errors.New("checkNode : proof is empty")
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
if count <= index {
|
if count <= index {
|
||||||
fmt.Println("bad count", count, index)
|
fmt.Println("bad count", count, index)
|
||||||
return nil, false
|
return nil, false, fmt.Errorf("bad count %d at index %d", count, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
if height == 1 {
|
if height == 1 {
|
||||||
if index != 0 || len(proof) != 1 {
|
if index != 0 || len(proof) != 1 {
|
||||||
fmt.Println("BAD", index, proof)
|
fmt.Println("BAD", index, proof)
|
||||||
return nil, false
|
return nil, false, fmt.Errorf("BAD %d %d", index, proof)
|
||||||
}
|
}
|
||||||
return proof[0], true
|
return proof[0], true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
childIndex := index >> uint(height-2)
|
childIndex := index >> uint(height-2)
|
||||||
|
|
@ -291,7 +290,7 @@ func checkNode(height int, proof [][]byte, index, count uint64) ([]byte, bool) {
|
||||||
nextIndex := index & mask
|
nextIndex := index & mask
|
||||||
|
|
||||||
var data []byte
|
var data []byte
|
||||||
var ok bool
|
//var ok bool
|
||||||
|
|
||||||
h := hashFunc()
|
h := hashFunc()
|
||||||
h.Reset()
|
h.Reset()
|
||||||
|
|
@ -301,7 +300,7 @@ func checkNode(height int, proof [][]byte, index, count uint64) ([]byte, bool) {
|
||||||
if childIndex == 1 {
|
if childIndex == 1 {
|
||||||
nextCount = count & mask
|
nextCount = count & mask
|
||||||
h.Write(proof[last])
|
h.Write(proof[last])
|
||||||
data, ok = checkNode(height-1, proof[:last], nextIndex, nextCount)
|
data, ok, err = checkNode(height-1, proof[:last], nextIndex, nextCount)
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
} else {
|
} else {
|
||||||
nextCount = count
|
nextCount = count
|
||||||
|
|
@ -309,39 +308,38 @@ func checkNode(height int, proof [][]byte, index, count uint64) ([]byte, bool) {
|
||||||
nextCount = ^mask
|
nextCount = ^mask
|
||||||
}
|
}
|
||||||
if count == nextCount {
|
if count == nextCount {
|
||||||
data, ok = checkNode(height-1, proof, nextIndex, nextCount)
|
data, ok, err = checkNode(height-1, proof, nextIndex, nextCount)
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
} else {
|
} else {
|
||||||
data, ok = checkNode(height-1, proof[:last], nextIndex, nextCount)
|
data, ok, err = checkNode(height-1, proof[:last], nextIndex, nextCount)
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
h.Write(proof[last])
|
h.Write(proof[last])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := h.Sum(make([]byte, 0))
|
hash = h.Sum(make([]byte, 0))
|
||||||
return hash, ok
|
return hash, ok, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShakeHash defines the interface to hash functions that
|
// BMTHash defines the interface to hash functions that
|
||||||
// support arbitrary-length output.
|
|
||||||
type BMTHash interface {
|
type BMTHash interface {
|
||||||
// Write absorbs more data into the hash's state. It panics if input is
|
// Write absorbs more data into the hash's state. It panics if input is
|
||||||
// written to it after output has been read from it.
|
// written to it after output has been read from it.
|
||||||
io.Writer
|
io.Writer
|
||||||
|
|
||||||
// Read reads more output from the hash; reading affects the hash's
|
// Read reads more output from the hash; reading affects the hash's
|
||||||
// state. (ShakeHash.Read is thus very different from Hash.Sum)
|
// state.
|
||||||
// It never returns an error.
|
// It never returns an error.
|
||||||
io.Reader
|
io.Reader
|
||||||
|
|
||||||
// Clone returns a copy of the ShakeHash in its current state.
|
// Clone returns a copy of the BMTHash in its current state.
|
||||||
Clone() BMTHash
|
Clone() BMTHash
|
||||||
|
|
||||||
// Reset resets the ShakeHash to its initial state.
|
// Reset resets the BMTHash to its initial state.
|
||||||
Reset()
|
Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset clears the internal state by zeroing the sponge state and
|
// Reset clears the internal state
|
||||||
func (d *state) Reset() {
|
func (d *state) Reset() {
|
||||||
d.root = Root{Count: 0, Base: nil}
|
d.root = Root{Count: 0, Base: nil}
|
||||||
d.btree = BTree{count: 0, root: nil, rootHash: nil}
|
d.btree = BTree{count: 0, root: nil, rootHash: nil}
|
||||||
|
|
@ -354,7 +352,7 @@ func (d *state) Write(p []byte) (written int, err error) {
|
||||||
d.btree = *tree
|
d.btree = *tree
|
||||||
d.root = *r
|
d.root = *r
|
||||||
|
|
||||||
if err1 != 0 {
|
if err1 != nil {
|
||||||
err = errors.New("bmt write error")
|
err = errors.New("bmt write error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,53 +2,17 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetHeight(t *testing.T) {
|
|
||||||
data := [][2]int{
|
|
||||||
{0, 0},
|
|
||||||
{1, 1},
|
|
||||||
{2, 2},
|
|
||||||
{3, 3},
|
|
||||||
{4, 3},
|
|
||||||
{255, 9},
|
|
||||||
{256, 9},
|
|
||||||
{257, 10},
|
|
||||||
}
|
|
||||||
for _, v := range data {
|
|
||||||
h := GetHeight(uint64(v[0]))
|
|
||||||
if !(v[1] == h) {
|
|
||||||
t.Errorf("GetHeight(%d)!=%d (was %d)", v[0], v[1], h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetHeight2(t *testing.T) {
|
|
||||||
for i := 1; i < 1000; i++ {
|
|
||||||
h := GetHeight(uint64(i))
|
|
||||||
upperBound := 1 << uint(h-1)
|
|
||||||
lowerBound := (1 << uint(h-2)) + 1
|
|
||||||
if i < lowerBound {
|
|
||||||
t.Errorf("GetHeight(%d) too high: %d", i, h)
|
|
||||||
}
|
|
||||||
if i > upperBound {
|
|
||||||
t.Errorf("GetHeight(%d) too low: %d", i, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildBMT3(t *testing.T) {
|
func TestBuildBMT3(t *testing.T) {
|
||||||
|
|
||||||
// Grab some data to make the tree out of, and partition
|
// Grab some data to make the tree out of, and partition
|
||||||
data, err := ioutil.ReadFile("binarymerkle_test.go") // assume testdata exists
|
data := make([]byte, 4096)
|
||||||
if err != nil {
|
tdata := testDataReader(4096)
|
||||||
fmt.Println(err)
|
tdata.Read(data)
|
||||||
return
|
|
||||||
}
|
|
||||||
var thashFunc = MakeHashFunc("BMTSHA3")
|
var thashFunc = MakeHashFunc("BMTSHA3")
|
||||||
var h = thashFunc()
|
var h = thashFunc()
|
||||||
h.Reset()
|
h.Reset()
|
||||||
|
|
@ -73,35 +37,28 @@ func TestBuildBMT3(t *testing.T) {
|
||||||
func TestBuildBMT(t *testing.T) {
|
func TestBuildBMT(t *testing.T) {
|
||||||
|
|
||||||
// Grab some data to make the tree out of, and partition
|
// Grab some data to make the tree out of, and partition
|
||||||
data, err := ioutil.ReadFile("binarymerkle_test.go") // assume testdata exists
|
data := make([]byte, 4096)
|
||||||
if err != nil {
|
tdata := testDataReader(4096)
|
||||||
fmt.Println(err)
|
tdata.Read(data)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tree, r, count, err1 := BuildBMT(sha3.NewKeccak256, data, 1)
|
tree, r, count, err1 := BuildBMT(sha3.NewKeccak256, data, 1)
|
||||||
|
|
||||||
switch err1 {
|
if err1 != nil {
|
||||||
case -1:
|
fmt.Println(err1)
|
||||||
|
|
||||||
t.Errorf("BMT Validation error")
|
|
||||||
return
|
return
|
||||||
case -2:
|
|
||||||
t.Errorf("BMT leaf count validation error")
|
|
||||||
return
|
|
||||||
case 0:
|
|
||||||
fmt.Println("Build BMT OK ", count)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(tree.Root())
|
fmt.Println(tree.Root())
|
||||||
|
|
||||||
|
//var ok bool
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
p := tree.InclusionProof(i)
|
p := tree.InclusionProof(i)
|
||||||
|
|
||||||
fmt.Println(p)
|
fmt.Println(p)
|
||||||
|
|
||||||
ok := r.CheckProof(sha3.NewKeccak256, p, i)
|
ok, err := r.CheckProof(sha3.NewKeccak256, p, i)
|
||||||
if !ok {
|
|
||||||
|
if !ok || (err != nil) {
|
||||||
t.Errorf("proof %d failed", i)
|
t.Errorf("proof %d failed", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,12 +67,9 @@ func TestBuildBMT(t *testing.T) {
|
||||||
|
|
||||||
func TestBuildBMT2(t *testing.T) {
|
func TestBuildBMT2(t *testing.T) {
|
||||||
|
|
||||||
// Grab some data to make the tree out of, and partition
|
data := make([]byte, 4096)
|
||||||
data, err := ioutil.ReadFile("binarymerkle_test.go") // assume testdata exists
|
tdata := testDataReader(4096)
|
||||||
if err != nil {
|
tdata.Read(data)
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(len(data))
|
fmt.Println(len(data))
|
||||||
blocks := splitData(data, 2)
|
blocks := splitData(data, 2)
|
||||||
|
|
@ -142,8 +96,8 @@ func TestBuildBMT2(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println(p)
|
fmt.Println(p)
|
||||||
|
|
||||||
ok := r.CheckProof(sha3.NewKeccak256, p, i)
|
ok, err := r.CheckProof(sha3.NewKeccak256, p, i)
|
||||||
if !ok {
|
if !ok || (err != nil) {
|
||||||
t.Errorf("proof %d failed", i)
|
t.Errorf("proof %d failed", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue