Created
October 2, 2020 16:57
-
-
Save enriquefynn/f261edee578eba1b80fa4c26e408ca2a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/binary" | |
"errors" | |
"fmt" | |
"github.com/sirupsen/logrus" | |
"github.com/tendermint/iavl" | |
dbm "github.com/tendermint/tm-db" | |
"github.com/tendermint/tendermint/abci/example/code" | |
abci "github.com/tendermint/tendermint/abci/types" | |
"github.com/tendermint/tendermint/version" | |
) | |
var _ abci.Application = (*Application)(nil) | |
const ( | |
snapshotFrequency = 10 | |
cacheSize = 4294967296 // 4Gb | |
prepopulateLimit = 10000000 | |
) | |
type Application struct { | |
abci.BaseApplication | |
store *iavl.MutableTree | |
} | |
func NewApplication(dataDir, logPath string, prepopulate int, snapshotChunkSize uint64) *Application { | |
// Set up IAVL store | |
// db, err := dbm.NewGoLevelDB("iavlapp", dataDir) | |
db := dbm.NewDB("marolapp", dbm.RocksDBBackend, dataDir) | |
store, err := iavl.NewMutableTree(db, cacheSize) | |
if err != nil { | |
panic(err) | |
} | |
_, err = store.Load() | |
if err != nil { | |
panic(err) | |
} | |
return &Application{ | |
store: store, | |
} | |
} | |
func (app *Application) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo) { | |
return abci.ResponseInfo{ | |
Data: fmt.Sprintf(`{"size":%v}`, app.store.Size()), | |
Version: version.ABCIVersion, | |
AppVersion: 1, | |
LastBlockHeight: app.store.Version(), | |
LastBlockAppHash: app.store.Hash(), | |
} | |
} | |
// parseTx parses a tx in 'key=value' format into a key and value. | |
func parseTx(tx []byte) ([]byte, []byte, error) { | |
keySize := binary.LittleEndian.Uint16(tx[:2]) | |
if len(tx) < int(keySize) { | |
return nil, nil, errors.New("key cannot be empty") | |
} | |
key, value := tx[2:keySize+2], tx[keySize+2:] | |
return key, value, nil | |
} | |
func (app *Application) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { | |
_, _, err := parseTx(req.Tx) | |
if err != nil { | |
logrus.Infof("ERROR: %v", err) | |
panic(err) | |
} | |
return abci.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1} | |
} | |
func (app *Application) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { | |
key, value, err := parseTx(req.Tx) | |
// logrus.Infof("KEY: %x, VALUE: %x", key, value) | |
if err != nil { | |
panic(err) | |
} | |
app.store.Set(key, value) | |
return abci.ResponseDeliverTx{Code: code.CodeTypeOK} | |
} | |
func (app *Application) Commit() abci.ResponseCommit { | |
hash, _, _ := app.store.SaveVersion() | |
return abci.ResponseCommit{Data: hash} | |
} | |
func (app *Application) Query(req abci.RequestQuery) abci.ResponseQuery { | |
_, value := app.store.Get(req.Data) | |
return abci.ResponseQuery{ | |
Height: app.store.Version(), | |
Key: req.Data, | |
Value: value, | |
} | |
} | |
func (app *Application) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock { | |
// reset valset changes | |
return abci.ResponseBeginBlock{} | |
} | |
func (app *Application) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock { | |
return abci.ResponseEndBlock{} | |
} | |
func (app *Application) InitChain(abci.RequestInitChain) abci.ResponseInitChain { | |
return abci.ResponseInitChain{} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"os" | |
"os/signal" | |
"path/filepath" | |
"syscall" | |
"github.com/apex/log" | |
"github.com/spf13/viper" | |
abci "github.com/tendermint/tendermint/abci/types" | |
tmCfg "github.com/tendermint/tendermint/config" | |
tmflags "github.com/tendermint/tendermint/libs/cli/flags" | |
tmLogger "github.com/tendermint/tendermint/libs/log" | |
tmNode "github.com/tendermint/tendermint/node" | |
"github.com/tendermint/tendermint/p2p" | |
"github.com/tendermint/tendermint/privval" | |
"github.com/tendermint/tendermint/proxy" | |
) | |
var storagePath string | |
var tmConfigFile string | |
var treeTypeArg string | |
var validatorKeyPath string | |
var validatorStatePath string | |
var rpcServers string | |
var trustHeight int64 | |
var trustHash string | |
var prepopulate int | |
var byzantineBehaviourString string | |
var byzantineBehaviour int | |
var chunkCapacity int | |
func init() { | |
} | |
func main() { | |
app := NewApplication(storagePath, "/tmp/tree_logs_"+treeTypeArg, prepopulate, uint64(100*chunkCapacity)) | |
// logger := tmLogger.NewTMLogger(tmLogger.NewSyncWriter(os.Stdout)) | |
node, err := newTendermint(app, tmConfigFile) | |
if err != nil { | |
fmt.Fprintf(os.Stderr, "%v", err) | |
os.Exit(2) | |
} | |
node.Start() | |
// Handle Ctr-c | |
c := make(chan os.Signal, 1) | |
signal.Notify(c, os.Interrupt, syscall.SIGTERM) | |
<-c | |
node.Stop() | |
node.Wait() | |
log.Infof("Exiting app") | |
os.Exit(0) | |
} | |
func newTendermint(app abci.Application, configFile string) (*tmNode.Node, error) { | |
// read config | |
config := tmCfg.DefaultConfig() | |
config.RootDir = filepath.Dir(filepath.Dir(configFile)) | |
viper.SetConfigFile(configFile) | |
if err := viper.ReadInConfig(); err != nil { | |
return nil, fmt.Errorf("viper failed to read config file: %w", err) | |
} | |
if err := viper.Unmarshal(config); err != nil { | |
return nil, fmt.Errorf("viper failed to unmarshal config: %w", err) | |
} | |
if err := config.ValidateBasic(); err != nil { | |
return nil, fmt.Errorf("config is invalid: %w", err) | |
} | |
// create logger | |
logger := tmLogger.NewTMLogger(tmLogger.NewSyncWriter(os.Stdout)) | |
var err error | |
logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, tmCfg.DefaultLogLevel()) | |
if err != nil { | |
return nil, fmt.Errorf("failed to parse log level: %w", err) | |
} | |
// read private validator | |
pv := privval.LoadFilePV(validatorKeyPath, validatorStatePath) | |
// read node key | |
nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) | |
if err != nil { | |
return nil, fmt.Errorf("failed to load node's key: %w", err) | |
} | |
// create node | |
node, err := tmNode.NewNode( | |
config, | |
pv, | |
nodeKey, | |
proxy.NewLocalClientCreator(app), | |
tmNode.DefaultGenesisDocProviderFunc(config), | |
tmNode.DefaultDBProvider, | |
tmNode.DefaultMetricsProvider(config.Instrumentation), | |
logger) | |
if err != nil { | |
return nil, fmt.Errorf("failed to create new Tendermint node: %w", err) | |
} | |
return node, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment