Skip to content

Commit

Permalink
Merge pull request #47 from kaspa-live/about
Browse files Browse the repository at this point in the history
Add version information for all application tiers and for the embedded kaspad
  • Loading branch information
tiram88 authored Aug 12, 2022
2 parents f7d5bdf + 63fa146 commit 8bf5a74
Show file tree
Hide file tree
Showing 21 changed files with 337 additions and 38 deletions.
13 changes: 13 additions & 0 deletions api/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ server.get('/blockHashesByIds', async (request, response) =>{
}
});

server.get('/appConfig', async (request, response) => {
try {
await database.withClient(async client => {
const appConfig = await database.getAppConfig(client);
response.send(JSON.stringify(appConfig));
});
return;
} catch (error) {
response.status(400).send(`invalid input: ${error}`);
return;
}
});

if (protocol === "https") {
https
.createServer(
Expand Down
21 changes: 19 additions & 2 deletions api/src/database.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pg from "pg";
import {Block, BlockHashById, BlocksAndEdgesAndHeightGroups, Edge, HeightGroup} from "./model";
import {AppConfig, Block, BlockHashById, BlocksAndEdgesAndHeightGroups, Edge, HeightGroup} from "./model";
import { packageVersion } from "./version.js";

export default class Database {
private pool: pg.Pool;
Expand Down Expand Up @@ -139,5 +140,21 @@ export default class Database {
throw new Error(`DAA scores ${daaScore} do not exist`);
}
return parseInt(result.rows[0].height);
}
}

getAppConfig = async (client: pg.PoolClient): Promise<AppConfig> => {
const result = await client.query('SELECT * FROM app_config');
if (result.rows.length === 0) {
return {
kaspadVersion: "",
processingVersion: "",
apiVersion: "",
}
}
return {
kaspadVersion: result.rows[0].kaspad_version,
processingVersion: result.rows[0].processing_version,
apiVersion: packageVersion,
};
}
}
6 changes: 6 additions & 0 deletions api/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ export type BlockHashById = {
id: number,
hash: string,
};

export type AppConfig = {
kaspadVersion: string,
processingVersion: string,
apiVersion: string,
}
12 changes: 12 additions & 0 deletions api/src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import fs from "fs";

const getPackageVersion = (): string => {
const packagejson:any = JSON.parse(fs.readFileSync('package.json', 'utf8'))
return packagejson.version;
};

const packageVersion = getPackageVersion();

export {
packageVersion
};
23 changes: 23 additions & 0 deletions processing/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,29 @@ func (db *Database) InsertOrUpdateHeightGroup(databaseTransaction *pg.Tx, height
return nil
}

// GetAppConfig returns the stored app config.
// Returns an error if no app config does exist in the database.
func (db *Database) GetAppConfig(databaseTransaction *pg.Tx) (*model.AppConfig, error) {
result := new(model.AppConfig)
_, err := databaseTransaction.QueryOne(result, "SELECT * FROM appConfig")
if err != nil {
return nil, err
}
return result, nil
}

// StoreAppConfig stores an AppConfig in the database.
// ID is forced to true, this is the only accepted value by the database.
// Consequently, the database stores at most one AppConfig row.
func (db *Database) StoreAppConfig(databaseTransaction *pg.Tx, appConfig *model.AppConfig) error {
appConfig.ID = true
_, err := databaseTransaction.Model(appConfig).OnConflict("(id) DO UPDATE SET kaspad_version = EXCLUDED.kaspad_version, processing_version = EXCLUDED.processing_version").Insert()
if err != nil {
return err
}
return nil
}

