Browse Source

:ledger: Send only last block over

Ettore Di Giacinto 3 years ago
parent
commit
9519584166
3 changed files with 44 additions and 32 deletions
  1. 1 0
      go.mod
  2. 3 0
      go.sum
  3. 40 32
      pkg/blockchain/ledger.go

+ 1 - 0
go.mod

@@ -18,6 +18,7 @@ require (
 	github.com/lthibault/jitterbug v2.0.0+incompatible
 	github.com/lthibault/jitterbug v2.0.0+incompatible
 	github.com/mudler/go-isterminal v0.0.0-20211031135732-5e4e06fc5a58 // indirect
 	github.com/mudler/go-isterminal v0.0.0-20211031135732-5e4e06fc5a58 // indirect
 	github.com/multiformats/go-multiaddr v0.4.0
 	github.com/multiformats/go-multiaddr v0.4.0
+	github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
 	github.com/pkg/errors v0.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/pterm/pterm v0.12.33 // indirect
 	github.com/pterm/pterm v0.12.33 // indirect
 	github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091
 	github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091

+ 3 - 0
go.sum

@@ -241,6 +241,7 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -877,6 +878,8 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
 github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
+github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

+ 40 - 32
pkg/blockchain/ledger.go

@@ -9,20 +9,30 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/mudler/edgevpn/pkg/hub"
 	"github.com/mudler/edgevpn/pkg/hub"
+
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 )
 )
 
 
 type Ledger struct {
 type Ledger struct {
 	sync.Mutex
 	sync.Mutex
-	blockchain Blockchain
+	blockchain store
 
 
 	maxChainSize int
 	maxChainSize int
 	channel      io.Writer
 	channel      io.Writer
+
+	onDisk bool
+}
+
+type store interface {
+	Add(Block)
+	Reset()
+	Len() int
+	Last() Block
 }
 }
 
 
 // New returns a new ledger which writes to the writer
 // New returns a new ledger which writes to the writer
 func New(w io.Writer, maxChainSize int) *Ledger {
 func New(w io.Writer, maxChainSize int) *Ledger {
-	c := &Ledger{channel: w, maxChainSize: maxChainSize}
+	c := &Ledger{channel: w, maxChainSize: maxChainSize, blockchain: &memory{}}
 	c.newGenesis()
 	c.newGenesis()
 	return c
 	return c
 }
 }
@@ -31,7 +41,7 @@ func (l *Ledger) newGenesis() {
 	t := time.Now()
 	t := time.Now()
 	genesisBlock := Block{}
 	genesisBlock := Block{}
 	genesisBlock = Block{0, t.String(), map[string]map[string]Data{}, genesisBlock.Checksum(), ""}
 	genesisBlock = Block{0, t.String(), map[string]map[string]Data{}, genesisBlock.Checksum(), ""}
-	l.blockchain = append(l.blockchain, genesisBlock)
+	l.blockchain.Add(genesisBlock)
 }
 }
 
 
 // Syncronizer starts a goroutine which
 // Syncronizer starts a goroutine which
