mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-03 23:57:26 +00:00 
			
		
		
		
	primitive storage + data clock store
This commit is contained in:
		
							parent
							
								
									c6d02ad1e7
								
							
						
					
					
						commit
						b7b5bc0e41
					
				
							
								
								
									
										112
									
								
								node/app/db_console.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								node/app/db_console.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/store"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DBConsole struct {
 | 
			
		||||
	clockStore store.ClockStore
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newDBConsole(
 | 
			
		||||
	clockStore store.ClockStore,
 | 
			
		||||
) (*DBConsole, error) {
 | 
			
		||||
	return &DBConsole{
 | 
			
		||||
		clockStore,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Runs the DB console, this is meant for simple debugging, not production use.
 | 
			
		||||
func (c *DBConsole) Run() {
 | 
			
		||||
	for {
 | 
			
		||||
		fmt.Printf("db> ")
 | 
			
		||||
 | 
			
		||||
		reader := bufio.NewReader(os.Stdin)
 | 
			
		||||
		s, err := reader.ReadString('\n')
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cmd := strings.Trim(s, "\n")
 | 
			
		||||
		switch cmd {
 | 
			
		||||
		case "quit":
 | 
			
		||||
			return
 | 
			
		||||
		case "show frames":
 | 
			
		||||
			earliestFrame, err := c.clockStore.GetEarliestMasterClockFrame([]byte{
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			latestFrame, err := c.clockStore.GetLatestMasterClockFrame([]byte{
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fmt.Printf(
 | 
			
		||||
				"earliest: %d, latest: %d\n",
 | 
			
		||||
				earliestFrame.FrameNumber,
 | 
			
		||||
				latestFrame.FrameNumber,
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			fmt.Printf(
 | 
			
		||||
				"Genesis Frame:\n\tVDF Proof: %x\n",
 | 
			
		||||
				earliestFrame.Input[:516],
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			iter, err := c.clockStore.RangeMasterClockFrames(
 | 
			
		||||
				[]byte{
 | 
			
		||||
					0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
					0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
					0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
					0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				},
 | 
			
		||||
				earliestFrame.FrameNumber,
 | 
			
		||||
				latestFrame.FrameNumber,
 | 
			
		||||
			)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for iter.First(); iter.Valid(); iter.Next() {
 | 
			
		||||
				value, err := iter.Value()
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					panic(err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				selector, err := value.GetSelector()
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					panic(err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				fmt.Printf(
 | 
			
		||||
					"Frame %d (Selector: %x):\n\tParent: %x\n\tVDF Proof: %x\n\n",
 | 
			
		||||
					value.FrameNumber,
 | 
			
		||||
					selector.Bytes(),
 | 
			
		||||
					value.ParentSelector,
 | 
			
		||||
					value.Input[:516],
 | 
			
		||||
				)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err := iter.Close(); err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			fmt.Printf("unknown command %s\n", cmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/execution/nop"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/keys"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/p2p"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/store"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func logger() *zap.Logger {
 | 
			
		||||
@ -33,6 +34,13 @@ var keyManagerSet = wire.NewSet(
 | 
			
		||||
	wire.Bind(new(keys.KeyManager), new(*keys.FileKeyManager)),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var storeSet = wire.NewSet(
 | 
			
		||||
	wire.FieldsOf(new(*config.Config), "DB"),
 | 
			
		||||
	store.NewPebbleDB,
 | 
			
		||||
	store.NewPebbleClockStore,
 | 
			
		||||
	wire.Bind(new(store.ClockStore), new(*store.PebbleClockStore)),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var pubSubSet = wire.NewSet(
 | 
			
		||||
	wire.FieldsOf(new(*config.Config), "P2P"),
 | 
			
		||||
	p2p.NewBlossomSub,
 | 
			
		||||
@ -46,9 +54,24 @@ var engineSet = wire.NewSet(
 | 
			
		||||
var consensusSet = wire.NewSet(
 | 
			
		||||
	wire.FieldsOf(new(*config.Config), "Engine"),
 | 
			
		||||
	master.NewMasterClockConsensusEngine,
 | 
			
		||||
	wire.Bind(new(consensus.ConsensusEngine), new(*master.MasterClockConsensusEngine)),
 | 
			
		||||
	wire.Bind(
 | 
			
		||||
		new(consensus.ConsensusEngine),
 | 
			
		||||
		new(*master.MasterClockConsensusEngine),
 | 
			
		||||
	),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewNode(*config.Config) (*Node, error) {
 | 
			
		||||
	panic(wire.Build(loggerSet, keyManagerSet, pubSubSet, engineSet, consensusSet, newNode))
 | 
			
		||||
	panic(wire.Build(
 | 
			
		||||
		loggerSet,
 | 
			
		||||
		keyManagerSet,
 | 
			
		||||
		storeSet,
 | 
			
		||||
		pubSubSet,
 | 
			
		||||
		engineSet,
 | 
			
		||||
		consensusSet,
 | 
			
		||||
		newNode,
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDBConsole(*config.Config) (*DBConsole, error) {
 | 
			
		||||
	panic(wire.Build(loggerSet, storeSet, newDBConsole))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ import (
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/execution/nop"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/keys"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/p2p"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/store"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Injectors from wire.go:
 | 
			
		||||
@ -23,11 +24,14 @@ func NewNode(configConfig *config.Config) (*Node, error) {
 | 
			
		||||
	zapLogger := logger()
 | 
			
		||||
	nopExecutionEngine := nop.NewNopExecutionEngine(zapLogger)
 | 
			
		||||
	engineConfig := configConfig.Engine
 | 
			
		||||
	dbConfig := configConfig.DB
 | 
			
		||||
	db := store.NewPebbleDB(dbConfig)
 | 
			
		||||
	pebbleClockStore := store.NewPebbleClockStore(db, zapLogger)
 | 
			
		||||
	keyConfig := configConfig.Key
 | 
			
		||||
	fileKeyManager := keys.NewFileKeyManager(keyConfig, zapLogger)
 | 
			
		||||
	p2PConfig := configConfig.P2P
 | 
			
		||||
	blossomSub := p2p.NewBlossomSub(p2PConfig, zapLogger)
 | 
			
		||||
	masterClockConsensusEngine := master.NewMasterClockConsensusEngine(engineConfig, zapLogger, fileKeyManager, blossomSub)
 | 
			
		||||
	masterClockConsensusEngine := master.NewMasterClockConsensusEngine(engineConfig, zapLogger, pebbleClockStore, fileKeyManager, blossomSub)
 | 
			
		||||
	node, err := newNode(nopExecutionEngine, masterClockConsensusEngine)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@ -35,6 +39,18 @@ func NewNode(configConfig *config.Config) (*Node, error) {
 | 
			
		||||
	return node, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDBConsole(configConfig *config.Config) (*DBConsole, error) {
 | 
			
		||||
	dbConfig := configConfig.DB
 | 
			
		||||
	db := store.NewPebbleDB(dbConfig)
 | 
			
		||||
	zapLogger := logger()
 | 
			
		||||
	pebbleClockStore := store.NewPebbleClockStore(db, zapLogger)
 | 
			
		||||
	dbConsole, err := newDBConsole(pebbleClockStore)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return dbConsole, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wire.go:
 | 
			
		||||
 | 
			
		||||
func logger() *zap.Logger {
 | 
			
		||||
@ -52,8 +68,14 @@ var loggerSet = wire.NewSet(
 | 
			
		||||
 | 
			
		||||
var keyManagerSet = wire.NewSet(wire.FieldsOf(new(*config.Config), "Key"), keys.NewFileKeyManager, wire.Bind(new(keys.KeyManager), new(*keys.FileKeyManager)))
 | 
			
		||||
 | 
			
		||||
var storeSet = wire.NewSet(wire.FieldsOf(new(*config.Config), "DB"), store.NewPebbleDB, store.NewPebbleClockStore, wire.Bind(new(store.ClockStore), new(*store.PebbleClockStore)))
 | 
			
		||||
 | 
			
		||||
var pubSubSet = wire.NewSet(wire.FieldsOf(new(*config.Config), "P2P"), p2p.NewBlossomSub, wire.Bind(new(p2p.PubSub), new(*p2p.BlossomSub)))
 | 
			
		||||
 | 
			
		||||
var engineSet = wire.NewSet(nop.NewNopExecutionEngine)
 | 
			
		||||
 | 
			
		||||
var consensusSet = wire.NewSet(wire.FieldsOf(new(*config.Config), "Engine"), master.NewMasterClockConsensusEngine, wire.Bind(new(consensus.ConsensusEngine), new(*master.MasterClockConsensusEngine)))
 | 
			
		||||
var consensusSet = wire.NewSet(wire.FieldsOf(new(*config.Config), "Engine"), master.NewMasterClockConsensusEngine, wire.Bind(
 | 
			
		||||
	new(consensus.ConsensusEngine),
 | 
			
		||||
	new(*master.MasterClockConsensusEngine),
 | 
			
		||||
),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -238,8 +238,33 @@ func (
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txn, err := e.clockStore.NewTransaction()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		e.logger.Error("error while creating transaction", zap.Error(err))
 | 
			
		||||
		return nil, errors.Wrap(err, "confirm latest frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, frame := range committedSet {
 | 
			
		||||
		if err = e.clockStore.PutMasterClockFrame(frame, txn); err != nil {
 | 
			
		||||
			e.logger.Error("error while committing frame", zap.Error(err))
 | 
			
		||||
			return nil, errors.Wrap(err, "confirm latest frame")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Commit(); err != nil {
 | 
			
		||||
		e.logger.Error("error while committing transaction", zap.Error(err))
 | 
			
		||||
		return nil, errors.Wrap(err, "confirm latest frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e.logger.Info("stored frames", zap.Int("frame_count", len(committedSet)))
 | 
			
		||||
 | 
			
		||||
	e.historicFramesMx.Lock()
 | 
			
		||||
 | 
			
		||||
	e.historicFrames = append(e.historicFrames, committedSet...)
 | 
			
		||||
	if len(e.historicFrames) > 256 {
 | 
			
		||||
		e.historicFrames = e.historicFrames[len(e.historicFrames)-256:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e.historicFramesMx.Unlock()
 | 
			
		||||
 | 
			
		||||
	e.setFrame(prev)
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/keys"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/p2p"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/store"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SyncStatusType int
 | 
			
		||||
@ -42,9 +43,9 @@ type MasterClockConsensusEngine struct {
 | 
			
		||||
	engineMx         sync.Mutex
 | 
			
		||||
	seenFramesMx     sync.Mutex
 | 
			
		||||
	historicFramesMx sync.Mutex
 | 
			
		||||
	// for DHT testing, we're only using in memory stores
 | 
			
		||||
	seenFrames     []*protobufs.ClockFrame
 | 
			
		||||
	historicFrames []*protobufs.ClockFrame
 | 
			
		||||
	seenFrames       []*protobufs.ClockFrame
 | 
			
		||||
	historicFrames   []*protobufs.ClockFrame
 | 
			
		||||
	clockStore       store.ClockStore
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ consensus.ConsensusEngine = (*MasterClockConsensusEngine)(nil)
 | 
			
		||||
@ -52,6 +53,7 @@ var _ consensus.ConsensusEngine = (*MasterClockConsensusEngine)(nil)
 | 
			
		||||
func NewMasterClockConsensusEngine(
 | 
			
		||||
	engineConfig *config.EngineConfig,
 | 
			
		||||
	logger *zap.Logger,
 | 
			
		||||
	clockStore store.ClockStore,
 | 
			
		||||
	keyManager keys.KeyManager,
 | 
			
		||||
	pubSub p2p.PubSub,
 | 
			
		||||
) *MasterClockConsensusEngine {
 | 
			
		||||
@ -88,6 +90,7 @@ func NewMasterClockConsensusEngine(
 | 
			
		||||
		input:               seed,
 | 
			
		||||
		lastFrameReceivedAt: time.Time{},
 | 
			
		||||
		syncingStatus:       SyncStatusNotSyncing,
 | 
			
		||||
		clockStore:          clockStore,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if e.filter, err = hex.DecodeString(engineConfig.Filter); err != nil {
 | 
			
		||||
@ -107,8 +110,59 @@ func (e *MasterClockConsensusEngine) Start() <-chan error {
 | 
			
		||||
	e.state = consensus.EngineStateLoading
 | 
			
		||||
	e.logger.Info("syncing last seen state")
 | 
			
		||||
 | 
			
		||||
	latestFrame := e.createGenesisFrame()
 | 
			
		||||
	e.historicFrames = []*protobufs.ClockFrame{latestFrame}
 | 
			
		||||
	latestFrame, err := e.clockStore.GetLatestMasterClockFrame(e.filter)
 | 
			
		||||
	if err != nil && errors.Is(err, store.ErrNotFound) {
 | 
			
		||||
		latestFrame = e.createGenesisFrame()
 | 
			
		||||
		txn, err := e.clockStore.NewTransaction()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = e.clockStore.PutMasterClockFrame(latestFrame, txn); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = txn.Commit(); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	} else if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	} else {
 | 
			
		||||
		e.setFrame(latestFrame)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e.historicFrames = []*protobufs.ClockFrame{}
 | 
			
		||||
 | 
			
		||||
	if latestFrame.FrameNumber != 0 {
 | 
			
		||||
		min := uint64(0)
 | 
			
		||||
		if latestFrame.FrameNumber-255 > min {
 | 
			
		||||
			min = latestFrame.FrameNumber - 255
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		iter, err := e.clockStore.RangeMasterClockFrames(
 | 
			
		||||
			e.filter,
 | 
			
		||||
			min,
 | 
			
		||||
			latestFrame.FrameNumber-1,
 | 
			
		||||
		)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for iter.First(); iter.Valid(); iter.Next() {
 | 
			
		||||
			frame, err := iter.Value()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			e.historicFrames = append(e.historicFrames, frame)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = iter.Close(); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e.historicFrames = append(e.historicFrames, latestFrame)
 | 
			
		||||
 | 
			
		||||
	e.logger.Info("subscribing to pubsub messages")
 | 
			
		||||
	e.pubSub.Subscribe(e.filter, e.handleMessage, true)
 | 
			
		||||
 | 
			
		||||
@ -225,11 +225,35 @@ func (e *MasterClockConsensusEngine) handleClockFramesRequest(
 | 
			
		||||
		zap.Uint64("total_frames", uint64(to-from+1)),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	iter, err := e.clockStore.RangeMasterClockFrames(
 | 
			
		||||
		request.Filter,
 | 
			
		||||
		from,
 | 
			
		||||
		to,
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "handle clock frame request")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := []*protobufs.ClockFrame{}
 | 
			
		||||
 | 
			
		||||
	for iter.First(); iter.Valid(); iter.Next() {
 | 
			
		||||
		frame, err := iter.Value()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.Wrap(err, "handle clock frame request")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		response = append(response, frame)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = iter.Close(); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "handle clock frame request")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := e.publishMessage(channel, &protobufs.ClockFramesResponse{
 | 
			
		||||
		Filter:          request.Filter,
 | 
			
		||||
		FromFrameNumber: request.FromFrameNumber,
 | 
			
		||||
		ToFrameNumber:   to,
 | 
			
		||||
		ClockFrames:     e.historicFrames[from:to],
 | 
			
		||||
		ClockFrames:     response,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "handle clock frame request")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								node/main.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								node/main.go
									
									
									
									
									
								
							@ -16,8 +16,21 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	configDirectory = flag.String("config", "./.config/", "the configuration directory")
 | 
			
		||||
	importPrivKey   = flag.String("import-priv-key", "", "creates a new config using a specific key from the phase one ceremony")
 | 
			
		||||
	configDirectory = flag.String(
 | 
			
		||||
		"config",
 | 
			
		||||
		"./.config/",
 | 
			
		||||
		"the configuration directory",
 | 
			
		||||
	)
 | 
			
		||||
	importPrivKey = flag.String(
 | 
			
		||||
		"import-priv-key",
 | 
			
		||||
		"",
 | 
			
		||||
		"creates a new config using a specific key from the phase one ceremony",
 | 
			
		||||
	)
 | 
			
		||||
	dbConsole = flag.Bool(
 | 
			
		||||
		"db-console",
 | 
			
		||||
		false,
 | 
			
		||||
		"starts the node in database console mode",
 | 
			
		||||
	)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
@ -45,6 +58,16 @@ func main() {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if *dbConsole {
 | 
			
		||||
		console, err := app.NewDBConsole(nodeConfig)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		console.Run()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	node, err := app.NewNode(nodeConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										778
									
								
								node/store/clock.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										778
									
								
								node/store/clock.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,778 @@
 | 
			
		||||
package store
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
 | 
			
		||||
	"github.com/cockroachdb/pebble"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
	"google.golang.org/protobuf/proto"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/tries"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ClockStore interface {
 | 
			
		||||
	NewTransaction() (Transaction, error)
 | 
			
		||||
	GetLatestMasterClockFrame(filter []byte) (*protobufs.ClockFrame, error)
 | 
			
		||||
	GetEarliestMasterClockFrame(filter []byte) (*protobufs.ClockFrame, error)
 | 
			
		||||
	GetMasterClockFrame(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
	) (*protobufs.ClockFrame, error)
 | 
			
		||||
	RangeMasterClockFrames(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		startFrameNumber uint64,
 | 
			
		||||
		endFrameNumber uint64,
 | 
			
		||||
	) (*PebbleMasterClockIterator, error)
 | 
			
		||||
	PutMasterClockFrame(frame *protobufs.ClockFrame, txn Transaction) error
 | 
			
		||||
	GetLatestDataClockFrame(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		proverTrie *tries.RollingFrecencyCritbitTrie,
 | 
			
		||||
	) (*protobufs.ClockFrame, error)
 | 
			
		||||
	GetEarliestDataClockFrame(filter []byte) (*protobufs.ClockFrame, error)
 | 
			
		||||
	GetDataClockFrame(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
	) (*protobufs.ClockFrame, error)
 | 
			
		||||
	RangeDataClockFrames(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		startFrameNumber uint64,
 | 
			
		||||
		endFrameNumber uint64,
 | 
			
		||||
	) (*PebbleClockIterator, error)
 | 
			
		||||
	PutDataClockFrame(
 | 
			
		||||
		frame *protobufs.ClockFrame,
 | 
			
		||||
		proverTrie *tries.RollingFrecencyCritbitTrie,
 | 
			
		||||
		txn Transaction,
 | 
			
		||||
	) error
 | 
			
		||||
	PutCandidateDataClockFrame(
 | 
			
		||||
		parentSelector []byte,
 | 
			
		||||
		distance []byte,
 | 
			
		||||
		selector []byte,
 | 
			
		||||
		frame *protobufs.ClockFrame,
 | 
			
		||||
		txn Transaction,
 | 
			
		||||
	) error
 | 
			
		||||
	GetParentDataClockFrame(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
		parentSelector []byte,
 | 
			
		||||
	) (*protobufs.ClockFrame, error)
 | 
			
		||||
	RangeCandidateDataClockFrames(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		parent []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
	) (*PebbleCandidateClockIterator, error)
 | 
			
		||||
	GetLeadingCandidateDataClockFrame(
 | 
			
		||||
		filter []byte,
 | 
			
		||||
		parent []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
	) (*protobufs.ClockFrame, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleClockStore struct {
 | 
			
		||||
	db     *pebble.DB
 | 
			
		||||
	logger *zap.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ ClockStore = (*PebbleClockStore)(nil)
 | 
			
		||||
 | 
			
		||||
type PebbleMasterClockIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleClockIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleCandidateClockIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Iterator[*protobufs.ClockFrame] = (*PebbleMasterClockIterator)(nil)
 | 
			
		||||
var _ Iterator[*protobufs.ClockFrame] = (*PebbleClockIterator)(nil)
 | 
			
		||||
var _ Iterator[*protobufs.ClockFrame] = (*PebbleCandidateClockIterator)(nil)
 | 
			
		||||
 | 
			
		||||
func (p *PebbleMasterClockIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleMasterClockIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleMasterClockIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleMasterClockIterator) Value() (*protobufs.ClockFrame, error) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key := p.i.Key()
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.ClockFrame{}
 | 
			
		||||
 | 
			
		||||
	frameNumber, filter, err := extractFrameNumberAndFilterFromMasterFrameKey(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get master clock frame iterator value")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frame.FrameNumber = frameNumber
 | 
			
		||||
	frame.Filter = filter
 | 
			
		||||
 | 
			
		||||
	if len(value) < 521 {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			ErrInvalidData,
 | 
			
		||||
			"get master clock frame iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frame.Difficulty = binary.BigEndian.Uint32(value[:4])
 | 
			
		||||
	frame.Input = value[4 : len(value)-516]
 | 
			
		||||
	frame.Output = value[len(value)-516:]
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleMasterClockIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing master clock iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockIterator) Value() (*protobufs.ClockFrame, error) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.ClockFrame{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get clock frame iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing clock frame iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleCandidateClockIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleCandidateClockIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleCandidateClockIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleCandidateClockIterator) Value() (*protobufs.ClockFrame, error) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.ClockFrame{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get candidate clock frame iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleCandidateClockIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing candidate clock frame iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPebbleClockStore(db *pebble.DB, logger *zap.Logger) *PebbleClockStore {
 | 
			
		||||
	return &PebbleClockStore{
 | 
			
		||||
		db,
 | 
			
		||||
		logger,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CLOCK_FRAME = 0x00
 | 
			
		||||
const CLOCK_MASTER_FRAME_DATA = 0x00
 | 
			
		||||
const CLOCK_DATA_FRAME_DATA = 0x01
 | 
			
		||||
const CLOCK_DATA_FRAME_CANDIDATE_DATA = 0x02
 | 
			
		||||
const CLOCK_DATA_FRAME_FRECENCY_DATA = 0x03
 | 
			
		||||
const CLOCK_MASTER_FRAME_INDEX_EARLIEST = 0x10 | CLOCK_MASTER_FRAME_DATA
 | 
			
		||||
const CLOCK_MASTER_FRAME_INDEX_LATEST = 0x20 | CLOCK_MASTER_FRAME_DATA
 | 
			
		||||
const CLOCK_MASTER_FRAME_INDEX_PARENT = 0x30 | CLOCK_MASTER_FRAME_DATA
 | 
			
		||||
const CLOCK_DATA_FRAME_INDEX_EARLIEST = 0x10 | CLOCK_DATA_FRAME_DATA
 | 
			
		||||
const CLOCK_DATA_FRAME_INDEX_LATEST = 0x20 | CLOCK_DATA_FRAME_DATA
 | 
			
		||||
const CLOCK_DATA_FRAME_INDEX_PARENT = 0x30 | CLOCK_DATA_FRAME_DATA
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// DB Keys
 | 
			
		||||
//
 | 
			
		||||
// Keys are structured as:
 | 
			
		||||
// <core type><sub type | index>[<non-index increment>]<segment>
 | 
			
		||||
// Increment necessarily must be full width – elsewise the frame number would
 | 
			
		||||
// easily produce conflicts if filters are stepped by byte:
 | 
			
		||||
// 0x01 || 0xffff == 0x01ff || 0xff
 | 
			
		||||
//
 | 
			
		||||
// Master frames are serialized as output data only, Data frames are raw
 | 
			
		||||
// protobufs for fast disk-to-network output.
 | 
			
		||||
 | 
			
		||||
func clockFrameKey(filter []byte, frameNumber uint64, frameType byte) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, frameType}
 | 
			
		||||
	key = binary.BigEndian.AppendUint64(key, frameNumber)
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockMasterFrameKey(filter []byte, frameNumber uint64) []byte {
 | 
			
		||||
	return clockFrameKey(filter, frameNumber, CLOCK_MASTER_FRAME_DATA)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func extractFrameNumberAndFilterFromMasterFrameKey(
 | 
			
		||||
	key []byte,
 | 
			
		||||
) (uint64, []byte, error) {
 | 
			
		||||
	if len(key) < 11 {
 | 
			
		||||
		return 0, nil, errors.Wrap(
 | 
			
		||||
			ErrInvalidData,
 | 
			
		||||
			"extract frame number and filter from master frame key",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return binary.BigEndian.Uint64(key[2:10]), key[10:], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockDataFrameKey(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) []byte {
 | 
			
		||||
	return clockFrameKey(filter, frameNumber, CLOCK_DATA_FRAME_DATA)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockLatestIndex(filter []byte, frameType byte) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, frameType}
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockMasterLatestIndex(filter []byte) []byte {
 | 
			
		||||
	return clockLatestIndex(filter, CLOCK_MASTER_FRAME_INDEX_LATEST)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockDataLatestIndex(filter []byte) []byte {
 | 
			
		||||
	return clockLatestIndex(filter, CLOCK_DATA_FRAME_INDEX_LATEST)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockEarliestIndex(filter []byte, frameType byte) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, frameType}
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockMasterEarliestIndex(filter []byte) []byte {
 | 
			
		||||
	return clockEarliestIndex(filter, CLOCK_MASTER_FRAME_INDEX_EARLIEST)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockDataEarliestIndex(filter []byte) []byte {
 | 
			
		||||
	return clockEarliestIndex(filter, CLOCK_DATA_FRAME_INDEX_EARLIEST)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockParentIndexKey(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
	selector []byte,
 | 
			
		||||
	frameType byte,
 | 
			
		||||
) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, frameType}
 | 
			
		||||
	key = binary.BigEndian.AppendUint64(key, frameNumber)
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	key = append(key, rightAlign(selector, 32)...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockDataParentIndexKey(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
	selector []byte,
 | 
			
		||||
) []byte {
 | 
			
		||||
	return clockParentIndexKey(
 | 
			
		||||
		filter,
 | 
			
		||||
		frameNumber,
 | 
			
		||||
		selector,
 | 
			
		||||
		CLOCK_DATA_FRAME_INDEX_PARENT,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockDataCandidateFrameKey(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
	parent []byte,
 | 
			
		||||
	distance []byte,
 | 
			
		||||
) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, CLOCK_DATA_FRAME_CANDIDATE_DATA}
 | 
			
		||||
	key = binary.BigEndian.AppendUint64(key, frameNumber)
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	key = append(key, rightAlign(parent, 32)...)
 | 
			
		||||
	key = append(key, rightAlign(distance, 32)...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clockProverTrieKey(filter []byte, frameNumber uint64) []byte {
 | 
			
		||||
	key := []byte{CLOCK_FRAME, CLOCK_DATA_FRAME_FRECENCY_DATA}
 | 
			
		||||
	key = binary.BigEndian.AppendUint64(key, frameNumber)
 | 
			
		||||
	key = append(key, filter...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleClockStore) NewTransaction() (Transaction, error) {
 | 
			
		||||
	return &PebbleTransaction{
 | 
			
		||||
		b: p.db.NewBatch(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEarliestMasterClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetEarliestMasterClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	idxValue, closer, err := p.db.Get(clockMasterEarliestIndex(filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get earliest master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
	frameNumber := binary.BigEndian.Uint64(idxValue)
 | 
			
		||||
	frame, err := p.GetMasterClockFrame(filter, frameNumber)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get earliest master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLatestMasterClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetLatestMasterClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	idxValue, closer, err := p.db.Get(clockMasterLatestIndex(filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
	frameNumber := binary.BigEndian.Uint64(idxValue)
 | 
			
		||||
	frame, err := p.GetMasterClockFrame(filter, frameNumber)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMasterClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetMasterClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	value, closer, err := p.db.Get(clockMasterFrameKey(filter, frameNumber))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
	frame := &protobufs.ClockFrame{}
 | 
			
		||||
	frame.FrameNumber = frameNumber
 | 
			
		||||
	frame.Filter = filter
 | 
			
		||||
	frame.Difficulty = binary.BigEndian.Uint32(value[:4])
 | 
			
		||||
	frame.Input = value[4 : len(value)-516]
 | 
			
		||||
	frame.Output = value[len(value)-516:]
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RangeMasterClockFrames implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) RangeMasterClockFrames(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	startFrameNumber uint64,
 | 
			
		||||
	endFrameNumber uint64,
 | 
			
		||||
) (*PebbleMasterClockIterator, error) {
 | 
			
		||||
	if startFrameNumber > endFrameNumber {
 | 
			
		||||
		temp := endFrameNumber
 | 
			
		||||
		endFrameNumber = startFrameNumber
 | 
			
		||||
		startFrameNumber = temp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: clockMasterFrameKey(filter, startFrameNumber),
 | 
			
		||||
		UpperBound: clockMasterFrameKey(filter, endFrameNumber),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleMasterClockIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PutMasterClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) PutMasterClockFrame(
 | 
			
		||||
	frame *protobufs.ClockFrame,
 | 
			
		||||
	txn Transaction,
 | 
			
		||||
) error {
 | 
			
		||||
	data := binary.BigEndian.AppendUint32([]byte{}, frame.Difficulty)
 | 
			
		||||
	data = append(data, frame.Input...)
 | 
			
		||||
	data = append(data, frame.Output...)
 | 
			
		||||
 | 
			
		||||
	frameNumberBytes := make([]byte, 8)
 | 
			
		||||
	binary.BigEndian.PutUint64(frameNumberBytes, frame.FrameNumber)
 | 
			
		||||
 | 
			
		||||
	if err := txn.Set(
 | 
			
		||||
		clockMasterFrameKey(frame.Filter, frame.FrameNumber),
 | 
			
		||||
		data,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, closer, err := p.db.Get(clockMasterEarliestIndex(frame.Filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if !errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return errors.Wrap(err, "put master clock frame")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = txn.Set(
 | 
			
		||||
			clockMasterEarliestIndex(frame.Filter),
 | 
			
		||||
			frameNumberBytes,
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return errors.Wrap(err, "put master clock frame")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err == nil && closer != nil {
 | 
			
		||||
		closer.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockMasterLatestIndex(frame.Filter),
 | 
			
		||||
		frameNumberBytes,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put master clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetDataClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	value, closer, err := p.db.Get(clockDataFrameKey(filter, frameNumber))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
	frame := &protobufs.ClockFrame{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get data clock frame",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetEarliestDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetEarliestDataClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	idxValue, closer, err := p.db.Get(clockDataEarliestIndex(filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get earliest data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
	frameNumber := binary.BigEndian.Uint64(idxValue)
 | 
			
		||||
	frame, err := p.GetDataClockFrame(filter, frameNumber)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get earliest data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLatestDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetLatestDataClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	proverTrie *tries.RollingFrecencyCritbitTrie,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	idxValue, closer, err := p.db.Get(clockDataLatestIndex(filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frameNumber := binary.BigEndian.Uint64(idxValue)
 | 
			
		||||
	frame, err := p.GetDataClockFrame(filter, frameNumber)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	closer.Close()
 | 
			
		||||
	if proverTrie != nil {
 | 
			
		||||
		trieData, closer, err := p.db.Get(clockProverTrieKey(filter, frameNumber))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrap(err, "get latest data clock frame")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		defer closer.Close()
 | 
			
		||||
 | 
			
		||||
		if err := proverTrie.Deserialize(trieData); err != nil {
 | 
			
		||||
			return nil, errors.Wrap(err, "get latest data clock frame")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLeadingCandidateDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetLeadingCandidateDataClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	parent []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	iter, err := p.RangeCandidateDataClockFrames(filter, parent, frameNumber)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get leading candidate data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !iter.First() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer iter.Close()
 | 
			
		||||
	frame, err := iter.Value()
 | 
			
		||||
	return frame, errors.Wrap(err, "get leading candidate data clock frame")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetParentDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) GetParentDataClockFrame(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
	parentSelector []byte,
 | 
			
		||||
) (*protobufs.ClockFrame, error) {
 | 
			
		||||
	data, closer, err := p.db.Get(
 | 
			
		||||
		clockDataParentIndexKey(filter, frameNumber, parentSelector),
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get parent data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parent := &protobufs.ClockFrame{}
 | 
			
		||||
	if err := proto.Unmarshal(data, parent); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get parent data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if closer != nil {
 | 
			
		||||
		closer.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return parent, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PutCandidateDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) PutCandidateDataClockFrame(
 | 
			
		||||
	parentSelector []byte,
 | 
			
		||||
	distance []byte,
 | 
			
		||||
	selector []byte,
 | 
			
		||||
	frame *protobufs.ClockFrame,
 | 
			
		||||
	txn Transaction,
 | 
			
		||||
) error {
 | 
			
		||||
	data, err := proto.Marshal(frame)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"put candidate data clock frame",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockDataCandidateFrameKey(
 | 
			
		||||
			frame.Filter,
 | 
			
		||||
			frame.FrameNumber,
 | 
			
		||||
			frame.ParentSelector,
 | 
			
		||||
			distance,
 | 
			
		||||
		),
 | 
			
		||||
		data,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put candidate data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockDataParentIndexKey(
 | 
			
		||||
			frame.Filter,
 | 
			
		||||
			frame.FrameNumber,
 | 
			
		||||
			selector,
 | 
			
		||||
		),
 | 
			
		||||
		data,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put candidate data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PutDataClockFrame implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) PutDataClockFrame(
 | 
			
		||||
	frame *protobufs.ClockFrame,
 | 
			
		||||
	proverTrie *tries.RollingFrecencyCritbitTrie,
 | 
			
		||||
	txn Transaction,
 | 
			
		||||
) error {
 | 
			
		||||
	data, err := proto.Marshal(frame)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"put data clock frame",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frameNumberBytes := make([]byte, 8)
 | 
			
		||||
	binary.BigEndian.PutUint64(frameNumberBytes, frame.FrameNumber)
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockDataFrameKey(frame.Filter, frame.FrameNumber),
 | 
			
		||||
		data,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proverData, err := proverTrie.Serialize()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockProverTrieKey(frame.Filter, frame.FrameNumber),
 | 
			
		||||
		proverData,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, closer, err := p.db.Get(clockDataEarliestIndex(frame.Filter))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if !errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = txn.Set(
 | 
			
		||||
			clockDataEarliestIndex(frame.Filter),
 | 
			
		||||
			frameNumberBytes,
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err == nil && closer != nil {
 | 
			
		||||
		closer.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		clockDataLatestIndex(frame.Filter),
 | 
			
		||||
		frameNumberBytes,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put data clock frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RangeCandidateDataClockFrames implements ClockStore.
 | 
			
		||||
// Distance is 32-byte aligned, so we just use a 0x00 * 32 -> 0xff * 32 range
 | 
			
		||||
func (p *PebbleClockStore) RangeCandidateDataClockFrames(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	parent []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) (*PebbleCandidateClockIterator, error) {
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: clockDataCandidateFrameKey(
 | 
			
		||||
			filter,
 | 
			
		||||
			frameNumber,
 | 
			
		||||
			parent,
 | 
			
		||||
			[]byte{
 | 
			
		||||
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			},
 | 
			
		||||
		),
 | 
			
		||||
		UpperBound: clockDataCandidateFrameKey(
 | 
			
		||||
			filter,
 | 
			
		||||
			frameNumber,
 | 
			
		||||
			parent,
 | 
			
		||||
			[]byte{
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
				0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			},
 | 
			
		||||
		),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleCandidateClockIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RangeDataClockFrames implements ClockStore.
 | 
			
		||||
func (p *PebbleClockStore) RangeDataClockFrames(
 | 
			
		||||
	filter []byte,
 | 
			
		||||
	startFrameNumber uint64,
 | 
			
		||||
	endFrameNumber uint64,
 | 
			
		||||
) (*PebbleClockIterator, error) {
 | 
			
		||||
	if startFrameNumber > endFrameNumber {
 | 
			
		||||
		temp := endFrameNumber
 | 
			
		||||
		endFrameNumber = startFrameNumber
 | 
			
		||||
		startFrameNumber = temp
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: clockDataFrameKey(filter, startFrameNumber),
 | 
			
		||||
		UpperBound: clockDataFrameKey(filter, endFrameNumber),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleClockIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								node/store/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								node/store/errors.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
package store
 | 
			
		||||
 | 
			
		||||
import "errors"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrNotFound    = errors.New("item not found")
 | 
			
		||||
	ErrInvalidData = errors.New("invalid data")
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										11
									
								
								node/store/iterator.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								node/store/iterator.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
package store
 | 
			
		||||
 | 
			
		||||
import "google.golang.org/protobuf/proto"
 | 
			
		||||
 | 
			
		||||
type Iterator[T proto.Message] interface {
 | 
			
		||||
	First() bool
 | 
			
		||||
	Next() bool
 | 
			
		||||
	Valid() bool
 | 
			
		||||
	Value() (T, error)
 | 
			
		||||
	Close() error
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										531
									
								
								node/store/key.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										531
									
								
								node/store/key.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,531 @@
 | 
			
		||||
package store
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
 | 
			
		||||
	"github.com/cockroachdb/pebble"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
	"google.golang.org/protobuf/proto"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KeyStore interface {
 | 
			
		||||
	NewTransaction() (Transaction, error)
 | 
			
		||||
	StageProvingKey(provingKey *protobufs.ProvingKeyAnnouncement) error
 | 
			
		||||
	IncludeProvingKey(
 | 
			
		||||
		inclusionCommitment *protobufs.InclusionCommitment,
 | 
			
		||||
		txn Transaction,
 | 
			
		||||
	) error
 | 
			
		||||
	GetStagedProvingKey(
 | 
			
		||||
		provingKey []byte,
 | 
			
		||||
	) (*protobufs.ProvingKeyAnnouncement, error)
 | 
			
		||||
	GetProvingKey(provingKey []byte) (*protobufs.InclusionCommitment, error)
 | 
			
		||||
	GetKeyBundle(
 | 
			
		||||
		provingKey []byte,
 | 
			
		||||
		frameNumber uint64,
 | 
			
		||||
	) (*protobufs.InclusionCommitment, error)
 | 
			
		||||
	GetLatestKeyBundle(provingKey []byte) (*protobufs.InclusionCommitment, error)
 | 
			
		||||
	PutKeyBundle(
 | 
			
		||||
		provingKey []byte,
 | 
			
		||||
		keyBundleCommitment *protobufs.InclusionCommitment,
 | 
			
		||||
		txn Transaction,
 | 
			
		||||
	) error
 | 
			
		||||
	RangeProvingKeys() (*PebbleProvingKeyIterator, error)
 | 
			
		||||
	RangeStagedProvingKeys() (*PebbleStagedProvingKeyIterator, error)
 | 
			
		||||
	RangeKeyBundleKeys(provingKey []byte) (*PebbleKeyBundleIterator, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleKeyStore struct {
 | 
			
		||||
	db     *pebble.DB
 | 
			
		||||
	logger *zap.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleProvingKeyIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleStagedProvingKeyIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleKeyBundleIterator struct {
 | 
			
		||||
	i *pebble.Iterator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var pki = (*PebbleProvingKeyIterator)(nil)
 | 
			
		||||
var spki = (*PebbleStagedProvingKeyIterator)(nil)
 | 
			
		||||
var kbi = (*PebbleKeyBundleIterator)(nil)
 | 
			
		||||
var _ Iterator[*protobufs.InclusionCommitment] = pki
 | 
			
		||||
var _ Iterator[*protobufs.ProvingKeyAnnouncement] = spki
 | 
			
		||||
var _ Iterator[*protobufs.InclusionCommitment] = kbi
 | 
			
		||||
var _ KeyStore = (*PebbleKeyStore)(nil)
 | 
			
		||||
 | 
			
		||||
func (p *PebbleProvingKeyIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleProvingKeyIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleProvingKeyIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleProvingKeyIterator) Value() (
 | 
			
		||||
	*protobufs.InclusionCommitment,
 | 
			
		||||
	error,
 | 
			
		||||
) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.InclusionCommitment{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get proving key iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleProvingKeyIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleStagedProvingKeyIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleStagedProvingKeyIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleStagedProvingKeyIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleStagedProvingKeyIterator) Value() (
 | 
			
		||||
	*protobufs.ProvingKeyAnnouncement,
 | 
			
		||||
	error,
 | 
			
		||||
) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.ProvingKeyAnnouncement{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get staged proving key iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleStagedProvingKeyIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyBundleIterator) First() bool {
 | 
			
		||||
	return p.i.First()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyBundleIterator) Next() bool {
 | 
			
		||||
	return p.i.Next()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyBundleIterator) Valid() bool {
 | 
			
		||||
	return p.i.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyBundleIterator) Value() (
 | 
			
		||||
	*protobufs.InclusionCommitment,
 | 
			
		||||
	error,
 | 
			
		||||
) {
 | 
			
		||||
	if !p.i.Valid() {
 | 
			
		||||
		return nil, ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.i.Value()
 | 
			
		||||
	frame := &protobufs.InclusionCommitment{}
 | 
			
		||||
	if err := proto.Unmarshal(value, frame); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get key bundle iterator value",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return frame, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyBundleIterator) Close() error {
 | 
			
		||||
	return errors.Wrap(p.i.Close(), "closing iterator")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPebbleKeyStore(db *pebble.DB, logger *zap.Logger) *PebbleKeyStore {
 | 
			
		||||
	return &PebbleKeyStore{
 | 
			
		||||
		db,
 | 
			
		||||
		logger,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	PROVING_KEY               = 0x01
 | 
			
		||||
	PROVING_KEY_STAGED        = 0x02
 | 
			
		||||
	KEY_BUNDLE                = 0x03
 | 
			
		||||
	KEY_DATA                  = 0x00
 | 
			
		||||
	KEY_BUNDLE_INDEX_EARLIEST = 0x10
 | 
			
		||||
	KEY_BUNDLE_INDEX_LATEST   = 0x20
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func provingKeyKey(provingKey []byte) []byte {
 | 
			
		||||
	key := []byte{PROVING_KEY, KEY_DATA}
 | 
			
		||||
	key = append(key, provingKey...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stagedProvingKeyKey(provingKey []byte) []byte {
 | 
			
		||||
	key := []byte{PROVING_KEY_STAGED, KEY_DATA}
 | 
			
		||||
	key = append(key, provingKey...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func keyBundleKey(provingKey []byte, frameNumber uint64) []byte {
 | 
			
		||||
	key := []byte{KEY_BUNDLE, KEY_DATA}
 | 
			
		||||
	key = append(key, provingKey...)
 | 
			
		||||
	key = binary.BigEndian.AppendUint64(key, frameNumber)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func keyBundleLatestKey(provingKey []byte) []byte {
 | 
			
		||||
	key := []byte{KEY_BUNDLE, KEY_BUNDLE_INDEX_LATEST}
 | 
			
		||||
	key = append(key, provingKey...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func keyBundleEarliestKey(provingKey []byte) []byte {
 | 
			
		||||
	key := []byte{KEY_BUNDLE, KEY_BUNDLE_INDEX_EARLIEST}
 | 
			
		||||
	key = append(key, provingKey...)
 | 
			
		||||
	return key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyStore) NewTransaction() (Transaction, error) {
 | 
			
		||||
	return &PebbleTransaction{
 | 
			
		||||
		b: p.db.NewBatch(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stages a proving key for later inclusion on proof of meaningful work.
 | 
			
		||||
// Does not verify, upstream callers must verify.
 | 
			
		||||
func (p *PebbleKeyStore) StageProvingKey(
 | 
			
		||||
	provingKey *protobufs.ProvingKeyAnnouncement,
 | 
			
		||||
) error {
 | 
			
		||||
	data, err := proto.Marshal(provingKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "stage proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = p.db.Set(
 | 
			
		||||
		stagedProvingKeyKey(provingKey.PublicKey()),
 | 
			
		||||
		data,
 | 
			
		||||
		&pebble.WriteOptions{
 | 
			
		||||
			Sync: true,
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "stage proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Includes a proving key with an inclusion commitment. If a proving key is
 | 
			
		||||
// staged, promotes it by including it in the primary key store and deletes the
 | 
			
		||||
// staged key.
 | 
			
		||||
func (p *PebbleKeyStore) IncludeProvingKey(
 | 
			
		||||
	inclusionCommitment *protobufs.InclusionCommitment,
 | 
			
		||||
	txn Transaction,
 | 
			
		||||
) error {
 | 
			
		||||
	provingKey := &protobufs.ProvingKeyAnnouncement{}
 | 
			
		||||
	if err := proto.Unmarshal(inclusionCommitment.Data, provingKey); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "include proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := provingKey.Verify(); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "include proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := proto.Marshal(inclusionCommitment)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "include proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txn.Set(
 | 
			
		||||
		provingKeyKey(provingKey.PublicKey()),
 | 
			
		||||
		data,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	staged, closer, err := p.db.Get(stagedProvingKeyKey(provingKey.PublicKey()))
 | 
			
		||||
	if err != nil && !errors.Is(err, ErrNotFound) {
 | 
			
		||||
		return errors.Wrap(err, "include proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if staged != nil {
 | 
			
		||||
		if err := txn.Delete(
 | 
			
		||||
			stagedProvingKeyKey(provingKey.PublicKey()),
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return errors.Wrap(err, "include proving key")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err := closer.Close(); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "include proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyStore) GetStagedProvingKey(
 | 
			
		||||
	provingKey []byte,
 | 
			
		||||
) (*protobufs.ProvingKeyAnnouncement, error) {
 | 
			
		||||
	data, closer, err := p.db.Get(stagedProvingKeyKey(provingKey))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get staged proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stagedKey := &protobufs.ProvingKeyAnnouncement{}
 | 
			
		||||
	if err = proto.Unmarshal(data, stagedKey); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get staged proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := closer.Close(); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get staged proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stagedKey, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns the latest key bundle for a given proving key.
 | 
			
		||||
func (p *PebbleKeyStore) GetLatestKeyBundle(
 | 
			
		||||
	provingKey []byte,
 | 
			
		||||
) (*protobufs.InclusionCommitment, error) {
 | 
			
		||||
	value, closer, err := p.db.Get(keyBundleLatestKey(provingKey))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest key bundle")
 | 
			
		||||
	}
 | 
			
		||||
	frameNumber := binary.BigEndian.Uint64(value)
 | 
			
		||||
 | 
			
		||||
	if err := closer.Close(); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest key bundle")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value, closer, err = p.db.Get(keyBundleKey(provingKey, frameNumber))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get latest key bundle")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
 | 
			
		||||
	announcement := &protobufs.InclusionCommitment{}
 | 
			
		||||
	if err := proto.Unmarshal(value, announcement); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get latest key bundle",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return announcement, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieves the specific key bundle included at a given frame number.
 | 
			
		||||
func (p *PebbleKeyStore) GetKeyBundle(
 | 
			
		||||
	provingKey []byte,
 | 
			
		||||
	frameNumber uint64,
 | 
			
		||||
) (*protobufs.InclusionCommitment, error) {
 | 
			
		||||
	value, closer, err := p.db.Get(keyBundleKey(provingKey, frameNumber))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get key bundle")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
 | 
			
		||||
	announcement := &protobufs.InclusionCommitment{}
 | 
			
		||||
	if err := proto.Unmarshal(value, announcement); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get key bundle",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return announcement, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieves an included proving key, returns ErrNotFound if not present.
 | 
			
		||||
func (p *PebbleKeyStore) GetProvingKey(
 | 
			
		||||
	provingKey []byte,
 | 
			
		||||
) (*protobufs.InclusionCommitment, error) {
 | 
			
		||||
	value, closer, err := p.db.Get(provingKeyKey(provingKey))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return nil, ErrNotFound
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil, errors.Wrap(err, "get proving key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer closer.Close()
 | 
			
		||||
 | 
			
		||||
	announcement := &protobufs.InclusionCommitment{}
 | 
			
		||||
	if err := proto.Unmarshal(value, announcement); err != nil {
 | 
			
		||||
		return nil, errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"get proving key",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return announcement, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Inserts a key bundle with inclusion commitment. Does not verify, upstream
 | 
			
		||||
// callers must perform the verification.
 | 
			
		||||
func (p *PebbleKeyStore) PutKeyBundle(
 | 
			
		||||
	provingKey []byte,
 | 
			
		||||
	keyBundle *protobufs.InclusionCommitment,
 | 
			
		||||
	txn Transaction,
 | 
			
		||||
) error {
 | 
			
		||||
	data, err := proto.Marshal(keyBundle)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(
 | 
			
		||||
			errors.Wrap(err, ErrInvalidData.Error()),
 | 
			
		||||
			"put key bundle",
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	frameNumberBytes := make([]byte, 8)
 | 
			
		||||
	binary.BigEndian.PutUint64(frameNumberBytes, keyBundle.FrameNumber)
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		keyBundleKey(provingKey, keyBundle.FrameNumber),
 | 
			
		||||
		data,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put key bundle")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, closer, err := p.db.Get(keyBundleEarliestKey(provingKey))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if !errors.Is(err, pebble.ErrNotFound) {
 | 
			
		||||
			return errors.Wrap(err, "put key bundle")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = txn.Set(
 | 
			
		||||
			keyBundleEarliestKey(provingKey),
 | 
			
		||||
			frameNumberBytes,
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return errors.Wrap(err, "put key bundle")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err == nil && closer != nil {
 | 
			
		||||
		closer.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = txn.Set(
 | 
			
		||||
		keyBundleLatestKey(provingKey),
 | 
			
		||||
		frameNumberBytes,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return errors.Wrap(err, "put key bundle")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyStore) RangeProvingKeys() (*PebbleProvingKeyIterator, error) {
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: provingKeyKey([]byte{
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00,
 | 
			
		||||
		}),
 | 
			
		||||
		UpperBound: provingKeyKey([]byte{
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff,
 | 
			
		||||
		}),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleProvingKeyIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyStore) RangeStagedProvingKeys() (
 | 
			
		||||
	*PebbleStagedProvingKeyIterator,
 | 
			
		||||
	error,
 | 
			
		||||
) {
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: stagedProvingKeyKey([]byte{
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
			0x00,
 | 
			
		||||
		}),
 | 
			
		||||
		UpperBound: stagedProvingKeyKey([]byte{
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 | 
			
		||||
			0xff,
 | 
			
		||||
		}),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleStagedProvingKeyIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *PebbleKeyStore) RangeKeyBundleKeys(provingKey []byte) (
 | 
			
		||||
	*PebbleKeyBundleIterator,
 | 
			
		||||
	error,
 | 
			
		||||
) {
 | 
			
		||||
	iter := p.db.NewIter(&pebble.IterOptions{
 | 
			
		||||
		LowerBound: keyBundleKey(provingKey, 0),
 | 
			
		||||
		UpperBound: keyBundleKey(provingKey, 0xffffffffffffffff),
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return &PebbleKeyBundleIterator{i: iter}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								node/store/pebble.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								node/store/pebble.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
package store
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/cockroachdb/pebble"
 | 
			
		||||
	"source.quilibrium.com/quilibrium/monorepo/node/config"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewPebbleDB(config *config.DBConfig) *pebble.DB {
 | 
			
		||||
	db, err := pebble.Open(config.Path, &pebble.Options{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return db
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Transaction interface {
 | 
			
		||||
	Set(key []byte, value []byte) error
 | 
			
		||||
	Commit() error
 | 
			
		||||
	Delete(key []byte) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PebbleTransaction struct {
 | 
			
		||||
	b *pebble.Batch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *PebbleTransaction) Set(key []byte, value []byte) error {
 | 
			
		||||
	return t.b.Set(key, value, &pebble.WriteOptions{Sync: true})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *PebbleTransaction) Commit() error {
 | 
			
		||||
	return t.b.Commit(&pebble.WriteOptions{Sync: true})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *PebbleTransaction) Delete(key []byte) error {
 | 
			
		||||
	return t.b.Delete(key, &pebble.WriteOptions{Sync: true})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Transaction = (*PebbleTransaction)(nil)
 | 
			
		||||
 | 
			
		||||
func rightAlign(data []byte, size int) []byte {
 | 
			
		||||
	l := len(data)
 | 
			
		||||
 | 
			
		||||
	if l == size {
 | 
			
		||||
		return data
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l > size {
 | 
			
		||||
		return data[l-size:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pad := make([]byte, size)
 | 
			
		||||
	copy(pad[size-l:], data)
 | 
			
		||||
	return pad
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user