func (db *Database) Clear(databaseTransaction *pg.Tx) error {
db.clearCache()
_, err := databaseTransaction.Exec("TRUNCATE TABLE blocks")
Expand Down
7 changes: 7 additions & 0 deletions processing/database/migrations/000006_app_config.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE app_config
(
id BOOLEAN PRIMARY KEY DEFAULT TRUE,
kaspad_version TEXT NOT NULL,
processing_version TEXT NOT NULL,
CONSTRAINT unique_row CHECK (id)
);
9 changes: 9 additions & 0 deletions processing/database/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,12 @@ type HeightGroup struct {
Height uint64 `pg:"height,use_zero"`
Size uint32 `pg:"size,use_zero"`
}

type AppConfig struct {
//lint:ignore U1000 This field is used by gp-pg reflexively
tableName struct{} `pg:"app_config,alias:app_config"`

ID bool `pg:"id,pk"`
KaspadVersion string `pg:"kaspad_version"`
ProcessingVersion string `pg:"processing_version"`
}
10 changes: 10 additions & 0 deletions processing/infrastructure/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (

"github.com/jessevdk/go-flags"
"github.com/kaspa-live/kaspa-graph-inspector/processing/infrastructure/logging"
versionPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/version"
kaspaConfigPackage "github.com/kaspanet/kaspad/infrastructure/config"
kaspaLogger "github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/version"
"github.com/pkg/errors"
)

Expand All @@ -29,6 +31,7 @@ var (
)

type Flags struct {
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
AppDir string `short:"b" long:"appdir" description:"Directory to store data"`
LogDir string `long:"logdir" description:"Directory to log output."`
DatabaseConnectionString string `long:"connection-string" description:"Connection string for PostgrSQL database to connect to. Should be of the form: postgres://<username>:<password>@<host>:<port>/<database name>"`
Expand Down Expand Up @@ -86,6 +89,13 @@ func LoadConfig() (*Config, error) {
Flags: cfgFlags,
}

// Show the version and exit if the version flag was specified.
if cfg.ShowVersion {
fmt.Println(appName, "version", versionPackage.Version())
fmt.Println("kaspad version", version.Version())
os.Exit(0)
}

if cfg.DatabaseConnectionString == "" {
return nil, errors.Errorf("--connection-string is required.")
}
Expand Down
11 changes: 11 additions & 0 deletions processing/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
package main

import (
"fmt"

databasePackage "github.com/kaspa-live/kaspa-graph-inspector/processing/database"
configPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/infrastructure/config"
"github.com/kaspa-live/kaspa-graph-inspector/processing/infrastructure/logging"
kaspadPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/kaspad"
processingPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/processing"
versionPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/version"
"github.com/kaspanet/kaspad/version"
)

func main() {
fmt.Println("=================================================")
fmt.Println("Kaspa Graph Inspector (KGI) - Processing Tier")
fmt.Println("=================================================")

config, err := configPackage.LoadConfig()
if err != nil {
logging.LogErrorAndExit("Could not parse command line arguments.\n%s", err)
}

logging.Logger().Infof("Application version %s", versionPackage.Version())
logging.Logger().Infof("Embedded kaspad version %s", version.Version())

database, err := databasePackage.Connect(config.DatabaseConnectionString)
if err != nil {
logging.LogErrorAndExit("Could not connect to database %s: %s", config.DatabaseConnectionString, err)
Expand Down
38 changes: 31 additions & 7 deletions processing/processing/processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,48 @@ import (
"github.com/kaspa-live/kaspa-graph-inspector/processing/infrastructure/tools"
kaspadPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/kaspad"
"github.com/kaspa-live/kaspa-graph-inspector/processing/processing/batch"
versionPackage "github.com/kaspa-live/kaspa-graph-inspector/processing/version"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/version"
"github.com/pkg/errors"
)

var log = logging.Logger()

type Processing struct {
config *configPackage.Config
database *databasePackage.Database
kaspad *kaspadPackage.Kaspad
config *configPackage.Config
database *databasePackage.Database
kaspad *kaspadPackage.Kaspad
appConfig *model.AppConfig

sync.Mutex
}

func NewProcessing(config *configPackage.Config,
database *databasePackage.Database, kaspad *kaspadPackage.Kaspad) (*Processing, error) {

appConfig := &model.AppConfig{
ID: true,
KaspadVersion: version.Version(),
ProcessingVersion: versionPackage.Version(),
}

processing := &Processing{
config: config,
database: database,
kaspad: kaspad,
config: config,
database: database,
kaspad: kaspad,
appConfig: appConfig,
}
processing.initConsensusEventsHandler()

err := processing.ResyncDatabase()
err := processing.RegisterAppConfig()
if err != nil {
return nil, err
}

err = processing.ResyncDatabase()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -71,6 +86,15 @@ func (p *Processing) initConsensusEventsHandler() {
}()
}

func (p *Processing) RegisterAppConfig() error {
return p.database.RunInTransaction(func(databaseTransaction *pg.Tx) error {
log.Infof("Registering app config")
defer log.Infof("Finished registering app config")

return p.database.StoreAppConfig(databaseTransaction, p.appConfig)
})
}

func (p *Processing) ResyncDatabase() error {
p.Lock()
defer p.Unlock()
Expand Down
52 changes: 52 additions & 0 deletions processing/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package version

import (
"fmt"
"strings"
)

// validCharacters is a list of characters valid in the appBuild string
const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"

const (
appMajor uint = 0
appMinor uint = 1
appPatch uint = 17
)

// appBuild is defined as a variable so it can be overridden during the build
// process with '-ldflags "-X github.com/kaspanet/kaspad/version.appBuild=foo"' if needed.
// It MUST only contain characters from validCharacters.
var appBuild string

var version = "" // string used for memoization of version

func init() {
if version == "" {
// Start with the major, minor, and patch versions.
version = fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch)

// Append build metadata if there is any.
// Panic if any invalid characters are encountered
if appBuild != "" {
checkAppBuild(appBuild)

version = fmt.Sprintf("%s-%s", version, appBuild)
}
}
}

// Version returns the application version as a properly formed string
func Version() string {
return version
}

// checkAppBuild verifies that appBuild does not contain any characters outside of validCharacters.
// In case of any invalid characters checkAppBuild panics
func checkAppBuild(appBuild string) {
for _, r := range appBuild {
if !strings.ContainsRune(validCharacters, r) {
panic(fmt.Errorf("appBuild string (%s) contains forbidden characters. Only alphanumeric characters and dashes are allowed", appBuild))
}
}
}
12 changes: 9 additions & 3 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { createTheme, ThemeProvider, StyledEngineProvider } from '@mui/material';
import Dag from "./dag/Dag";
import {useState, useRef} from "react";
import { useState, useRef } from "react";
import BlockInformationPanel from "./components/panel/BlockInformation";
import Canvas from "./components/Canvas";
import Sidebar from './components/sidebar/Sidebar';
import {BlockInformation} from "./model/BlockInformation";
import { AppConfig } from './model/AppConfig';
import { BlockInformation } from "./model/BlockInformation";
import SlideItem from './components/base/SlideItem';
import AppContainer from './components/base/AppContainer';
import GlobalStyles from '@mui/material/GlobalStyles';

const App = ({interactive}: {interactive: boolean}) => {
const [blockInformationState, setBlockInformationState] = useState<BlockInformation | null>(null);
const [appConfigState, setAppConfig] = useState<AppConfig | null>(null);
const [wasBlockSetState, setWasBlockSetState] = useState(false);
const [wasBlockInformationPanelCloseRequested, setBlockInformationPanelCloseRequested] = useState(false);
const [isBlockInformationPanelOpenState, setBlockInformationPanelOpenState] = useState(false);
Expand All @@ -36,6 +38,10 @@ const App = ({interactive}: {interactive: boolean}) => {
setWasBlockSetState(wasBlockSetState || blockInformation !== null);
});

dag.setAppConfigChangedListener(appConfig => {
setAppConfig(appConfig);
});

dag.setBlockClickedListener(block => {
setBlockInformationPanelOpenState(!!block);
setBlockInformationPanelCloseRequested(!block);
Expand Down Expand Up @@ -65,7 +71,7 @@ const App = ({interactive}: {interactive: boolean}) => {
ref={appContainerRef}
>
<Canvas dag={dag}/>
<Sidebar dag={dag}/>
<Sidebar dag={dag} appConfig={appConfigState}/>

{!wasBlockSetState || !interactive ? undefined :
<SlideItem
Expand Down
Loading

0 comments on commit 8bf5a74

Please sign in to comment.