@@ -44,15 +54,15 @@ func (l *Ledger) Syncronizer(ctx context.Context, t time.Duration) {
 			select {
 			select {
 			case <-t.C:
 			case <-t.C:
 				l.Lock()
 				l.Lock()
-				bytes, err := json.Marshal(l.blockchain)
+				bytes, err := json.Marshal(l.blockchain.Last())
 				if err != nil {
 				if err != nil {
 					log.Println(err)
 					log.Println(err)
 				}
 				}
 				l.channel.Write(bytes)
 				l.channel.Write(bytes)
 
 
 				// Reset blockchain if we exceed chainsize
 				// Reset blockchain if we exceed chainsize
-				if l.maxChainSize != 0 && len(l.blockchain) >= l.maxChainSize {
-					l.blockchain = []Block{}
+				if l.maxChainSize != 0 && l.blockchain.Len() >= l.maxChainSize {
+					l.blockchain.Reset()
 					l.newGenesis()
 					l.newGenesis()
 				}
 				}
 				l.Unlock()
 				l.Unlock()
@@ -71,18 +81,20 @@ func (l *Ledger) String() string {
 
 
 // Update the blockchain from a message
 // Update the blockchain from a message
 func (l *Ledger) Update(h *hub.Message) (err error) {
 func (l *Ledger) Update(h *hub.Message) (err error) {
-	chain := make(Blockchain, 0)
+	//chain := make(Blockchain, 0)
+	block := &Block{}
 
 
-	err = json.Unmarshal([]byte(h.Message), &chain)
+	err = json.Unmarshal([]byte(h.Message), block)
 	if err != nil {
 	if err != nil {
 		err = errors.Wrap(err, "failed unmarshalling blockchain data")
 		err = errors.Wrap(err, "failed unmarshalling blockchain data")
 		return
 		return
 	}
 	}
 
 
 	l.Lock()
 	l.Lock()
-	if (l.maxChainSize == 0 || (l.maxChainSize != 0 && len(chain) <= l.maxChainSize)) &&
-		chain.IsMoreRecent(l.blockchain) {
-		l.blockchain = chain
+	if (l.maxChainSize == 0 || (l.maxChainSize != 0 && block.Index <= l.maxChainSize)) &&
+		block.Index > l.blockchain.Len() || block.Index == l.blockchain.Len() &&
+		block.Hash != l.blockchain.Last().Hash {
+		l.blockchain.Add(*block)
 	}
 	}
 	l.Unlock()
 	l.Unlock()
 
 
@@ -153,17 +165,13 @@ func (l *Ledger) Persist(ctx context.Context, interval time.Duration, bucket, ke
 	})
 	})
 }
 }
 
 
-func (l *Ledger) lastBlock() Block {
-	return (l.blockchain[len(l.blockchain)-1])
-}
-
 // GetKey retrieve the current key from the blockchain
 // GetKey retrieve the current key from the blockchain
 func (l *Ledger) GetKey(b, s string) (value Data, exists bool) {
 func (l *Ledger) GetKey(b, s string) (value Data, exists bool) {
 	l.Lock()
 	l.Lock()
 	defer l.Unlock()
 	defer l.Unlock()
 
 
-	if len(l.blockchain) > 0 {
-		last := l.lastBlock()
+	if l.blockchain.Len() > 0 {
+		last := l.blockchain.Last()
 		if _, exists = last.Storage[b]; !exists {
 		if _, exists = last.Storage[b]; !exists {
 			return
 			return
 		}
 		}
@@ -179,8 +187,8 @@ func (l *Ledger) GetKey(b, s string) (value Data, exists bool) {
 func (l *Ledger) Exists(b string, f func(Data) bool) (exists bool) {
 func (l *Ledger) Exists(b string, f func(Data) bool) (exists bool) {
 	l.Lock()
 	l.Lock()
 	defer l.Unlock()
 	defer l.Unlock()
-	if len(l.blockchain) > 0 {
-		for _, bv := range l.lastBlock().Storage[b] {
+	if l.blockchain.Len() > 0 {
+		for _, bv := range l.blockchain.Last().Storage[b] {
 			if f(bv) {
 			if f(bv) {
 				exists = true
 				exists = true
 				return
 				return
@@ -195,20 +203,20 @@ func (l *Ledger) Exists(b string, f func(Data) bool) (exists bool) {
 func (l *Ledger) CurrentData() map[string]map[string]Data {
 func (l *Ledger) CurrentData() map[string]map[string]Data {
 	l.Lock()
 	l.Lock()
 	defer l.Unlock()
 	defer l.Unlock()
-	return l.lastBlock().Storage
+	return l.blockchain.Last().Storage
 }
 }
 
 
-// BlockChain returns the current blockchain (locking)
-func (l *Ledger) BlockChain() Blockchain {
-	l.Lock()
-	defer l.Unlock()
-	return l.blockchain
-}
+// // BlockChain returns the current blockchain (locking)
+// func (l *Ledger) BlockChain() Blockchain {
+// 	l.Lock()
+// 	defer l.Unlock()
+// 	return l.blockchain
+// }
 
 
 // Add data to the blockchain
 // Add data to the blockchain
 func (l *Ledger) Add(b string, s map[string]interface{}) {
 func (l *Ledger) Add(b string, s map[string]interface{}) {
 	l.Lock()
 	l.Lock()
-	current := l.lastBlock().Storage
+	current := l.blockchain.Last().Storage
 	for s, k := range s {
 	for s, k := range s {
 		if _, exists := current[b]; !exists {
 		if _, exists := current[b]; !exists {
 			current[b] = make(map[string]Data)
 			current[b] = make(map[string]Data)
@@ -224,7 +232,7 @@ func (l *Ledger) Add(b string, s map[string]interface{}) {
 func (l *Ledger) Delete(b string, k string) {
 func (l *Ledger) Delete(b string, k string) {
 	l.Lock()
 	l.Lock()
 	new := make(map[string]map[string]Data)
 	new := make(map[string]map[string]Data)
-	for bb, kk := range l.lastBlock().Storage {
+	for bb, kk := range l.blockchain.Last().Storage {
 		if _, exists := new[bb]; !exists {
 		if _, exists := new[bb]; !exists {
 			new[bb] = make(map[string]Data)
 			new[bb] = make(map[string]Data)
 		}
 		}
@@ -243,7 +251,7 @@ func (l *Ledger) Delete(b string, k string) {
 func (l *Ledger) DeleteBucket(b string) {
 func (l *Ledger) DeleteBucket(b string) {
 	l.Lock()
 	l.Lock()
 	new := make(map[string]map[string]Data)
 	new := make(map[string]map[string]Data)
-	for bb, kk := range l.lastBlock().Storage {
+	for bb, kk := range l.blockchain.Last().Storage {
 		// Copy all except the specified bucket
 		// Copy all except the specified bucket
 		if bb == b {
 		if bb == b {
 			continue
 			continue
@@ -260,11 +268,11 @@ func (l *Ledger) DeleteBucket(b string) {
 }
 }
 
 
 func (l *Ledger) writeData(s map[string]map[string]Data) {
 func (l *Ledger) writeData(s map[string]map[string]Data) {
-	newBlock := l.lastBlock().NewBlock(s)
+	newBlock := l.blockchain.Last().NewBlock(s)
 
 
-	if newBlock.IsValid(l.lastBlock()) {
+	if newBlock.IsValid(l.blockchain.Last()) {
 		l.Lock()
 		l.Lock()
-		l.blockchain = append(l.blockchain, newBlock)
+		l.blockchain.Add(newBlock)
 		l.Unlock()
 		l.Unlock()
 	}
 	}