mirror of
https://github.com/arnaucube/go-merkletree-iden3.git
synced 2026-02-07 03:26:46 +01:00
Merge pull request #13 from iden3/feature/upgrade-linters
Upgrade linter rules
This commit is contained in:
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -13,4 +13,4 @@ jobs:
|
||||
- name: Lint
|
||||
run: |
|
||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||
$(go env GOPATH)/bin/golangci-lint run --timeout=5m -E whitespace -E gosec -E gci -E misspell -E gomnd --max-same-issues 0
|
||||
$(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml
|
||||
|
||||
17
.golangci.yml
Normal file
17
.golangci.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
issues:
|
||||
max-same-issues: 0
|
||||
exclude-use-default: false
|
||||
linters:
|
||||
enable:
|
||||
- whitespace
|
||||
- gosec
|
||||
- gci
|
||||
- misspell
|
||||
- gomnd
|
||||
- gofmt
|
||||
- goimports
|
||||
- lll
|
||||
- golint
|
||||
linters-settings:
|
||||
lll:
|
||||
line-length: 100
|
||||
1
db/db.go
1
db/db.go
@@ -19,7 +19,6 @@ type Storage interface {
|
||||
Get([]byte) ([]byte, error)
|
||||
List(int) ([]KV, error)
|
||||
Close()
|
||||
Info() string
|
||||
Iterate(func([]byte, []byte) (bool, error)) error
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package leveldb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/iden3/go-merkletree/db"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
@@ -11,20 +9,20 @@ import (
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
// LevelDbStorage implements the db.Storage interface
|
||||
type LevelDbStorage struct {
|
||||
// Storage implements the db.Storage interface
|
||||
type Storage struct {
|
||||
ldb *leveldb.DB
|
||||
prefix []byte
|
||||
}
|
||||
|
||||
// LevelDbStorageTx implements the db.Tx interface
|
||||
type LevelDbStorageTx struct {
|
||||
*LevelDbStorage
|
||||
// StorageTx implements the db.Tx interface
|
||||
type StorageTx struct {
|
||||
*Storage
|
||||
cache db.KvMap
|
||||
}
|
||||
|
||||
// NewLevelDbStorage returns a new LevelDbStorage
|
||||
func NewLevelDbStorage(path string, errorIfMissing bool) (*LevelDbStorage, error) {
|
||||
// NewLevelDbStorage returns a new Storage
|
||||
func NewLevelDbStorage(path string, errorIfMissing bool) (*Storage, error) {
|
||||
o := &opt.Options{
|
||||
ErrorIfMissing: errorIfMissing,
|
||||
}
|
||||
@@ -32,57 +30,21 @@ func NewLevelDbStorage(path string, errorIfMissing bool) (*LevelDbStorage, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &LevelDbStorage{ldb, []byte{}}, nil
|
||||
}
|
||||
|
||||
type storageInfo struct {
|
||||
KeyCount int
|
||||
ClaimCount int
|
||||
}
|
||||
|
||||
// Info implements the method Info of the interface db.Storage
|
||||
func (l *LevelDbStorage) Info() string {
|
||||
snapshot, err := l.ldb.GetSnapshot()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
keycount := 0
|
||||
claimcount := 0
|
||||
iter := snapshot.NewIterator(nil, nil)
|
||||
for iter.Next() {
|
||||
if iter.Value()[0] == byte(1) {
|
||||
claimcount++
|
||||
}
|
||||
|
||||
keycount++
|
||||
}
|
||||
iter.Release()
|
||||
if err := iter.Error(); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
json, _ := json.MarshalIndent(
|
||||
storageInfo{
|
||||
KeyCount: keycount,
|
||||
ClaimCount: claimcount,
|
||||
},
|
||||
"", " ",
|
||||
)
|
||||
return string(json)
|
||||
return &Storage{ldb, []byte{}}, nil
|
||||
}
|
||||
|
||||
// WithPrefix implements the method WithPrefix of the interface db.Storage
|
||||
func (l *LevelDbStorage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &LevelDbStorage{l.ldb, db.Concat(l.prefix, prefix)}
|
||||
func (l *Storage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &Storage{l.ldb, db.Concat(l.prefix, prefix)}
|
||||
}
|
||||
|
||||
// NewTx implements the method NewTx of the interface db.Storage
|
||||
func (l *LevelDbStorage) NewTx() (db.Tx, error) {
|
||||
return &LevelDbStorageTx{l, make(db.KvMap)}, nil
|
||||
func (l *Storage) NewTx() (db.Tx, error) {
|
||||
return &StorageTx{l, make(db.KvMap)}, nil
|
||||
}
|
||||
|
||||
// Get retreives a value from a key in the db.Storage
|
||||
func (l *LevelDbStorage) Get(key []byte) ([]byte, error) {
|
||||
func (l *Storage) Get(key []byte) ([]byte, error) {
|
||||
v, err := l.ldb.Get(db.Concat(l.prefix, key[:]), nil)
|
||||
if err == errors.ErrNotFound {
|
||||
return nil, db.ErrNotFound
|
||||
@@ -91,7 +53,7 @@ func (l *LevelDbStorage) Get(key []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Iterate implements the method Iterate of the interface db.Storage
|
||||
func (l *LevelDbStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
func (l *Storage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
// FIXME: Use the prefix!
|
||||
snapshot, err := l.ldb.GetSnapshot()
|
||||
if err != nil {
|
||||
@@ -112,7 +74,7 @@ func (l *LevelDbStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
}
|
||||
|
||||
// Get retreives a value from a key in the interface db.Tx
|
||||
func (tx *LevelDbStorageTx) Get(key []byte) ([]byte, error) {
|
||||
func (tx *StorageTx) Get(key []byte) ([]byte, error) {
|
||||
var err error
|
||||
|
||||
fullkey := db.Concat(tx.prefix, key)
|
||||
@@ -130,14 +92,14 @@ func (tx *LevelDbStorageTx) Get(key []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Put saves a key:value into the db.Storage
|
||||
func (tx *LevelDbStorageTx) Put(k, v []byte) error {
|
||||
func (tx *StorageTx) Put(k, v []byte) error {
|
||||
tx.cache.Put(db.Concat(tx.prefix, k[:]), v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add implements the method Add of the interface db.Tx
|
||||
func (tx *LevelDbStorageTx) Add(atx db.Tx) error {
|
||||
ldbtx := atx.(*LevelDbStorageTx)
|
||||
func (tx *StorageTx) Add(atx db.Tx) error {
|
||||
ldbtx := atx.(*StorageTx)
|
||||
for _, v := range ldbtx.cache {
|
||||
tx.cache.Put(v.K, v.V)
|
||||
}
|
||||
@@ -145,7 +107,7 @@ func (tx *LevelDbStorageTx) Add(atx db.Tx) error {
|
||||
}
|
||||
|
||||
// Commit implements the method Commit of the interface db.Tx
|
||||
func (tx *LevelDbStorageTx) Commit() error {
|
||||
func (tx *StorageTx) Commit() error {
|
||||
var batch leveldb.Batch
|
||||
for _, v := range tx.cache {
|
||||
batch.Put(v.K, v.V)
|
||||
@@ -156,12 +118,12 @@ func (tx *LevelDbStorageTx) Commit() error {
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Tx
|
||||
func (tx *LevelDbStorageTx) Close() {
|
||||
func (tx *StorageTx) Close() {
|
||||
tx.cache = nil
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Storage
|
||||
func (l *LevelDbStorage) Close() {
|
||||
func (l *Storage) Close() {
|
||||
if err := l.ldb.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -169,12 +131,12 @@ func (l *LevelDbStorage) Close() {
|
||||
}
|
||||
|
||||
// LevelDB is an extra method that returns the *leveldb.DB
|
||||
func (l *LevelDbStorage) LevelDB() *leveldb.DB {
|
||||
func (l *Storage) LevelDB() *leveldb.DB {
|
||||
return l.ldb
|
||||
}
|
||||
|
||||
// List implements the method List of the interface db.Storage
|
||||
func (l *LevelDbStorage) List(limit int) ([]db.KV, error) {
|
||||
func (l *Storage) List(limit int) ([]db.KV, error) {
|
||||
ret := []db.KV{}
|
||||
err := l.Iterate(func(key []byte, value []byte) (bool, error) {
|
||||
ret = append(ret, db.KV{K: db.Clone(key), V: db.Clone(value)})
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestLevelDbInterface(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
result := m.Run()
|
||||
for _, dir := range rmDirs {
|
||||
os.RemoveAll(dir)
|
||||
os.RemoveAll(dir) //nolint:errcheck,gosec
|
||||
}
|
||||
os.Exit(result)
|
||||
}
|
||||
|
||||
@@ -7,41 +7,36 @@ import (
|
||||
"github.com/iden3/go-merkletree/db"
|
||||
)
|
||||
|
||||
// MemoryStorage implements the db.Storage interface
|
||||
type MemoryStorage struct {
|
||||
// Storage implements the db.Storage interface
|
||||
type Storage struct {
|
||||
prefix []byte
|
||||
kv db.KvMap
|
||||
}
|
||||
|
||||
// MemoryStorageTx implements the db.Tx interface
|
||||
type MemoryStorageTx struct {
|
||||
s *MemoryStorage
|
||||
// StorageTx implements the db.Tx interface
|
||||
type StorageTx struct {
|
||||
s *Storage
|
||||
kv db.KvMap
|
||||
}
|
||||
|
||||
// NewMemoryStorage returns a new MemoryStorage
|
||||
func NewMemoryStorage() *MemoryStorage {
|
||||
// NewMemoryStorage returns a new Storage
|
||||
func NewMemoryStorage() *Storage {
|
||||
kvmap := make(db.KvMap)
|
||||
return &MemoryStorage{[]byte{}, kvmap}
|
||||
}
|
||||
|
||||
// Info implements the method Info of the interface db.Storage
|
||||
func (m *MemoryStorage) Info() string {
|
||||
return "in-memory"
|
||||
return &Storage{[]byte{}, kvmap}
|
||||
}
|
||||
|
||||
// WithPrefix implements the method WithPrefix of the interface db.Storage
|
||||
func (m *MemoryStorage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &MemoryStorage{db.Concat(m.prefix, prefix), m.kv}
|
||||
func (m *Storage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &Storage{db.Concat(m.prefix, prefix), m.kv}
|
||||
}
|
||||
|
||||
// NewTx implements the method NewTx of the interface db.Storage
|
||||
func (m *MemoryStorage) NewTx() (db.Tx, error) {
|
||||
return &MemoryStorageTx{m, make(db.KvMap)}, nil
|
||||
func (m *Storage) NewTx() (db.Tx, error) {
|
||||
return &StorageTx{m, make(db.KvMap)}, nil
|
||||
}
|
||||
|
||||
// Get retreives a value from a key in the db.Storage
|
||||
func (m *MemoryStorage) Get(key []byte) ([]byte, error) {
|
||||
func (m *Storage) Get(key []byte) ([]byte, error) {
|
||||
if v, ok := m.kv.Get(db.Concat(m.prefix, key[:])); ok {
|
||||
return v, nil
|
||||
}
|
||||
@@ -49,16 +44,19 @@ func (m *MemoryStorage) Get(key []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Iterate implements the method Iterate of the interface db.Storage
|
||||
func (m *MemoryStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
func (m *Storage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
kvs := make([]db.KV, 0)
|
||||
for _, v := range m.kv {
|
||||
if len(v.K) < len(m.prefix) || !bytes.Equal(v.K[:len(m.prefix)], m.prefix) {
|
||||
if len(v.K) < len(m.prefix) ||
|
||||
!bytes.Equal(v.K[:len(m.prefix)], m.prefix) {
|
||||
continue
|
||||
}
|
||||
localkey := v.K[len(m.prefix):]
|
||||
kvs = append(kvs, db.KV{K: localkey, V: v.V})
|
||||
}
|
||||
sort.SliceStable(kvs, func(i, j int) bool { return bytes.Compare(kvs[i].K, kvs[j].K) < 0 })
|
||||
sort.SliceStable(kvs, func(i, j int) bool {
|
||||
return bytes.Compare(kvs[i].K, kvs[j].K) < 0
|
||||
})
|
||||
|
||||
for _, kv := range kvs {
|
||||
if cont, err := f(kv.K, kv.V); err != nil {
|
||||
@@ -71,7 +69,7 @@ func (m *MemoryStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
}
|
||||
|
||||
// Get implements the method Get of the interface db.Tx
|
||||
func (tx *MemoryStorageTx) Get(key []byte) ([]byte, error) {
|
||||
func (tx *StorageTx) Get(key []byte) ([]byte, error) {
|
||||
if v, ok := tx.kv.Get(db.Concat(tx.s.prefix, key)); ok {
|
||||
return v, nil
|
||||
}
|
||||
@@ -83,13 +81,13 @@ func (tx *MemoryStorageTx) Get(key []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Put implements the method Put of the interface db.Tx
|
||||
func (tx *MemoryStorageTx) Put(k, v []byte) error {
|
||||
func (tx *StorageTx) Put(k, v []byte) error {
|
||||
tx.kv.Put(db.Concat(tx.s.prefix, k), v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit implements the method Commit of the interface db.Tx
|
||||
func (tx *MemoryStorageTx) Commit() error {
|
||||
func (tx *StorageTx) Commit() error {
|
||||
for _, v := range tx.kv {
|
||||
tx.s.kv.Put(v.K, v.V)
|
||||
}
|
||||
@@ -98,8 +96,8 @@ func (tx *MemoryStorageTx) Commit() error {
|
||||
}
|
||||
|
||||
// Add implements the method Add of the interface db.Tx
|
||||
func (tx *MemoryStorageTx) Add(atx db.Tx) error {
|
||||
mstx := atx.(*MemoryStorageTx)
|
||||
func (tx *StorageTx) Add(atx db.Tx) error {
|
||||
mstx := atx.(*StorageTx)
|
||||
for _, v := range mstx.kv {
|
||||
tx.kv.Put(v.K, v.V)
|
||||
}
|
||||
@@ -107,16 +105,16 @@ func (tx *MemoryStorageTx) Add(atx db.Tx) error {
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Tx
|
||||
func (tx *MemoryStorageTx) Close() {
|
||||
func (tx *StorageTx) Close() {
|
||||
tx.kv = nil
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Storage
|
||||
func (m *MemoryStorage) Close() {
|
||||
func (m *Storage) Close() {
|
||||
}
|
||||
|
||||
// List implements the method List of the interface db.Storage
|
||||
func (m *MemoryStorage) List(limit int) ([]db.KV, error) {
|
||||
func (m *Storage) List(limit int) ([]db.KV, error) {
|
||||
ret := []db.KV{}
|
||||
err := m.Iterate(func(key []byte, value []byte) (bool, error) {
|
||||
ret = append(ret, db.KV{K: db.Clone(key), V: db.Clone(value)})
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
package pebble
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/cockroachdb/pebble"
|
||||
"github.com/iden3/go-merkletree/db"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PebbleStorage implements the db.Storage interface
|
||||
type PebbleStorage struct {
|
||||
// Storage implements the db.Storage interface
|
||||
type Storage struct {
|
||||
pdb *pebble.DB
|
||||
prefix []byte
|
||||
}
|
||||
|
||||
// PebbleStorageTx implements the db.Tx interface
|
||||
type PebbleStorageTx struct {
|
||||
*PebbleStorage
|
||||
// StorageTx implements the db.Tx interface
|
||||
type StorageTx struct {
|
||||
*Storage
|
||||
batch *pebble.Batch
|
||||
}
|
||||
|
||||
// NewPebbleStorage returns a new PebbleStorage
|
||||
func NewPebbleStorage(path string, errorIfMissing bool) (*PebbleStorage, error) {
|
||||
// NewPebbleStorage returns a new Storage
|
||||
func NewPebbleStorage(path string, errorIfMissing bool) (*Storage, error) {
|
||||
o := &pebble.Options{
|
||||
ErrorIfNotExists: errorIfMissing,
|
||||
}
|
||||
@@ -29,59 +27,33 @@ func NewPebbleStorage(path string, errorIfMissing bool) (*PebbleStorage, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PebbleStorage{rdb, []byte{}}, nil
|
||||
}
|
||||
|
||||
type storageInfo struct {
|
||||
KeyCount int
|
||||
ClaimCount int
|
||||
}
|
||||
|
||||
// Info implements the method Info of the interface db.Storage
|
||||
func (p *PebbleStorage) Info() string {
|
||||
keycount := 0
|
||||
claimcount := 0
|
||||
err := p.Iterate(func(key []byte, value []byte) (bool, error) {
|
||||
if value[0] == byte(1) {
|
||||
claimcount++
|
||||
}
|
||||
|
||||
keycount++
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
json, _ := json.MarshalIndent(
|
||||
storageInfo{
|
||||
KeyCount: keycount,
|
||||
ClaimCount: claimcount,
|
||||
},
|
||||
"", " ",
|
||||
)
|
||||
return string(json)
|
||||
return &Storage{rdb, []byte{}}, nil
|
||||
}
|
||||
|
||||
// WithPrefix implements the method WithPrefix of the interface db.Storage
|
||||
func (p *PebbleStorage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &PebbleStorage{p.pdb, db.Concat(p.prefix, prefix)}
|
||||
func (p *Storage) WithPrefix(prefix []byte) db.Storage {
|
||||
return &Storage{p.pdb, db.Concat(p.prefix, prefix)}
|
||||
}
|
||||
|
||||
// NewTx implements the method NewTx of the interface db.Storage
|
||||
func (p *PebbleStorage) NewTx() (db.Tx, error) {
|
||||
return &PebbleStorageTx{p, p.pdb.NewIndexedBatch()}, nil
|
||||
func (p *Storage) NewTx() (db.Tx, error) {
|
||||
return &StorageTx{p, p.pdb.NewIndexedBatch()}, nil
|
||||
}
|
||||
|
||||
// Get retreives a value from a key in the db.Storage
|
||||
func (p *PebbleStorage) Get(key []byte) ([]byte, error) {
|
||||
func (p *Storage) Get(key []byte) ([]byte, error) {
|
||||
v, closer, err := p.pdb.Get(db.Concat(p.prefix, key[:]))
|
||||
if err == pebble.ErrNotFound {
|
||||
return nil, db.ErrNotFound
|
||||
}
|
||||
closer.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = closer.Close()
|
||||
return v, err
|
||||
}
|
||||
|
||||
//nolint:lll
|
||||
// https://github.com/cockroachdb/pebble/pull/923/files#diff-c2ade2f386c41794d5ebc57ee49b57a5fca8082e03255e5bff13977cbc061287R39
|
||||
func keyUpperBound(b []byte) []byte {
|
||||
end := make([]byte, len(b))
|
||||
@@ -102,7 +74,7 @@ func prefixIterOptions(prefix []byte) *pebble.IterOptions {
|
||||
}
|
||||
|
||||
// Iterate implements the method Iterate of the interface db.Storage
|
||||
func (p *PebbleStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
func (p *Storage) Iterate(f func([]byte, []byte) (bool, error)) (err error) {
|
||||
// NewIter already provides a point-in-time view of the current DB
|
||||
// state, but if is used for long term (is not the case), should use an
|
||||
// iterator over an snapshot:
|
||||
@@ -110,7 +82,13 @@ func (p *PebbleStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
// defer snapshot.Close()
|
||||
// iter := snapshot.NewIter(nil)
|
||||
iter := p.pdb.NewIter(prefixIterOptions(p.prefix))
|
||||
defer iter.Close()
|
||||
defer func() {
|
||||
err1 := iter.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = err1
|
||||
}()
|
||||
|
||||
for iter.First(); iter.Valid(); iter.Next() {
|
||||
localKey := iter.Key()[len(p.prefix):]
|
||||
@@ -124,7 +102,7 @@ func (p *PebbleStorage) Iterate(f func([]byte, []byte) (bool, error)) error {
|
||||
}
|
||||
|
||||
// Get retreives a value from a key in the interface db.Tx
|
||||
func (tx *PebbleStorageTx) Get(key []byte) ([]byte, error) {
|
||||
func (tx *StorageTx) Get(key []byte) ([]byte, error) {
|
||||
var err error
|
||||
|
||||
fullkey := db.Concat(tx.prefix, key)
|
||||
@@ -133,34 +111,36 @@ func (tx *PebbleStorageTx) Get(key []byte) ([]byte, error) {
|
||||
if err == pebble.ErrNotFound {
|
||||
return nil, db.ErrNotFound
|
||||
}
|
||||
closer.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = closer.Close()
|
||||
return v, err
|
||||
}
|
||||
|
||||
// Put saves a key:value into the db.Storage
|
||||
func (tx *PebbleStorageTx) Put(k, v []byte) error {
|
||||
func (tx *StorageTx) Put(k, v []byte) error {
|
||||
return tx.batch.Set(db.Concat(tx.prefix, k[:]), v, nil)
|
||||
}
|
||||
|
||||
// Add implements the method Add of the interface db.Tx
|
||||
func (tx *PebbleStorageTx) Add(atx db.Tx) error {
|
||||
patx := atx.(*PebbleStorageTx)
|
||||
func (tx *StorageTx) Add(atx db.Tx) error {
|
||||
patx := atx.(*StorageTx)
|
||||
return tx.batch.Apply(patx.batch, nil)
|
||||
}
|
||||
|
||||
// Commit implements the method Commit of the interface db.Tx
|
||||
func (tx *PebbleStorageTx) Commit() error {
|
||||
func (tx *StorageTx) Commit() error {
|
||||
return tx.batch.Commit(nil)
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Tx
|
||||
func (tx *PebbleStorageTx) Close() {
|
||||
func (tx *StorageTx) Close() {
|
||||
_ = tx.batch.Close()
|
||||
}
|
||||
|
||||
// Close implements the method Close of the interface db.Storage
|
||||
func (p *PebbleStorage) Close() {
|
||||
func (p *Storage) Close() {
|
||||
if err := p.pdb.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -168,12 +148,12 @@ func (p *PebbleStorage) Close() {
|
||||
}
|
||||
|
||||
// Pebble is an extra method that returns the *pebble.DB
|
||||
func (p *PebbleStorage) Pebble() *pebble.DB {
|
||||
func (p *Storage) Pebble() *pebble.DB {
|
||||
return p.pdb
|
||||
}
|
||||
|
||||
// List implements the method List of the interface db.Storage
|
||||
func (p *PebbleStorage) List(limit int) ([]db.KV, error) {
|
||||
func (p *Storage) List(limit int) ([]db.KV, error) {
|
||||
ret := []db.KV{}
|
||||
err := p.Iterate(func(key []byte, value []byte) (bool, error) {
|
||||
ret = append(ret, db.KV{K: db.Clone(key), V: db.Clone(value)})
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestPebbleInterface(t *testing.T) {
|
||||
func TestMain(m *testing.M) {
|
||||
result := m.Run()
|
||||
for _, dir := range rmDirs {
|
||||
os.RemoveAll(dir)
|
||||
os.RemoveAll(dir) //nolint:errcheck,gosec
|
||||
}
|
||||
os.Exit(result)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//nolint:gomnd
|
||||
//nolint:gomnd,golint
|
||||
package test
|
||||
|
||||
import (
|
||||
|
||||
3
go.mod
3
go.mod
@@ -4,8 +4,7 @@ go 1.14
|
||||
|
||||
require (
|
||||
github.com/cockroachdb/pebble v0.0.0-20200814004841-77c18adb0ee3
|
||||
github.com/iden3/go-iden3-core v0.0.8
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20200819064831-09d161e9f670
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20201218111145-a2015adb2f1b
|
||||
github.com/sirupsen/logrus v1.5.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
|
||||
|
||||
9
go.sum
9
go.sum
@@ -132,11 +132,11 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/iden3/go-circom-prover-verifier v0.0.1/go.mod h1:1FkpX4nUXxYcY2fpzqd27wHHEnWeo1v1nwDnz2TgBRo=
|
||||
github.com/iden3/go-circom-witnesscalc v0.0.1/go.mod h1:xjT1BlFZDBioHOlbD75SmZZLC1d1AfOycqbSa/1QRJU=
|
||||
github.com/iden3/go-iden3-core v0.0.8 h1:PLw7iCiX7Pw1dqBkR+JaLQWqB5RKd+vgu25UBdvFXGQ=
|
||||
github.com/iden3/go-iden3-core v0.0.8/go.mod h1:URNjIhMql6sEbWubIGrjJdw5wHCE1Pk1XghxjBOtA3s=
|
||||
github.com/iden3/go-iden3-crypto v0.0.5/go.mod h1:XKw1oDwYn2CIxKOtr7m/mL5jMn4mLOxAxtZBRxQBev8=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20200819064831-09d161e9f670 h1:gNBFu/WnRfNn+xywE04fgCWSHlb6wr0nIIll9i4R2fc=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20200819064831-09d161e9f670/go.mod h1:oBgthFLboAWi9feaBUFy7OxEcyn9vA1khHSL/WwWFyg=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20201203095229-821a601d2002 h1:f2twuL20aAqq1TlSdfQgL5r68hKjB/ioQdSctREQLuY=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20201203095229-821a601d2002/go.mod h1:oBgthFLboAWi9feaBUFy7OxEcyn9vA1khHSL/WwWFyg=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20201218111145-a2015adb2f1b h1:U2EsJRdonl0lhWvNiDscXZRDqSsPLIJHZg5DmU10IDo=
|
||||
github.com/iden3/go-iden3-crypto v0.0.6-0.20201218111145-a2015adb2f1b/go.mod h1:oBgthFLboAWi9feaBUFy7OxEcyn9vA1khHSL/WwWFyg=
|
||||
github.com/iden3/go-wasm3 v0.0.1/go.mod h1:j+TcAB94Dfrjlu5kJt83h2OqAU+oyNUTwNZnQyII1sI=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||
@@ -255,7 +255,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
|
||||
126
merkletree.go
126
merkletree.go
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/iden3/go-iden3-core/common"
|
||||
cryptoUtils "github.com/iden3/go-iden3-crypto/utils"
|
||||
"github.com/iden3/go-merkletree/db"
|
||||
)
|
||||
@@ -54,7 +53,8 @@ var (
|
||||
|
||||
dbKeyRootNode = []byte("currentroot")
|
||||
// HashZero is used at Empty nodes
|
||||
HashZero = Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
HashZero = Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
)
|
||||
|
||||
// Hash is the generic type stored in the MerkleTree
|
||||
@@ -87,16 +87,16 @@ func (h Hash) Hex() string {
|
||||
// alternatively equivalent, but with too extra steps:
|
||||
// bRaw := h.BigInt().Bytes()
|
||||
// b := [32]byte{}
|
||||
// copy(b[:], common.SwapEndianness(bRaw[:]))
|
||||
// copy(b[:], SwapEndianness(bRaw[:]))
|
||||
// return hex.EncodeToString(b[:])
|
||||
}
|
||||
|
||||
// BigInt returns the *big.Int representation of the *Hash
|
||||
func (h *Hash) BigInt() *big.Int {
|
||||
if new(big.Int).SetBytes(common.SwapEndianness(h[:])) == nil {
|
||||
if new(big.Int).SetBytes(SwapEndianness(h[:])) == nil {
|
||||
return big.NewInt(0)
|
||||
}
|
||||
return new(big.Int).SetBytes(common.SwapEndianness(h[:]))
|
||||
return new(big.Int).SetBytes(SwapEndianness(h[:]))
|
||||
}
|
||||
|
||||
// Bytes returns the []byte representation of the *Hash, which always is 32
|
||||
@@ -104,7 +104,7 @@ func (h *Hash) BigInt() *big.Int {
|
||||
func (h *Hash) Bytes() []byte {
|
||||
bi := new(big.Int).SetBytes(h[:]).Bytes()
|
||||
b := [32]byte{}
|
||||
copy(b[:], common.SwapEndianness(bi[:]))
|
||||
copy(b[:], SwapEndianness(bi[:]))
|
||||
return b[:]
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func NewBigIntFromHashBytes(b []byte) (*big.Int, error) {
|
||||
// NewHashFromBigInt returns a *Hash representation of the given *big.Int
|
||||
func NewHashFromBigInt(b *big.Int) *Hash {
|
||||
r := &Hash{}
|
||||
copy(r[:], common.SwapEndianness(b.Bytes()))
|
||||
copy(r[:], SwapEndianness(b.Bytes()))
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func NewHashFromBytes(b []byte) (*Hash, error) {
|
||||
return nil, fmt.Errorf("Expected 32 bytes, found %d bytes", len(b))
|
||||
}
|
||||
var h Hash
|
||||
copy(h[:], common.SwapEndianness(b))
|
||||
copy(h[:], SwapEndianness(b))
|
||||
return &h, nil
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ func NewHashFromHex(h string) (*Hash, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewHashFromBytes(common.SwapEndianness(b[:]))
|
||||
return NewHashFromBytes(SwapEndianness(b[:]))
|
||||
}
|
||||
|
||||
// NewHashFromString returns a *Hash representation of the given decimal string
|
||||
@@ -281,7 +281,8 @@ func (mt *MerkleTree) Add(k, v *big.Int) error {
|
||||
}
|
||||
|
||||
// AddAndGetCircomProof does an Add, and returns a CircomProcessorProof
|
||||
func (mt *MerkleTree) AddAndGetCircomProof(k, v *big.Int) (*CircomProcessorProof, error) {
|
||||
func (mt *MerkleTree) AddAndGetCircomProof(k,
|
||||
v *big.Int) (*CircomProcessorProof, error) {
|
||||
var cp CircomProcessorProof
|
||||
cp.Fnc = 2
|
||||
cp.OldRoot = mt.rootKey
|
||||
@@ -315,8 +316,8 @@ func (mt *MerkleTree) AddAndGetCircomProof(k, v *big.Int) (*CircomProcessorProof
|
||||
// pushLeaf recursively pushes an existing oldLeaf down until its path diverges
|
||||
// from newLeaf, at which point both leafs are stored, all while updating the
|
||||
// path.
|
||||
func (mt *MerkleTree) pushLeaf(tx db.Tx, newLeaf *Node, oldLeaf *Node,
|
||||
lvl int, pathNewLeaf []bool, pathOldLeaf []bool) (*Hash, error) {
|
||||
func (mt *MerkleTree) pushLeaf(tx db.Tx, newLeaf *Node, oldLeaf *Node, lvl int,
|
||||
pathNewLeaf []bool, pathOldLeaf []bool) (*Hash, error) {
|
||||
if lvl > mt.maxLevels-2 {
|
||||
return nil, ErrReachedMaxLevel
|
||||
}
|
||||
@@ -326,13 +327,13 @@ func (mt *MerkleTree) pushLeaf(tx db.Tx, newLeaf *Node, oldLeaf *Node,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pathNewLeaf[lvl] {
|
||||
newNodeMiddle = NewNodeMiddle(&HashZero, nextKey) // go right
|
||||
} else {
|
||||
newNodeMiddle = NewNodeMiddle(nextKey, &HashZero) // go left
|
||||
if pathNewLeaf[lvl] { // go right
|
||||
newNodeMiddle = NewNodeMiddle(&HashZero, nextKey)
|
||||
} else { // go left
|
||||
newNodeMiddle = NewNodeMiddle(nextKey, &HashZero)
|
||||
}
|
||||
return mt.addNode(tx, newNodeMiddle)
|
||||
} else {
|
||||
}
|
||||
oldLeafKey, err := oldLeaf.Key()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -347,13 +348,13 @@ func (mt *MerkleTree) pushLeaf(tx db.Tx, newLeaf *Node, oldLeaf *Node,
|
||||
} else {
|
||||
newNodeMiddle = NewNodeMiddle(newLeafKey, oldLeafKey)
|
||||
}
|
||||
// We can add newLeaf now. We don't need to add oldLeaf because it's already in the tree.
|
||||
// We can add newLeaf now. We don't need to add oldLeaf because it's
|
||||
// already in the tree.
|
||||
_, err = mt.addNode(tx, newLeaf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mt.addNode(tx, newNodeMiddle)
|
||||
}
|
||||
}
|
||||
|
||||
// addLeaf recursively adds a newLeaf in the MT while updating the path.
|
||||
@@ -374,23 +375,25 @@ func (mt *MerkleTree) addLeaf(tx db.Tx, newLeaf *Node, key *Hash,
|
||||
return mt.addNode(tx, newLeaf)
|
||||
case NodeTypeLeaf:
|
||||
nKey := n.Entry[0]
|
||||
// Check if leaf node found contains the leaf node we are trying to add
|
||||
// Check if leaf node found contains the leaf node we are
|
||||
// trying to add
|
||||
newLeafKey := newLeaf.Entry[0]
|
||||
if bytes.Equal(nKey[:], newLeafKey[:]) {
|
||||
return nil, ErrEntryIndexAlreadyExists
|
||||
}
|
||||
pathOldLeaf := getPath(mt.maxLevels, nKey[:])
|
||||
// We need to push newLeaf down until its path diverges from n's path
|
||||
// We need to push newLeaf down until its path diverges from
|
||||
// n's path
|
||||
return mt.pushLeaf(tx, newLeaf, n, lvl, path, pathOldLeaf)
|
||||
case NodeTypeMiddle:
|
||||
// We need to go deeper, continue traversing the tree, left or
|
||||
// right depending on path
|
||||
var newNodeMiddle *Node
|
||||
if path[lvl] {
|
||||
nextKey, err = mt.addLeaf(tx, newLeaf, n.ChildR, lvl+1, path) // go right
|
||||
if path[lvl] { // go right
|
||||
nextKey, err = mt.addLeaf(tx, newLeaf, n.ChildR, lvl+1, path)
|
||||
newNodeMiddle = NewNodeMiddle(n.ChildL, nextKey)
|
||||
} else {
|
||||
nextKey, err = mt.addLeaf(tx, newLeaf, n.ChildL, lvl+1, path) // go left
|
||||
} else { // go left
|
||||
nextKey, err = mt.addLeaf(tx, newLeaf, n.ChildL, lvl+1, path)
|
||||
newNodeMiddle = NewNodeMiddle(nextKey, n.ChildR)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -468,9 +471,8 @@ func (mt *MerkleTree) Get(k *big.Int) (*big.Int, *big.Int, []*Hash, error) {
|
||||
case NodeTypeLeaf:
|
||||
if bytes.Equal(kHash[:], n.Entry[0][:]) {
|
||||
return n.Entry[0].BigInt(), n.Entry[1].BigInt(), siblings, nil
|
||||
} else {
|
||||
return n.Entry[0].BigInt(), n.Entry[1].BigInt(), siblings, ErrKeyNotFound
|
||||
}
|
||||
return n.Entry[0].BigInt(), n.Entry[1].BigInt(), siblings, ErrKeyNotFound
|
||||
case NodeTypeMiddle:
|
||||
if path[i] {
|
||||
nextKey = n.ChildR
|
||||
@@ -541,7 +543,8 @@ func (mt *MerkleTree) Update(k, v *big.Int) (*CircomProcessorProof, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newRootKey, err := mt.recalculatePathUntilRoot(tx, path, newNodeLeaf, siblings)
|
||||
newRootKey, err :=
|
||||
mt.recalculatePathUntilRoot(tx, path, newNodeLeaf, siblings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -555,9 +558,8 @@ func (mt *MerkleTree) Update(k, v *big.Int) (*CircomProcessorProof, error) {
|
||||
return nil, err
|
||||
}
|
||||
return &cp, nil
|
||||
} else {
|
||||
return nil, ErrKeyNotFound
|
||||
}
|
||||
return nil, ErrKeyNotFound
|
||||
case NodeTypeMiddle:
|
||||
if path[i] {
|
||||
nextKey = n.ChildR
|
||||
@@ -619,9 +621,8 @@ func (mt *MerkleTree) Delete(k *big.Int) error {
|
||||
// remove and go up with the sibling
|
||||
err = mt.rmAndUpload(tx, path, kHash, siblings)
|
||||
return err
|
||||
} else {
|
||||
return ErrKeyNotFound
|
||||
}
|
||||
return ErrKeyNotFound
|
||||
case NodeTypeMiddle:
|
||||
if path[i] {
|
||||
nextKey = n.ChildR
|
||||
@@ -638,7 +639,8 @@ func (mt *MerkleTree) Delete(k *big.Int) error {
|
||||
return ErrKeyNotFound
|
||||
}
|
||||
|
||||
// rmAndUpload removes the key, and goes up until the root updating all the nodes with the new values.
|
||||
// rmAndUpload removes the key, and goes up until the root updating all the
|
||||
// nodes with the new values.
|
||||
func (mt *MerkleTree) rmAndUpload(tx db.Tx, path []bool, kHash *Hash, siblings []*Hash) error {
|
||||
if len(siblings) == 0 {
|
||||
mt.rootKey = &HashZero
|
||||
@@ -671,7 +673,8 @@ func (mt *MerkleTree) rmAndUpload(tx db.Tx, path []bool, kHash *Hash, siblings [
|
||||
return err
|
||||
}
|
||||
// go up until the root
|
||||
newRootKey, err := mt.recalculatePathUntilRoot(tx, path, newNode, siblings[:i])
|
||||
newRootKey, err := mt.recalculatePathUntilRoot(tx, path, newNode,
|
||||
siblings[:i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -682,7 +685,8 @@ func (mt *MerkleTree) rmAndUpload(tx db.Tx, path []bool, kHash *Hash, siblings [
|
||||
}
|
||||
break
|
||||
}
|
||||
// if i==0 (root position), stop and store the sibling of the deleted leaf as root
|
||||
// if i==0 (root position), stop and store the sibling of the
|
||||
// deleted leaf as root
|
||||
if i == 0 {
|
||||
mt.rootKey = toUpload
|
||||
err := mt.dbInsert(tx, dbKeyRootNode, DBEntryTypeRoot, mt.rootKey[:])
|
||||
@@ -700,7 +704,8 @@ func (mt *MerkleTree) rmAndUpload(tx db.Tx, path []bool, kHash *Hash, siblings [
|
||||
}
|
||||
|
||||
// recalculatePathUntilRoot recalculates the nodes until the Root
|
||||
func (mt *MerkleTree) recalculatePathUntilRoot(tx db.Tx, path []bool, node *Node, siblings []*Hash) (*Hash, error) {
|
||||
func (mt *MerkleTree) recalculatePathUntilRoot(tx db.Tx, path []bool, node *Node,
|
||||
siblings []*Hash) (*Hash, error) {
|
||||
for i := len(siblings) - 1; i >= 0; i-- {
|
||||
nodeKey, err := node.Key()
|
||||
if err != nil {
|
||||
@@ -746,7 +751,7 @@ func (mt *MerkleTree) GetNode(key *Hash) (*Node, error) {
|
||||
func getPath(numLevels int, k []byte) []bool {
|
||||
path := make([]bool, numLevels)
|
||||
for n := 0; n < numLevels; n++ {
|
||||
path[n] = common.TestBit(k[:], uint(n))
|
||||
path[n] = TestBit(k[:], uint(n))
|
||||
}
|
||||
return path
|
||||
}
|
||||
@@ -757,9 +762,11 @@ type NodeAux struct {
|
||||
Value *Hash
|
||||
}
|
||||
|
||||
// Proof defines the required elements for a MT proof of existence or non-existence.
|
||||
// Proof defines the required elements for a MT proof of existence or
|
||||
// non-existence.
|
||||
type Proof struct {
|
||||
// existence indicates wether this is a proof of existence or non-existence.
|
||||
// existence indicates wether this is a proof of existence or
|
||||
// non-existence.
|
||||
Existence bool
|
||||
// depth indicates how deep in the tree the proof goes.
|
||||
depth uint
|
||||
@@ -784,7 +791,7 @@ func NewProofFromBytes(bs []byte) (*Proof, error) {
|
||||
siblingBytes := bs[ElemBytesLen:]
|
||||
sibIdx := 0
|
||||
for i := uint(0); i < p.depth; i++ {
|
||||
if common.TestBitBigEndian(p.notempties[:], i) {
|
||||
if TestBitBigEndian(p.notempties[:], i) {
|
||||
if len(siblingBytes) < (sibIdx+1)*ElemBytesLen {
|
||||
return nil, ErrInvalidProofBytes
|
||||
}
|
||||
@@ -837,7 +844,7 @@ func SiblingsFromProof(proof *Proof) []*Hash {
|
||||
sibIdx := 0
|
||||
var siblings []*Hash
|
||||
for lvl := 0; lvl < int(proof.depth); lvl++ {
|
||||
if common.TestBitBigEndian(proof.notempties[:], uint(lvl)) {
|
||||
if TestBitBigEndian(proof.notempties[:], uint(lvl)) {
|
||||
siblings = append(siblings, proof.Siblings[sibIdx])
|
||||
sibIdx++
|
||||
} else {
|
||||
@@ -872,7 +879,8 @@ type CircomProcessorProof struct {
|
||||
NewKey *Hash `json:"newKey"`
|
||||
NewValue *Hash `json:"newValue"`
|
||||
IsOld0 bool `json:"isOld0"`
|
||||
Fnc int `json:"fnc"` // 0: NOP, 1: Update, 2: Insert, 3: Delete
|
||||
// 0: NOP, 1: Update, 2: Insert, 3: Delete
|
||||
Fnc int `json:"fnc"`
|
||||
}
|
||||
|
||||
// String returns a human readable string representation of the
|
||||
@@ -912,7 +920,8 @@ type CircomVerifierProof struct {
|
||||
// GenerateCircomVerifierProof returns the CircomVerifierProof for a certain
|
||||
// key in the MerkleTree. If the rootKey is nil, the current merkletree root
|
||||
// is used.
|
||||
func (mt *MerkleTree) GenerateCircomVerifierProof(k *big.Int, rootKey *Hash) (*CircomVerifierProof, error) {
|
||||
func (mt *MerkleTree) GenerateCircomVerifierProof(k *big.Int,
|
||||
rootKey *Hash) (*CircomVerifierProof, error) {
|
||||
if rootKey == nil {
|
||||
rootKey = mt.Root()
|
||||
}
|
||||
@@ -939,7 +948,8 @@ func (mt *MerkleTree) GenerateCircomVerifierProof(k *big.Int, rootKey *Hash) (*C
|
||||
// GenerateProof generates the proof of existence (or non-existence) of an
|
||||
// Entry's hash Index for a Merkle Tree given the root.
|
||||
// If the rootKey is nil, the current merkletree root is used
|
||||
func (mt *MerkleTree) GenerateProof(k *big.Int, rootKey *Hash) (*Proof, *big.Int, error) {
|
||||
func (mt *MerkleTree) GenerateProof(k *big.Int, rootKey *Hash) (*Proof,
|
||||
*big.Int, error) {
|
||||
p := &Proof{}
|
||||
var siblingKey *Hash
|
||||
|
||||
@@ -961,11 +971,10 @@ func (mt *MerkleTree) GenerateProof(k *big.Int, rootKey *Hash) (*Proof, *big.Int
|
||||
if bytes.Equal(kHash[:], n.Entry[0][:]) {
|
||||
p.Existence = true
|
||||
return p, n.Entry[1].BigInt(), nil
|
||||
} else {
|
||||
}
|
||||
// We found a leaf whose entry didn't match hIndex
|
||||
p.NodeAux = &NodeAux{Key: n.Entry[0], Value: n.Entry[1]}
|
||||
return p, n.Entry[1].BigInt(), nil
|
||||
}
|
||||
case NodeTypeMiddle:
|
||||
if path[p.depth] {
|
||||
nextKey = n.ChildR
|
||||
@@ -978,7 +987,7 @@ func (mt *MerkleTree) GenerateProof(k *big.Int, rootKey *Hash) (*Proof, *big.Int
|
||||
return nil, nil, ErrInvalidNodeFound
|
||||
}
|
||||
if !bytes.Equal(siblingKey[:], HashZero[:]) {
|
||||
common.SetBitBigEndian(p.notempties[:], uint(p.depth))
|
||||
SetBitBigEndian(p.notempties[:], uint(p.depth))
|
||||
p.Siblings = append(p.Siblings, siblingKey)
|
||||
}
|
||||
}
|
||||
@@ -1013,7 +1022,8 @@ func RootFromProof(proof *Proof, k, v *big.Int) (*Hash, error) {
|
||||
midKey = &HashZero
|
||||
} else {
|
||||
if bytes.Equal(kHash[:], proof.NodeAux.Key[:]) {
|
||||
return nil, fmt.Errorf("Non-existence proof being checked against hIndex equal to nodeAux")
|
||||
return nil,
|
||||
fmt.Errorf("Non-existence proof being checked against hIndex equal to nodeAux")
|
||||
}
|
||||
midKey, err = LeafKey(proof.NodeAux.Key, proof.NodeAux.Value)
|
||||
if err != nil {
|
||||
@@ -1024,7 +1034,7 @@ func RootFromProof(proof *Proof, k, v *big.Int) (*Hash, error) {
|
||||
path := getPath(int(proof.depth), kHash[:])
|
||||
var siblingKey *Hash
|
||||
for lvl := int(proof.depth) - 1; lvl >= 0; lvl-- {
|
||||
if common.TestBitBigEndian(proof.notempties[:], uint(lvl)) {
|
||||
if TestBitBigEndian(proof.notempties[:], uint(lvl)) {
|
||||
siblingKey = proof.Siblings[sibIdx]
|
||||
sibIdx--
|
||||
} else {
|
||||
@@ -1071,10 +1081,10 @@ func (mt *MerkleTree) walk(key *Hash, f func(*Node)) error {
|
||||
}
|
||||
|
||||
// Walk iterates over all the branches of a MerkleTree with the given rootKey
|
||||
// if rootKey is nil, it will get the current RootKey of the current state of the MerkleTree.
|
||||
// For each node, it calls the f function given in the parameters.
|
||||
// See some examples of the Walk function usage in the merkletree.go and
|
||||
// merkletree_test.go
|
||||
// if rootKey is nil, it will get the current RootKey of the current state of
|
||||
// the MerkleTree. For each node, it calls the f function given in the
|
||||
// parameters. See some examples of the Walk function usage in the
|
||||
// merkletree.go and merkletree_test.go
|
||||
func (mt *MerkleTree) Walk(rootKey *Hash, f func(*Node)) error {
|
||||
if rootKey == nil {
|
||||
rootKey = mt.Root()
|
||||
@@ -1083,8 +1093,8 @@ func (mt *MerkleTree) Walk(rootKey *Hash, f func(*Node)) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// GraphViz uses Walk function to generate a string GraphViz representation of the
|
||||
// tree and writes it to w
|
||||
// GraphViz uses Walk function to generate a string GraphViz representation of
|
||||
// the tree and writes it to w
|
||||
func (mt *MerkleTree) GraphViz(w io.Writer, rootKey *Hash) error {
|
||||
fmt.Fprintf(w, `digraph hierarchy {
|
||||
node [fontname=Monospace,fontsize=10,shape=box]
|
||||
@@ -1128,12 +1138,14 @@ func (mt *MerkleTree) PrintGraphViz(rootKey *Hash) error {
|
||||
rootKey = mt.Root()
|
||||
}
|
||||
w := bytes.NewBufferString("")
|
||||
fmt.Fprintf(w, "--------\nGraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n")
|
||||
fmt.Fprintf(w,
|
||||
"--------\nGraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n")
|
||||
err := mt.GraphViz(w, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "End of GraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n--------\n")
|
||||
fmt.Fprintf(w,
|
||||
"End of GraphViz of the MerkleTree with RootKey "+rootKey.BigInt().String()+"\n--------\n")
|
||||
|
||||
fmt.Println(w)
|
||||
return nil
|
||||
|
||||
@@ -43,10 +43,10 @@ func TestHashParsers(t *testing.T) {
|
||||
h8l := NewHashFromBigInt(big.NewInt(12345678))
|
||||
assert.Equal(t, "12345678...", h8l.String())
|
||||
|
||||
b, ok := new(big.Int).SetString("4932297968297298434239270129193057052722409868268166443802652458940273154854", 10)
|
||||
b, ok := new(big.Int).SetString("4932297968297298434239270129193057052722409868268166443802652458940273154854", 10) //nolint:lll
|
||||
assert.True(t, ok)
|
||||
h := NewHashFromBigInt(b)
|
||||
assert.Equal(t, "4932297968297298434239270129193057052722409868268166443802652458940273154854", h.BigInt().String())
|
||||
assert.Equal(t, "4932297968297298434239270129193057052722409868268166443802652458940273154854", h.BigInt().String()) //nolint:lll
|
||||
assert.Equal(t, "49322979...", h.String())
|
||||
assert.Equal(t, "265baaf161e875c372d08e50f52abddc01d32efc93e90290bb8b3d9ceb94e70a", h.Hex())
|
||||
|
||||
@@ -98,15 +98,15 @@ func TestNewTree(t *testing.T) {
|
||||
// test vectors generated using https://github.com/iden3/circomlib smt.js
|
||||
err = mt.Add(big.NewInt(1), big.NewInt(2))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "6449712043256457369579901840927028403950625973089336675272087704159094984964", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "6449712043256457369579901840927028403950625973089336675272087704159094984964", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Add(big.NewInt(33), big.NewInt(44))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Add(big.NewInt(1234), big.NewInt(9876))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "12841932325181810040554102151615400973767747666110051836366805309524360490677", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "12841932325181810040554102151615400973767747666110051836366805309524360490677", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
dbRoot, err := mt.dbGetRoot()
|
||||
require.Nil(t, err)
|
||||
@@ -142,7 +142,7 @@ func TestAddDifferentOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.Equal(t, mt1.Root().Hex(), mt2.Root().Hex())
|
||||
assert.Equal(t, "268e25964aa9d6ba42d66ae9eb44b5528540acb19a3644d1367d8c6f7cb23006", mt1.Root().Hex())
|
||||
assert.Equal(t, "268e25964aa9d6ba42d66ae9eb44b5528540acb19a3644d1367d8c6f7cb23006", mt1.Root().Hex()) //nolint:lll
|
||||
}
|
||||
|
||||
func TestAddRepeatedIndex(t *testing.T) {
|
||||
@@ -299,12 +299,24 @@ func TestSiblingsFromProof(t *testing.T) {
|
||||
|
||||
siblings := SiblingsFromProof(proof)
|
||||
assert.Equal(t, 6, len(siblings))
|
||||
assert.Equal(t, "5b478bdd58595ead03ebf494a74014cbb576ba0d9456aa0916885b9eefae592f", siblings[0].Hex())
|
||||
assert.Equal(t, "c1e8ab120a4e475ea1bf00633228bfb9d248f7ddec2aa6367f98d0defb9fb22e", siblings[1].Hex())
|
||||
assert.Equal(t, "f4dafd8ac2b9165adc3f6d125af67d5a4d8a7a263dcc90a373d0338929e16e0c", siblings[2].Hex())
|
||||
assert.Equal(t, "a94aa346bd85f96aba2e85b67920e44fe6ed767b0e13bea602784e0b8b897515", siblings[3].Hex())
|
||||
assert.Equal(t, "54791d7514030ded79301dbf221f5bf186facbc5800912411852fdc101b7151d", siblings[4].Hex())
|
||||
assert.Equal(t, "435d28bc0511f8feb93b5f1649a049b460947702ce0baaefcf596175370fe01e", siblings[5].Hex())
|
||||
assert.Equal(t,
|
||||
"5b478bdd58595ead03ebf494a74014cbb576ba0d9456aa0916885b9eefae592f",
|
||||
siblings[0].Hex())
|
||||
assert.Equal(t,
|
||||
"c1e8ab120a4e475ea1bf00633228bfb9d248f7ddec2aa6367f98d0defb9fb22e",
|
||||
siblings[1].Hex())
|
||||
assert.Equal(t,
|
||||
"f4dafd8ac2b9165adc3f6d125af67d5a4d8a7a263dcc90a373d0338929e16e0c",
|
||||
siblings[2].Hex())
|
||||
assert.Equal(t,
|
||||
"a94aa346bd85f96aba2e85b67920e44fe6ed767b0e13bea602784e0b8b897515",
|
||||
siblings[3].Hex())
|
||||
assert.Equal(t,
|
||||
"54791d7514030ded79301dbf221f5bf186facbc5800912411852fdc101b7151d",
|
||||
siblings[4].Hex())
|
||||
assert.Equal(t,
|
||||
"435d28bc0511f8feb93b5f1649a049b460947702ce0baaefcf596175370fe01e",
|
||||
siblings[5].Hex())
|
||||
}
|
||||
|
||||
func TestVerifyProofCases(t *testing.T) {
|
||||
@@ -318,14 +330,13 @@ func TestVerifyProofCases(t *testing.T) {
|
||||
}
|
||||
|
||||
// Existence proof
|
||||
|
||||
proof, _, err := mt.GenerateProof(big.NewInt(4), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, proof.Existence, true)
|
||||
assert.True(t, VerifyProof(mt.Root(), proof, big.NewInt(4), big.NewInt(0)))
|
||||
assert.Equal(t, "0003000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730211ddfcc8d30ebd157d1d6912769b8e4abdca41e5dc2b57b026a361c091a8c14c748530e61bf8ea80c987657c3d24b134ece1ef8e2d4bd3f74437bf4392a6b1e", hex.EncodeToString(proof.Bytes()))
|
||||
assert.Equal(t, "0003000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730211ddfcc8d30ebd157d1d6912769b8e4abdca41e5dc2b57b026a361c091a8c14c748530e61bf8ea80c987657c3d24b134ece1ef8e2d4bd3f74437bf4392a6b1e", hex.EncodeToString(proof.Bytes())) //nolint:lll
|
||||
|
||||
for i := 8; i < 32; i++ {
|
||||
proof, _, err = mt.GenerateProof(big.NewInt(int64(i)), nil)
|
||||
@@ -342,7 +353,7 @@ func TestVerifyProofCases(t *testing.T) {
|
||||
assert.Equal(t, proof.Existence, false)
|
||||
// assert.True(t, proof.nodeAux == nil)
|
||||
assert.True(t, VerifyProof(mt.Root(), proof, big.NewInt(12), big.NewInt(0)))
|
||||
assert.Equal(t, "0303000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730211ddfcc8d30ebd157d1d6912769b8e4abdca41e5dc2b57b026a361c091a8c14c748530e61bf8ea80c987657c3d24b134ece1ef8e2d4bd3f74437bf4392a6b1e04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(proof.Bytes()))
|
||||
assert.Equal(t, "0303000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730211ddfcc8d30ebd157d1d6912769b8e4abdca41e5dc2b57b026a361c091a8c14c748530e61bf8ea80c987657c3d24b134ece1ef8e2d4bd3f74437bf4392a6b1e04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(proof.Bytes())) //nolint:lll
|
||||
|
||||
// Non-existence proof, diff. node aux
|
||||
proof, _, err = mt.GenerateProof(big.NewInt(10), nil)
|
||||
@@ -352,7 +363,7 @@ func TestVerifyProofCases(t *testing.T) {
|
||||
assert.Equal(t, proof.Existence, false)
|
||||
assert.True(t, proof.NodeAux != nil)
|
||||
assert.True(t, VerifyProof(mt.Root(), proof, big.NewInt(10), big.NewInt(0)))
|
||||
assert.Equal(t, "0303000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730e667e2ca15909c4a23beff18e3cc74348fbd3c1a4c765a5bbbca126c9607a42b77e008a73926f1280f8531b139dc1cacf8d83fcec31d405f5c51b7cbddfe152902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(proof.Bytes()))
|
||||
assert.Equal(t, "0303000000000000000000000000000000000000000000000000000000000007a6d6b46fefe213a6b579844a1bb7ab5c2db4a13f8662d9c5e729c36728f42730e667e2ca15909c4a23beff18e3cc74348fbd3c1a4c765a5bbbca126c9607a42b77e008a73926f1280f8531b139dc1cacf8d83fcec31d405f5c51b7cbddfe152902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(proof.Bytes())) //nolint:lll
|
||||
}
|
||||
|
||||
func TestVerifyProofFalse(t *testing.T) {
|
||||
@@ -383,7 +394,8 @@ func TestVerifyProofFalse(t *testing.T) {
|
||||
// Now we change the proof from existence to non-existence, and add e's
|
||||
// data as auxiliary node.
|
||||
proof.Existence = false
|
||||
proof.NodeAux = &NodeAux{Key: NewHashFromBigInt(big.NewInt(int64(4))), Value: NewHashFromBigInt(big.NewInt(4))}
|
||||
proof.NodeAux = &NodeAux{Key: NewHashFromBigInt(big.NewInt(int64(4))),
|
||||
Value: NewHashFromBigInt(big.NewInt(4))}
|
||||
assert.True(t, !VerifyProof(mt.Root(), proof, big.NewInt(int64(4)), big.NewInt(0)))
|
||||
}
|
||||
|
||||
@@ -435,22 +447,22 @@ func TestDelete(t *testing.T) {
|
||||
// test vectors generated using https://github.com/iden3/circomlib smt.js
|
||||
err = mt.Add(big.NewInt(1), big.NewInt(2))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "6449712043256457369579901840927028403950625973089336675272087704159094984964", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "6449712043256457369579901840927028403950625973089336675272087704159094984964", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Add(big.NewInt(33), big.NewInt(44))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Add(big.NewInt(1234), big.NewInt(9876))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "12841932325181810040554102151615400973767747666110051836366805309524360490677", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "12841932325181810040554102151615400973767747666110051836366805309524360490677", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
// mt.PrintGraphViz(nil)
|
||||
|
||||
err = mt.Delete(big.NewInt(33))
|
||||
// mt.PrintGraphViz(nil)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "16195585003843604118922861401064871511855368913846540536604351220077317790615", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "16195585003843604118922861401064871511855368913846540536604351220077317790615", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Delete(big.NewInt(1234))
|
||||
assert.Nil(t, err)
|
||||
@@ -507,10 +519,10 @@ func TestDelete3(t *testing.T) {
|
||||
err = mt.Add(big.NewInt(2), big.NewInt(2))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "6701939280963330813043570145125351311131831356446202146710280245621673558344", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "6701939280963330813043570145125351311131831356446202146710280245621673558344", mt.Root().BigInt().String()) //nolint:lll
|
||||
err = mt.Delete(big.NewInt(1))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "10304354743004778619823249005484018655542356856535590307973732141291410579841", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "10304354743004778619823249005484018655542356856535590307973732141291410579841", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
mt2 := newTestingMerkle(t, 140)
|
||||
defer mt2.db.Close()
|
||||
@@ -532,10 +544,10 @@ func TestDelete4(t *testing.T) {
|
||||
err = mt.Add(big.NewInt(3), big.NewInt(3))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "6989694633650442615746486460134957295274675622748484439660143938730686550248", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "6989694633650442615746486460134957295274675622748484439660143938730686550248", mt.Root().BigInt().String()) //nolint:lll
|
||||
err = mt.Delete(big.NewInt(1))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "1192610901536912535888866440319084773171371421781091005185759505381507049136", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "1192610901536912535888866440319084773171371421781091005185759505381507049136", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
mt2 := newTestingMerkle(t, 140)
|
||||
defer mt2.db.Close()
|
||||
@@ -554,11 +566,11 @@ func TestDelete5(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
err = mt.Add(big.NewInt(33), big.NewInt(44))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "11404118908468506234838877883514126008995570353394659302846433035311596046064", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
err = mt.Delete(big.NewInt(1))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "12802904154263054831102426711825443668153853847661287611768065280921698471037", mt.Root().BigInt().String())
|
||||
assert.Equal(t, "12802904154263054831102426711825443668153853847661287611768065280921698471037", mt.Root().BigInt().String()) //nolint:lll
|
||||
|
||||
mt2 := newTestingMerkle(t, 140)
|
||||
defer mt2.db.Close()
|
||||
@@ -689,7 +701,9 @@ func TestUpdateCircomProcessorProof(t *testing.T) {
|
||||
assert.Equal(t, "10", cpp.NewKey.String())
|
||||
assert.Equal(t, "1024", cpp.NewValue.String())
|
||||
assert.Equal(t, false, cpp.IsOld0)
|
||||
assert.Equal(t, "[19625419... 46910949... 18399594... 20473908... 0 0 0 0 0 0 0]", fmt.Sprintf("%v", cpp.Siblings))
|
||||
assert.Equal(t,
|
||||
"[19625419... 46910949... 18399594... 20473908... 0 0 0 0 0 0 0]",
|
||||
fmt.Sprintf("%v", cpp.Siblings))
|
||||
}
|
||||
|
||||
func TestTypesMarshalers(t *testing.T) {
|
||||
|
||||
24
utils.go
24
utils.go
@@ -32,3 +32,27 @@ func HashElemsKey(key *big.Int, elems ...*big.Int) (*Hash, error) {
|
||||
}
|
||||
return NewHashFromBigInt(poseidonHash), nil
|
||||
}
|
||||
|
||||
// SetBitBigEndian sets the bit n in the bitmap to 1, in Big Endian.
|
||||
func SetBitBigEndian(bitmap []byte, n uint) {
|
||||
bitmap[uint(len(bitmap))-n/8-1] |= 1 << (n % 8)
|
||||
}
|
||||
|
||||
// TestBit tests whether the bit n in bitmap is 1.
|
||||
func TestBit(bitmap []byte, n uint) bool {
|
||||
return bitmap[n/8]&(1<<(n%8)) != 0
|
||||
}
|
||||
|
||||
// TestBitBigEndian tests whether the bit n in bitmap is 1, in Big Endian.
|
||||
func TestBitBigEndian(bitmap []byte, n uint) bool {
|
||||
return bitmap[uint(len(bitmap))-n/8-1]&(1<<(n%8)) != 0
|
||||
}
|
||||
|
||||
// SwapEndianness swaps the order of the bytes in the slice.
|
||||
func SwapEndianness(b []byte) []byte {
|
||||
o := make([]byte, len(b))
|
||||
for i := range b {
|
||||
o[len(b)-1-i] = b[i]
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user