Skip to content

Commit b18290c

Browse files
feat: Add properties and chainId on build-spec command (#1520)
1 parent 02b53b6 commit b18290c

File tree

5 files changed

+136
-3
lines changed

5 files changed

+136
-3
lines changed

cmd/gossamer/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ var (
141141
Name: "genesis-spec",
142142
Usage: "Path to human-readable genesis JSON file",
143143
}
144+
OutputSpecFlag = cli.StringFlag{
145+
Name: "output",
146+
Usage: "Path to output the recently created genesis JSON file",
147+
}
144148
)
145149

146150
// Network service configuration flags
@@ -321,6 +325,7 @@ var (
321325
BuildSpecFlags = append([]cli.Flag{
322326
RawFlag,
323327
GenesisSpecFlag,
328+
OutputSpecFlag,
324329
}, GlobalFlags...)
325330

326331
// ExportFlags are the flags that are valid for use with the export subcommand

cmd/gossamer/main.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ func buildSpecAction(ctx *cli.Context) error {
353353
}
354354

355355
var bs *dot.BuildSpec
356+
356357
if genesis := ctx.String(GenesisSpecFlag.Name); genesis != "" {
357358
bspec, e := dot.BuildFromGenesis(genesis, 0)
358359
if e != nil {
@@ -380,17 +381,24 @@ func buildSpecAction(ctx *cli.Context) error {
380381
}
381382

382383
var res []byte
384+
383385
if ctx.Bool(RawFlag.Name) {
384386
res, err = bs.ToJSONRaw()
385387
} else {
386388
res, err = bs.ToJSON()
387389
}
390+
388391
if err != nil {
389392
return err
390393
}
391-
// TODO implement --output flag so that user can specify redirecting output a file.
392-
// then this can be removed (See issue #1029)
393-
fmt.Printf("%s", res)
394+
395+
if outputPath := ctx.String(OutputSpecFlag.Name); outputPath != "" {
396+
if err = dot.WriteGenesisSpecFile(res, outputPath); err != nil {
397+
return err
398+
}
399+
} else {
400+
fmt.Printf("%s", res)
401+
}
394402

395403
return nil
396404
}

cmd/gossamer/main_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,25 @@ func TestGossamerCommand(t *testing.T) {
284284

285285
}
286286

287+
func TestBuildSpecCommandWithOutput(t *testing.T) {
288+
tmpOutputfile := "/tmp/raw-genesis-spec-output.json"
289+
buildSpecCommand := runTestGossamer(t,
290+
"build-spec",
291+
"--raw",
292+
"--genesis-spec", "../../chain/gssmr/genesis-spec.json",
293+
"--output", tmpOutputfile)
294+
295+
time.Sleep(5 * time.Second)
296+
297+
_, err := os.Stat(tmpOutputfile)
298+
require.False(t, os.IsNotExist(err))
299+
defer os.Remove(tmpOutputfile)
300+
301+
outb, errb := buildSpecCommand.GetOutput()
302+
require.Empty(t, outb)
303+
require.Empty(t, errb)
304+
}
305+
287306
// TODO: TestExportCommand test "gossamer export" does not error
288307

289308
// TODO: TestInitCommand test "gossamer init" does not error

dot/build_spec.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ package dot
1818

1919
import (
2020
"encoding/json"
21+
"fmt"
22+
"os"
23+
"path/filepath"
2124

2225
"github.com/ChainSafe/gossamer/dot/state"
2326
"github.com/ChainSafe/gossamer/lib/common"
2427
"github.com/ChainSafe/gossamer/lib/genesis"
28+
"github.com/ChainSafe/gossamer/lib/utils"
2529
log "github.com/ChainSafe/log15"
2630
)
2731

@@ -35,8 +39,10 @@ func (b *BuildSpec) ToJSON() ([]byte, error) {
3539
tmpGen := &genesis.Genesis{
3640
Name: b.genesis.Name,
3741
ID: b.genesis.ID,
42+
ChainType: b.genesis.ChainType,
3843
Bootnodes: b.genesis.Bootnodes,
3944
ProtocolID: b.genesis.ProtocolID,
45+
Properties: b.genesis.Properties,
4046
Genesis: genesis.Fields{
4147
Runtime: b.genesis.GenesisFields().Runtime,
4248
},
@@ -52,6 +58,7 @@ func (b *BuildSpec) ToJSONRaw() ([]byte, error) {
5258
ChainType: b.genesis.ChainType,
5359
Bootnodes: b.genesis.Bootnodes,
5460
ProtocolID: b.genesis.ProtocolID,
61+
Properties: b.genesis.Properties,
5562
Genesis: genesis.Fields{
5663
Raw: b.genesis.GenesisFields().Raw,
5764
},
@@ -71,6 +78,21 @@ func BuildFromGenesis(path string, authCount int) (*BuildSpec, error) {
7178
return bs, nil
7279
}
7380

81+
// WriteGenesisSpecFile writes the build-spec in the output filepath
82+
func WriteGenesisSpecFile(data []byte, fp string) error {
83+
// if file already exists then dont apply any written on it
84+
if utils.PathExists(fp) {
85+
return fmt.Errorf("file %s already exists, rename to avoid overwriting", fp)
86+
}
87+
88+
if err := os.MkdirAll(filepath.Dir(fp), os.ModeDir|os.ModePerm); err != nil {
89+
return err
90+
}
91+
92+
WriteConfig(data, fp)
93+
return nil
94+
}
95+
7496
// BuildFromDB builds a BuildSpec from the DB located at path
7597
func BuildFromDB(path string) (*BuildSpec, error) {
7698
tmpGen := &genesis.Genesis{

dot/build_spec_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package dot
1717

1818
import (
1919
"encoding/json"
20+
"fmt"
21+
"io/ioutil"
2022
"os"
2123
"testing"
2224

@@ -29,6 +31,17 @@ func TestBuildFromGenesis(t *testing.T) {
2931
defer os.Remove(file)
3032
require.NoError(t, err)
3133
bs, err := BuildFromGenesis(file, 0)
34+
35+
expectedChainType := "TESTCHAINTYPE"
36+
expectedProperties := map[string]interface{}{
37+
"ss58Format": 0.0,
38+
"tokenDecimals": 0.0,
39+
"tokenSymbol": "TEST",
40+
}
41+
42+
bs.genesis.ChainType = expectedChainType
43+
bs.genesis.Properties = expectedProperties
44+
3245
require.NoError(t, err)
3346

3447
// confirm human-readable fields
@@ -39,6 +52,8 @@ func TestBuildFromGenesis(t *testing.T) {
3952
require.NoError(t, err)
4053
genesis.TestGenesis.Genesis = genesis.TestFieldsHR
4154
require.Equal(t, genesis.TestGenesis.Genesis.Runtime, jGen.Genesis.Runtime)
55+
require.Equal(t, expectedChainType, jGen.ChainType)
56+
require.Equal(t, expectedProperties, jGen.Properties)
4257

4358
// confirm raw fields
4459
raw, err := bs.ToJSONRaw()
@@ -48,6 +63,70 @@ func TestBuildFromGenesis(t *testing.T) {
4863
require.NoError(t, err)
4964
genesis.TestGenesis.Genesis = genesis.TestFieldsRaw
5065
require.Equal(t, genesis.TestGenesis.Genesis.Raw, jGenRaw.Genesis.Raw)
66+
require.Equal(t, expectedChainType, jGenRaw.ChainType)
67+
require.Equal(t, expectedProperties, jGenRaw.Properties)
68+
}
69+
70+
func TestBuildFromGenesis_WhenGenesisDoesNotExists(t *testing.T) {
71+
bs, err := BuildFromGenesis("/not/exists/genesis.json", 0)
72+
require.Nil(t, bs)
73+
require.Error(t, err, os.ErrNotExist)
74+
}
75+
76+
func TestWriteGenesisSpecFileWhenFileAlreadyExists(t *testing.T) {
77+
f, err := ioutil.TempFile("", "existing file data")
78+
require.NoError(t, err)
79+
defer os.Remove(f.Name())
80+
81+
someBytes := []byte("Testing some bytes")
82+
err = WriteGenesisSpecFile(someBytes, f.Name())
83+
84+
require.Error(t, err,
85+
fmt.Sprintf("file %s already exists, rename to avoid overwritten", f.Name()))
86+
}
87+
88+
func TestWriteGenesisSpecFile(t *testing.T) {
89+
cfg := NewTestConfig(t)
90+
cfg.Init.Genesis = "../chain/gssmr/genesis.json"
91+
92+
expected, err := genesis.NewGenesisFromJSONRaw(cfg.Init.Genesis)
93+
require.NoError(t, err)
94+
95+
err = InitNode(cfg)
96+
require.NoError(t, err)
97+
98+
bs, err := BuildFromGenesis(cfg.Init.Genesis, 0)
99+
require.NoError(t, err)
100+
101+
data, err := bs.ToJSONRaw()
102+
require.NoError(t, err)
103+
104+
tmpFiles := []string{
105+
"/tmp/unique-raw-genesis.json",
106+
"./unique-raw-genesis.json",
107+
}
108+
109+
for _, tmpFile := range tmpFiles {
110+
err = WriteGenesisSpecFile(data, tmpFile)
111+
require.NoError(t, err)
112+
require.FileExists(t, tmpFile)
113+
114+
defer os.Remove(tmpFile)
115+
116+
file, err := os.Open(tmpFile)
117+
require.NoError(t, err)
118+
defer file.Close()
119+
120+
genesisBytes, err := ioutil.ReadAll(file)
121+
require.NoError(t, err)
122+
123+
gen := new(genesis.Genesis)
124+
err = json.Unmarshal(genesisBytes, gen)
125+
require.NoError(t, err)
126+
127+
require.Equal(t, expected.ChainType, gen.ChainType)
128+
require.Equal(t, expected.Properties, gen.Properties)
129+
}
51130
}
52131

53132
func TestBuildFromDB(t *testing.T) {

0 commit comments

Comments
 (0)