diff --git a/go.mod b/go.mod index 47f1fe94e2e5d51d1d0048ac29fb15c710b5185d..4526aae3d5501de31344e16c149200b281287a1c 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/labstack/echo v3.3.10+incompatible github.com/labstack/gommon v0.2.9 // indirect github.com/magiconair/properties v1.8.1 - github.com/panjf2000/ants v1.1.0 github.com/pkg/errors v0.8.1 github.com/rivo/tview v0.0.0-20190721135419-23dc8a0944e4 github.com/rivo/uniseg v0.1.0 // indirect diff --git a/go.sum b/go.sum index ab297780047b1a4dccb9870593f9875073a28612..331a8ca2b0606ab27d583513ff5d7204af6baa29 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,6 @@ github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/panjf2000/ants v1.1.0 h1:z1311FxGnwySXwQum1k4ZlHkWs86Xy18il4fuRzQemw= -github.com/panjf2000/ants v1.1.0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/packages/database/badger_instance.go b/packages/database/badger_instance.go index 50b5d8ba0593b887d69e71d8733f6c9c6a6b14be..6cf834f7140df321e9971e1c439dbd1a86bf1fdb 100644 --- a/packages/database/badger_instance.go +++ b/packages/database/badger_instance.go @@ -6,48 +6,63 @@ import ( "github.com/dgraph-io/badger" "github.com/dgraph-io/badger/options" + "github.com/pkg/errors" ) var instance *badger.DB +var once sync.Once -var openLock sync.Mutex - -func GetBadgerInstance() (result *badger.DB, err error) { - openLock.Lock() +// Returns whether the given file or directory exists. +func exists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if os.IsNotExist(err) { + return false, nil + } + return false, err +} - if instance == nil { - directory := *DIRECTORY.Value +func checkDir(dir string) error { + exists, err := exists(dir) + if err != nil { + return err + } - if _, osErr := os.Stat(directory); os.IsNotExist(osErr) { - if osErr := os.Mkdir(directory, 0700); osErr != nil { - err = osErr + if !exists { + return os.Mkdir(dir, 0700) + } + return nil +} - return - } - } else if osErr != nil { - err = osErr +func createDB() (*badger.DB, error) { + directory := *DIRECTORY.Value + if err := checkDir(directory); err != nil { + return nil, errors.Wrap(err, "Could not check directory") + } - return - } + opts := badger.DefaultOptions(directory) + opts.Logger = &logger{} + opts.Truncate = true + opts.TableLoadingMode = options.MemoryMap - opts := badger.DefaultOptions(directory) - opts.Logger = &logger{} - opts.Truncate = true - opts.TableLoadingMode = options.MemoryMap + db, err := badger.Open(opts) + if err != nil { + return nil, errors.Wrap(err, "Could not open new DB") + } - db, badgerErr := badger.Open(opts) - if badgerErr != nil { - err = badgerErr + return db, nil +} - return +func GetBadgerInstance() *badger.DB { + once.Do(func() { + db, err := createDB() + if err != nil { + // errors should cause a panic to avoid singleton deadlocks + panic(err) } - instance = db - } - - openLock.Unlock() - - result = instance - - return + }) + return instance } diff --git a/packages/database/database.go b/packages/database/database.go index 4a0e9657f6e66182154ff3ca1dae9cfc39d1eebe..573d0dd4168c2ec79d511de94b1a400243a4face 100644 --- a/packages/database/database.go +++ b/packages/database/database.go @@ -6,12 +6,10 @@ import ( "github.com/dgraph-io/badger" ) -var databasesByName = make(map[string]*databaseImpl) -var getLock sync.Mutex +var dbMap = make(map[string]*prefixDb) +var mu sync.Mutex -var ErrKeyNotFound = badger.ErrKeyNotFound - -type databaseImpl struct { +type prefixDb struct { db *badger.DB name string prefix []byte @@ -19,30 +17,32 @@ type databaseImpl struct { } func Get(name string) (Database, error) { - getLock.Lock() - defer getLock.Unlock() - - if database, exists := databasesByName[name]; exists { - return database, nil + // avoid locking if it's a clean hit + if db, exists := dbMap[name]; exists { + return db, nil } - badgerInstance, err := GetBadgerInstance() - if err != nil { - return nil, err + mu.Lock() + defer mu.Unlock() + + // needs to be re-checked after locking + if db, exists := dbMap[name]; exists { + return db, nil } - database := &databaseImpl{ - db: badgerInstance, + badger := GetBadgerInstance() + db := &prefixDb{ + db: badger, name: name, prefix: []byte(name + "_"), } - databasesByName[name] = database + dbMap[name] = db - return databasesByName[name], nil + return db, nil } -func (this *databaseImpl) Set(key []byte, value []byte) error { +func (this *prefixDb) Set(key []byte, value []byte) error { if err := this.db.Update(func(txn *badger.Txn) error { return txn.Set(append(this.prefix, key...), value) }); err != nil { return err } @@ -50,7 +50,7 @@ func (this *databaseImpl) Set(key []byte, value []byte) error { return nil } -func (this *databaseImpl) Contains(key []byte) (bool, error) { +func (this *prefixDb) Contains(key []byte) (bool, error) { err := this.db.View(func(txn *badger.Txn) error { _, err := txn.Get(append(this.prefix, key...)) if err != nil { @@ -60,14 +60,14 @@ func (this *databaseImpl) Contains(key []byte) (bool, error) { return nil }) - if err == ErrKeyNotFound { + if err == badger.ErrKeyNotFound { return false, nil } else { return err == nil, err } } -func (this *databaseImpl) Get(key []byte) ([]byte, error) { +func (this *prefixDb) Get(key []byte) ([]byte, error) { var result []byte = nil err := this.db.View(func(txn *badger.Txn) error { @@ -86,7 +86,7 @@ func (this *databaseImpl) Get(key []byte) ([]byte, error) { return result, err } -func (this *databaseImpl) Delete(key []byte) error { +func (this *prefixDb) Delete(key []byte) error { err := this.db.Update(func(txn *badger.Txn) error { err := txn.Delete(append(this.prefix, key...)) return err @@ -94,10 +94,10 @@ func (this *databaseImpl) Delete(key []byte) error { return err } -func (this *databaseImpl) ForEach(consumer func([]byte, []byte)) error { +func (this *prefixDb) ForEach(consumer func([]byte, []byte)) error { err := this.db.View(func(txn *badger.Txn) error { iteratorOptions := badger.DefaultIteratorOptions - iteratorOptions.Prefix = this.prefix + iteratorOptions.Prefix = this.prefix // filter by prefix // create an iterator the default options it := txn.NewIterator(iteratorOptions) diff --git a/packages/datastructure/weakmap_test.go b/packages/datastructure/weakmap_test.go deleted file mode 100644 index 2c239962d5c449f1834ec318cd0d1c977e1cb9b6..0000000000000000000000000000000000000000 --- a/packages/datastructure/weakmap_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package datastructure - -import ( - "fmt" - "testing" -) -import "runtime" -import "unsafe" -import "errors" -import "time" - -func TestWeakmap(t *testing.T) { - generateA(6) - fmt.Println("") - - debugWeakMap(6) - fmt.Println("") - - runtime.GC() - fmt.Println("GC runned.") - - time.Sleep(1 * time.Second) - - debugWeakMap(6) -} - -func generateA(n int) { - - for i := 0; i < n; i++ { - a := NewA() - WMap.Add(a) - fmt.Println("Added to WM A with id =", a.Id) - } - -} - -func debugWeakMap(n int) { - for i := 0; i < n; i++ { - if WMap.Has(i) { - fmt.Println("Has id =", i) - } else { - fmt.Println("Hasn't id =", i) - } - } -} - -var aId int - -func NewA() *A { - aId++ - return &A{aId} -} - -var WMap = &WeakMap{weakMap: make(map[int]uintptr)} - -type WeakMap struct { - weakMap map[int]uintptr -} - -type A struct { - Id int -} - -func (w *WeakMap) Add(a *A) { - runtime.SetFinalizer(a, finalizer) - - w.weakMap[a.Id] = uintptr(unsafe.Pointer(a)) -} - -func (w *WeakMap) Get(id int) (*A, error) { - if !w.Has(id) { - return nil, errors.New("") - } - - a := (*A)(unsafe.Pointer(w.weakMap[id])) - - return a, nil -} - -func (w *WeakMap) Has(id int) bool { - _, ok := w.weakMap[id] - return ok -} - -func (w *WeakMap) Remove(a *A) { - delete(w.weakMap, a.Id) -} - -func finalizer(a *A) { - fmt.Println(a.Id) - WMap.Remove(a) -} diff --git a/packages/events/event_test.go b/packages/events/event_test.go index 45084ba6faa58371eb5eb55c2ba2d1b084f95a85..37d91bd9a02fe5a49457656f83055eb33c7014d9 100644 --- a/packages/events/event_test.go +++ b/packages/events/event_test.go @@ -25,7 +25,7 @@ func intStringCaller(handler interface{}, params ...interface{}) { handler.(func(int, string))(params[0].(int), params[1].(string)) } -func ExampleHelloWorld() { +func ExampleEvent() { // create event object (usually exposed through a public struct that holds all the different event types) event := NewEvent(intStringCaller) diff --git a/packages/workerpool/workerpool_test.go b/packages/workerpool/workerpool_test.go index fb8f83e38adfe543488cc7170d77776fc74d66ca..deab7db7027dc68d0917321e23cad534601af24a 100644 --- a/packages/workerpool/workerpool_test.go +++ b/packages/workerpool/workerpool_test.go @@ -15,11 +15,11 @@ func Benchmark(b *testing.B) { for i := 0; i < b.N; i++ { wg.Add(1) - go func() { + go func(i int) { <-pool.Submit(i) wg.Done() - }() + }(i) } wg.Wait() diff --git a/plugins/autopeering/types/peerregister/peer_register.go b/plugins/autopeering/types/peerregister/peer_register.go index b90608dd84d1063e2352002af1109da3bd813a09..4b233d9491a1d33a5579f12aa2538f76693e20a9 100644 --- a/plugins/autopeering/types/peerregister/peer_register.go +++ b/plugins/autopeering/types/peerregister/peer_register.go @@ -73,7 +73,9 @@ func (this *PeerRegister) Remove(key string, lock ...bool) { if len(lock) == 0 || lock[0] { defer this.Lock()() - if peerEntry, exists := this.Peers[key]; exists { + // needs to be updated after locking + peerEntry, exists = this.Peers[key] + if exists { delete(this.Peers, key) this.Events.Remove.Trigger(peerEntry) diff --git a/plugins/validator/plugin.go b/plugins/validator/plugin.go index 10e80653233b88f608c2dce6ac59ad163ba50420..f5785b9869d3c26d0d097c4a6ede8f5142858622 100644 --- a/plugins/validator/plugin.go +++ b/plugins/validator/plugin.go @@ -6,8 +6,6 @@ import ( "github.com/iotaledger/goshimmer/packages/model/value_transaction" "github.com/iotaledger/goshimmer/packages/node" "github.com/iotaledger/goshimmer/plugins/bundleprocessor" - "github.com/iotaledger/iota.go/address" - . "github.com/iotaledger/iota.go/consts" "github.com/iotaledger/iota.go/kerl" "github.com/iotaledger/iota.go/signing" . "github.com/iotaledger/iota.go/trinary" @@ -15,31 +13,6 @@ import ( var PLUGIN = node.NewPlugin("Validator", node.Enabled, configure, run) -// Creates bundle signature fragments and the corresponding address to validate against. -// Each signature fragment after the first must go into its own meta transaction with value = 0. -func demoSign(seed Trytes, index uint64, sec SecurityLevel, bundleHash Hash) (Hash, []Trytes) { - addr, _ := address.GenerateAddress(seed, index, sec) - - // compute seed based on address index - subseed, _ := signing.Subseed(seed, index) - // generate the private key - prvKey, _ := signing.Key(subseed, sec) - - normalizedBundleHash := signing.NormalizedBundleHash(bundleHash) - - signatureFragments := make([]Trytes, sec) - for i := 0; i < int(sec); i++ { - // each security level signs one third of the (normalized) bundle hash - signedFragTrits, _ := signing.SignatureFragment( - normalizedBundleHash[i*HashTrytesSize/3:(i+1)*HashTrytesSize/3], - prvKey[i*KeyFragmentLength:(i+1)*KeyFragmentLength], - ) - signatureFragments[i] = MustTritsToTrytes(signedFragTrits) - } - - return addr, signatureFragments -} - func validateSignatures(bundleHash Hash, txs []*value_transaction.ValueTransaction) (bool, error) { for i, tx := range txs { // ignore all non-input transactions diff --git a/plugins/validator/validator_test.go b/plugins/validator/validator_test.go new file mode 100644 index 0000000000000000000000000000000000000000..fd4f70b431db7fc3765c5847e235d1888571b4bb --- /dev/null +++ b/plugins/validator/validator_test.go @@ -0,0 +1,54 @@ +package validator + +import ( + "fmt" + + "github.com/iotaledger/iota.go/address" + . "github.com/iotaledger/iota.go/consts" + "github.com/iotaledger/iota.go/signing" + . "github.com/iotaledger/iota.go/trinary" +) + +const ( + exampleHash = "999999999999999999999999999999999999999999999999999999999999999999999999999999999" + exampleSeed = exampleHash + exmapleIndex = 0 + exampleSec = SecurityLevelLow +) + +// Creates bundle signature fragments for the given address index and bundle hash. +// Each signature fragment after the first must go into its own meta transaction with value = 0. +func signature(seed Trytes, index uint64, sec SecurityLevel, bundleHash Hash) []Trytes { + // compute seed based on address index + subseed, _ := signing.Subseed(seed, index) + // generate the private key + prvKey, _ := signing.Key(subseed, sec) + + normalizedBundleHash := signing.NormalizedBundleHash(bundleHash) + + signatureFragments := make([]Trytes, sec) + for i := 0; i < int(sec); i++ { + // each security level signs one third of the (normalized) bundle hash + signedFragTrits, _ := signing.SignatureFragment( + normalizedBundleHash[i*HashTrytesSize/3:(i+1)*HashTrytesSize/3], + prvKey[i*KeyFragmentLength:(i+1)*KeyFragmentLength], + ) + signatureFragments[i] = MustTritsToTrytes(signedFragTrits) + } + + return signatureFragments +} + +func ExamplePLUGIN() { + // corresponding address to validate against. + addr, _ := address.GenerateAddress(exampleSeed, exmapleIndex, exampleSec) + fmt.Println(addr) + + // compute the signature fragments which would be added to the (meta) transactions + signatureFragments := signature(exampleSeed, exmapleIndex, exampleSec, exampleHash) + fmt.Println(signatureFragments[0]) + + // Output: + // BSIXFJENGVJSOWPVHVALMPOPO9PUKHXDQI9VDELCBJXN9TCNQPTFEDMPQCVBOJSZUHEOABYYYAT9IAHHY + // GHHKPBXOOBOEHGGEEKYPH9MANWEKSQTQJFJ9KUTMJQAVITYRZMNLUESQARNHAWUJAPPZSQ9A9RUKABCE9KZPJDUEHVZEOSCQMTCC9AWBGWZLZEXMJ9YOQUVIBGMXSINCOLUATYDDUBAALHCBIONNRQIVIPUFPOIFHYRBFBGXXNVYXFZUSTTA9LYGGITTAJCVDE9GCFRGIOTXLQ9ZJDLONDLZ9OPS9TNYVKLTCGFBH9QPJWLIGADWMTJVCLAUCOZFDSRRCAMVWYFXRPGPMIOPIW9GBWANVSMPONQOTNLLYYHXAMZMMNRHMRXHEIXPVNORNGZZ9ZAU9RAWASOZNIBKDWYZWKCMLEUE9UVDHZ9XXGPXZABB9FGTNDTDFTYCKLKRRC9GZFKHKDGAWPBWEUPPWISYBBNZCIBERPXTMZPZHPKKUQUPBIJBIKZAGFHDDNAGCRQMWOMLUMAYKRBMHPMDWZK9JRBDWCJCBJQYMDUBNKOIRSJSVTCNKROZ9KLFBZLOXQOASLCFETCNZRPZULOABOFCUO9WKNQILLLTQ9GWVDBASBGSKUHFHRXOKQIBRCLUYZBZMTXTIG9BJNYHTJQQOECXOWLIDOYKMFJWKRCYW99VZILSPU9I9ZSTTBZVGISUHPCWLGKCFNLIHJNCL9OWQDNAKJAGRKTGCTDRHXVAYXOHNFVJYBMZLMXV9VINNIAWONYDYOKHHMOFFEOOVBMVMYABWRWLZTWJECKKAGPCIMUDZZIEJCFBXFIYKDRMWZIOEUZNLOXZJRDHVVKOTJWMLTIXVIRJSXUBLFGOCCLEIZVCDYD9FEMCRUOERPRDFGUJSALRSOBN9J9XDTUAJZFLHUGQI9MCXZCYWTTIHNQUPUYPDRJLRZG9HAXHYQDSSCQNPTBYKNQUWZDE9QUESZJASRXHNW9OKAVUKLLMVGOJJRZCPRXSRYUECLNQEFIHI9S9NNEN9KACVIKCZYDEKCDNUASUJWMTVLSPBOBQMQEMZJXJVQAMUGBTMNWEWVJSXNZKIAADSQCCLISYSUZICSIVXZUG9MTICGWXKXKJDW9TOUBS9BTOUFUKWEBVIIJTGD9IBLRHBCPICWSZQNJQERTBOZGLJFCXKGQTAHIWKOSGHRMMWXABQYHVHOPG9XDIXMIRBXHOSYBCHSFWORNLUD9JAB9ICBIPXYVLIXYNRHJVEDMIRSAGXKZKSFZADJ9GA9DGJZAJTXZGIKRXVBCCBGJPJWJJZXZRQNWLEUZEFTWOXUBTAGDPPKKPKRYPGXVSRWLRNEDAXHZYT9DRN9L9ZWXPTTOSKMGTPQQXHACAKESRQXVXXNOLIATRKDGGJNIDWWYKQSLTC9ERTPMNXQHZNVNSBGIRRQHMOCOGDWPQAU9WPRSGZMPXZWQADUFUAWVGESLIWZNV9WNANDMZAOLXIHAOSFBADWVVAHMJVFNX9BGMMYGMJCUOYCSKJWIUMYHQFQXCFQXQNB9VTBLAYGKUZLFH9UVWIQJVLMLOZDLLIPJZSNXBPWAKKZWKCVSWUSBSQLBIAX9SQGMNPCJWTQDQEASSWWCSTVJRFDBPBLNYU9CNFUYINVMQPJZGKKUH9QBMUVWFSLPXWKBBWKNLMHGCEMJWCTNXZYWCFXYU9XLTWDSROJDTCRARMBNYDDD99HCFMXMUCO9NJSRA9G9HGWRTWNDBDQLBTCNYIVRMWRWPDJDDYCDODGEBNFTNINPNMZYMJJHVZSNEIJOAPGHAIVCZHQIULTRIZ9ML9LCWTQVGLBKKBGJYZTOZZIYUBCBKHKYUHCFGZKDERTWYHNYWSWLGPUGRB9WNQTHOMBFPKUQZREUQCNXL9MFSZCNBN9PTAVCERMWTTFDZL9BJQMC9OUBWGDTURAEYTYRDNFUBATOWFSVNXJC9JUPARMU9MINY9RWRHIXBPNIUADFAEP9F9FWNJNRPNGLWHRYYCV9ZIWBOUZPFZTWDLOCNOYZQLWFJHZ99ZBLUDSIQBJOJXMQJBUCYYMROBCJJJNCETVUYRXKHAWGUBIWOKQXOIOYBQKNDXZCKXQZLWEMXYLJPODRMOQUYOAATZZQ9JZDR9KPIHRQKIEAQNO9OVXNHDFCUUIZRQDWYGKUAYIGHGIIJIOIERLVNDUEBZUAQGDZMWNGXQPYSNWUEGF9BQDFJEQRPEGFGJTQFWO9PWECFGNDH9LW +}