commit
384a4041d5
53
CHANGELOG.md
53
CHANGELOG.md
|
@ -1,5 +1,58 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.3.0 (March 23, 2017)
|
||||||
|
|
||||||
|
BREAKING CHANGES:
|
||||||
|
|
||||||
|
- Remove `--data` flag and use `BCHOME` to set the home directory (defaults to `~/.basecoin`)
|
||||||
|
- Remove `--in-proc` flag and start Tendermint in-process by default (expect Tendermint files in $BCHOME/tendermint).
|
||||||
|
To start just the ABCI app/server, use `basecoin start --without-tendermint`.
|
||||||
|
- Consolidate genesis files so the Basecoin genesis is an object under `app_options` in Tendermint genesis. For instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"app_hash": "",
|
||||||
|
"chain_id": "foo_bar_chain",
|
||||||
|
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||||
|
"validators": [
|
||||||
|
{
|
||||||
|
"amount": 10,
|
||||||
|
"name": "",
|
||||||
|
"pub_key": [
|
||||||
|
1,
|
||||||
|
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_options": {
|
||||||
|
"accounts": [{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
|
||||||
|
},
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "blank",
|
||||||
|
"amount": 12345
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"denom": "ETH",
|
||||||
|
"amount": 654321
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
"plugin_options": ["plugin1/key1", "value1", "plugin1/key2", "value2"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note the array of key-value pairs is now under `app_options.plugin_options` while the `app_options` themselves are well formed.
|
||||||
|
We also changed `chainID` to `chain_id` and consolidated to have just one of them.
|
||||||
|
|
||||||
|
FEATURES:
|
||||||
|
|
||||||
|
- Introduce `basecoin init` and `basecoin unsafe_reset_all`
|
||||||
|
|
||||||
## 0.2.0 (March 6, 2017)
|
## 0.2.0 (March 6, 2017)
|
||||||
|
|
||||||
BREAKING CHANGES:
|
BREAKING CHANGES:
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
FROM alpine:3.5
|
||||||
|
|
||||||
|
# BCHOME is where your genesis.json, key.json and other files including state are stored.
|
||||||
|
ENV BCHOME /basecoin
|
||||||
|
|
||||||
|
# Create a basecoin user and group first so the IDs get set the same way, even
|
||||||
|
# as the rest of this may change over time.
|
||||||
|
RUN addgroup basecoin && \
|
||||||
|
adduser -S -G basecoin basecoin
|
||||||
|
|
||||||
|
RUN mkdir -p $BCHOME && \
|
||||||
|
chown -R basecoin:basecoin $BCHOME
|
||||||
|
WORKDIR $BCHOME
|
||||||
|
|
||||||
|
# Expose the basecoin home directory as a volume since there's mutable state in there.
|
||||||
|
VOLUME $BCHOME
|
||||||
|
|
||||||
|
# jq and curl used for extracting `pub_key` from private validator while
|
||||||
|
# deploying tendermint with Kubernetes. It is nice to have bash so the users
|
||||||
|
# could execute bash commands.
|
||||||
|
RUN apk add --no-cache bash curl jq
|
||||||
|
|
||||||
|
COPY basecoin /usr/bin/basecoin
|
||||||
|
|
||||||
|
ENTRYPOINT ["basecoin"]
|
||||||
|
|
||||||
|
# By default you will get the basecoin with local MerkleEyes and in-proc Tendermint.
|
||||||
|
CMD ["start", "--dir=${BCHOME}"]
|
|
@ -0,0 +1,12 @@
|
||||||
|
FROM golang:latest
|
||||||
|
|
||||||
|
RUN mkdir -p /go/src/github.com/tendermint/basecoin
|
||||||
|
WORKDIR /go/src/github.com/tendermint/basecoin
|
||||||
|
|
||||||
|
COPY Makefile /go/src/github.com/tendermint/basecoin/
|
||||||
|
COPY glide.yaml /go/src/github.com/tendermint/basecoin/
|
||||||
|
COPY glide.lock /go/src/github.com/tendermint/basecoin/
|
||||||
|
|
||||||
|
RUN make get_vendor_deps
|
||||||
|
|
||||||
|
COPY . /go/src/github.com/tendermint/basecoin
|
10
Makefile
10
Makefile
|
@ -1,5 +1,3 @@
|
||||||
.PHONY: all test get_deps
|
|
||||||
|
|
||||||
all: test install
|
all: test install
|
||||||
|
|
||||||
NOVENDOR = go list github.com/tendermint/basecoin/... | grep -v /vendor/
|
NOVENDOR = go list github.com/tendermint/basecoin/... | grep -v /vendor/
|
||||||
|
@ -24,3 +22,11 @@ get_vendor_deps:
|
||||||
go get github.com/Masterminds/glide
|
go get github.com/Masterminds/glide
|
||||||
glide install
|
glide install
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin
|
||||||
|
docker build -t "tendermint/basecoin" .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f ./basecoin
|
||||||
|
|
||||||
|
.PHONY: all build install test get_deps update_deps get_vendor_deps build-docker clean
|
||||||
|
|
32
README.md
32
README.md
|
@ -15,46 +15,26 @@ WARNING: Currently uses plain-text private keys for transactions and is otherwis
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* Go to https://golang.org/doc/install to install Golang.
|
[Install and setup Golang](https://tendermint.com/docs/guides/install-go).
|
||||||
* You will also need to set the $GOPATH environment variable as per the instructions [here](https://golang.org/doc/code.html#GOPATH).
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
On a good day, basecoin can be installed like a normal Go program:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
go get -u github.com/tendermint/basecoin/cmd/basecoin
|
go get -u github.com/tendermint/basecoin/cmd/basecoin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See the [install guide](/docs/guide/install.md) for more details.
|
||||||
If that fails, or if another branch is required, you may have to compile from source.
|
|
||||||
You will first need to install the Golang package manager [`glide`](https://github.com/Masterminds/glide).
|
|
||||||
|
|
||||||
```
|
|
||||||
cd $GOPATH/src/github.com/tendermint/basecoin
|
|
||||||
git checkout develop # (until we release tendermint v0.9)
|
|
||||||
make get_vendor_deps
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create the `basecoin` binary in `$GOPATH/bin`.
|
|
||||||
|
|
||||||
|
|
||||||
## Command Line Interface
|
## Guide
|
||||||
|
|
||||||
The basecoin CLI can be used to start a stand-alone basecoin instance (`basecoin start`),
|
1. Getting started with the [Basecoin basics](/docs/guide/basecoin-basics.md)
|
||||||
or to start basecoin with Tendermint in the same process (`basecoin start --in-proc`).
|
|
||||||
It can also be used to send transactions, eg. `basecoin tx send --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 100btc,10gold`
|
|
||||||
See `basecoin --help` and `basecoin [cmd] --help` for more details`.
|
|
||||||
|
|
||||||
## Learn more
|
|
||||||
|
|
||||||
1. Getting started with the [Basecoin tool](/docs/guide/basecoin-basics.md)
|
|
||||||
1. Learn more about [Basecoin's design](/docs/guide/basecoin-design.md)
|
1. Learn more about [Basecoin's design](/docs/guide/basecoin-design.md)
|
||||||
1. Extend Basecoin [using the plugin system](/docs/guide/example-plugin.md)
|
1. Extend Basecoin [using the plugin system](/docs/guide/example-plugin.md)
|
||||||
1. Learn more about [plugin design](/docs/guide/plugin-design.md)
|
1. Learn more about [plugin design](/docs/guide/plugin-design.md)
|
||||||
1. See some [more example applications](/docs/guide/more-examples.md)
|
1. See some [more example applications](/docs/guide/more-examples.md)
|
||||||
|
1. More features of the [Basecoin tool](/docs/guide/basecoin-tool.md)
|
||||||
1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md)
|
1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md)
|
||||||
1. [Deploy testnets](deployment.md) running your basecoin application.
|
1. [Deploy testnets](/docs/guide/deployment.md) running your basecoin application.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,12 +60,12 @@ func (app *Basecoin) SetOption(key string, value string) string {
|
||||||
if plugin == nil {
|
if plugin == nil {
|
||||||
return "Invalid plugin name: " + pluginName
|
return "Invalid plugin name: " + pluginName
|
||||||
}
|
}
|
||||||
log.Info("SetOption on plugin", "plugin", pluginName, "key", key, "value", value)
|
log.Notice("SetOption on plugin", "plugin", pluginName, "key", key, "value", value)
|
||||||
return plugin.SetOption(app.state, key, value)
|
return plugin.SetOption(app.state, key, value)
|
||||||
} else {
|
} else {
|
||||||
// Set option on basecoin
|
// Set option on basecoin
|
||||||
switch key {
|
switch key {
|
||||||
case "chainID":
|
case "chain_id":
|
||||||
app.state.SetChainID(value)
|
app.state.SetChainID(value)
|
||||||
return "Success"
|
return "Success"
|
||||||
case "account":
|
case "account":
|
||||||
|
@ -75,7 +75,8 @@ func (app *Basecoin) SetOption(key string, value string) string {
|
||||||
return "Error decoding acc message: " + err.Error()
|
return "Error decoding acc message: " + err.Error()
|
||||||
}
|
}
|
||||||
app.state.SetAccount(acc.PubKey.Address(), &acc)
|
app.state.SetAccount(acc.PubKey.Address(), &acc)
|
||||||
log.Info("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
|
log.Notice("SetAccount", "addr", acc.PubKey.Address(), "acc", acc)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
}
|
}
|
||||||
return "Unrecognized option key " + key
|
return "Unrecognized option key " + key
|
||||||
|
|
|
@ -4,16 +4,35 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/tendermint/basecoin/types"
|
||||||
cmn "github.com/tendermint/go-common"
|
cmn "github.com/tendermint/go-common"
|
||||||
|
//tmtypes "github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (app *Basecoin) LoadGenesis(path string) error {
|
func (app *Basecoin) LoadGenesis(path string) error {
|
||||||
kvz, err := loadGenesis(path)
|
genDoc, err := loadGenesis(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, kv := range kvz {
|
|
||||||
app.SetOption(kv.Key, kv.Value)
|
// set chain_id
|
||||||
|
app.SetOption("base/chain_id", genDoc.ChainID)
|
||||||
|
|
||||||
|
// set accounts
|
||||||
|
for _, acc := range genDoc.AppOptions.Accounts {
|
||||||
|
accBytes, err := json.Marshal(acc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r := app.SetOption("base/account", string(accBytes))
|
||||||
|
// TODO: SetOption returns an error
|
||||||
|
log.Notice("Done setting Account via SetOption", "result", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set plugin options
|
||||||
|
for _, kv := range genDoc.AppOptions.pluginOptions {
|
||||||
|
r := app.SetOption(kv.Key, kv.Value)
|
||||||
|
log.Notice("Done setting Plugin key-value pair via SetOption", "result", r, "k", kv.Key, "v", kv.Value)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -23,16 +42,45 @@ type keyValue struct {
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGenesis(filePath string) (kvz []keyValue, err error) {
|
// includes tendermint (in the json, we ignore here)
|
||||||
kvz_ := []json.RawMessage{}
|
type FullGenesisDoc struct {
|
||||||
|
ChainID string `json:"chain_id"`
|
||||||
|
AppOptions *GenesisDoc `json:"app_options"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisDoc struct {
|
||||||
|
Accounts []types.Account `json:"accounts"`
|
||||||
|
PluginOptions []json.RawMessage `json:"plugin_options"`
|
||||||
|
|
||||||
|
pluginOptions []keyValue // unmarshaled rawmessages
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadGenesis(filePath string) (*FullGenesisDoc, error) {
|
||||||
bytes, err := cmn.ReadFile(filePath)
|
bytes, err := cmn.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "loading genesis file")
|
return nil, errors.Wrap(err, "loading genesis file")
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(bytes, &kvz_)
|
|
||||||
|
// the tendermint genesis is go-wire
|
||||||
|
// tmGenesis := new(tmtypes.GenesisDoc)
|
||||||
|
// err = wire.ReadJSONBytes(bytes, tmGenesis)
|
||||||
|
|
||||||
|
// the basecoin genesis go-data :)
|
||||||
|
genDoc := new(FullGenesisDoc)
|
||||||
|
err = json.Unmarshal(bytes, genDoc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "parsing genesis file")
|
return nil, errors.Wrap(err, "unmarshaling genesis file")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginOpts, err := parseGenesisList(genDoc.AppOptions.PluginOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
genDoc.AppOptions.pluginOptions = pluginOpts
|
||||||
|
return genDoc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGenesisList(kvz_ []json.RawMessage) (kvz []keyValue, err error) {
|
||||||
if len(kvz_)%2 != 0 {
|
if len(kvz_)%2 != 0 {
|
||||||
return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]")
|
return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[
|
{
|
||||||
"base/chainID", "foo_bar_chain",
|
"chain_id": "foo_bar_chain",
|
||||||
"base/account", {
|
"app_options": {
|
||||||
|
"accounts": [{
|
||||||
"pub_key": {
|
"pub_key": {
|
||||||
"type": "ed25519",
|
"type": "ed25519",
|
||||||
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
|
"data": "6880db93598e283a67c4d88fc67a8858aa2de70f713fe94a5109e29c137100c2"
|
||||||
|
@ -15,5 +16,7 @@
|
||||||
"amount": 654321
|
"amount": 654321
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}],
|
||||||
|
"plugin_options": ["plugin1/key1", "value1", "plugin1/key2", "value2"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ func main() {
|
||||||
app.Usage = "basecoin [command] [args...]"
|
app.Usage = "basecoin [command] [args...]"
|
||||||
app.Version = version.Version
|
app.Version = version.Version
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
|
commands.InitCmd,
|
||||||
commands.StartCmd,
|
commands.StartCmd,
|
||||||
commands.TxCmd,
|
commands.TxCmd,
|
||||||
commands.QueryCmd,
|
commands.QueryCmd,
|
||||||
|
@ -21,6 +22,7 @@ func main() {
|
||||||
commands.VerifyCmd,
|
commands.VerifyCmd,
|
||||||
commands.BlockCmd,
|
commands.BlockCmd,
|
||||||
commands.AccountCmd,
|
commands.AccountCmd,
|
||||||
|
commands.UnsafeResetAllCmd,
|
||||||
}
|
}
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,9 @@ var (
|
||||||
// TODO: move to config file
|
// TODO: move to config file
|
||||||
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
// eyesCacheSizePtr := flag.Int("eyes-cache-size", 10000, "MerkleEyes db cache size, for embedded")
|
||||||
|
|
||||||
DirFlag = cli.StringFlag{
|
WithoutTendermintFlag = cli.BoolFlag{
|
||||||
Name: "dir",
|
Name: "without-tendermint",
|
||||||
Value: ".",
|
Usage: "Run the Basecoin app without Tendermint",
|
||||||
Usage: "Root directory",
|
|
||||||
}
|
|
||||||
|
|
||||||
InProcTMFlag = cli.BoolFlag{
|
|
||||||
Name: "in-proc",
|
|
||||||
Usage: "Run Tendermint in-process with the App",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
|
cmn "github.com/tendermint/go-common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var InitCmd = cli.Command{
|
||||||
|
Name: "init",
|
||||||
|
Usage: "Initialize a basecoin blockchain",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return cmdInit(c)
|
||||||
|
},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
ChainIDFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdInit(c *cli.Context) error {
|
||||||
|
rootDir := BasecoinRoot("")
|
||||||
|
|
||||||
|
cmn.EnsureDir(rootDir, 0777)
|
||||||
|
|
||||||
|
// initalize basecoin
|
||||||
|
genesisFile := path.Join(rootDir, "genesis.json")
|
||||||
|
privValFile := path.Join(rootDir, "priv_validator.json")
|
||||||
|
key1File := path.Join(rootDir, "key.json")
|
||||||
|
key2File := path.Join(rootDir, "key2.json")
|
||||||
|
|
||||||
|
if err := ioutil.WriteFile(genesisFile, []byte(genesisJSON), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(privValFile, []byte(privValJSON), 0400); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(key1File, []byte(key1JSON), 0400); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(key2File, []byte(key2JSON), 0400); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Notice("Initialized Basecoin", "genesis", genesisFile, "key", key1File)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const privValJSON = `{
|
||||||
|
"address": "7A956FADD20D3A5B2375042B2959F8AB172A058F",
|
||||||
|
"last_height": 0,
|
||||||
|
"last_round": 0,
|
||||||
|
"last_signature": null,
|
||||||
|
"last_signbytes": "",
|
||||||
|
"last_step": 0,
|
||||||
|
"priv_key": [
|
||||||
|
1,
|
||||||
|
"D07ABE82A8B15559A983B2DB5D4842B2B6E4D6AF58B080005662F424F17D68C17B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
|
||||||
|
],
|
||||||
|
"pub_key": [
|
||||||
|
1,
|
||||||
|
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
const genesisJSON = `{
|
||||||
|
"app_hash": "",
|
||||||
|
"chain_id": "test_chain_id",
|
||||||
|
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||||
|
"validators": [
|
||||||
|
{
|
||||||
|
"amount": 10,
|
||||||
|
"name": "",
|
||||||
|
"pub_key": [
|
||||||
|
1,
|
||||||
|
"7B90EA87E7DC0C7145C8C48C08992BE271C7234134343E8A8E8008E617DE7B30"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_options": {
|
||||||
|
"accounts": [{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||||
|
},
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "mycoin",
|
||||||
|
"amount": 9007199254740992
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
const key1JSON = `{
|
||||||
|
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
|
||||||
|
"priv_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||||
|
},
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
const key2JSON = `{
|
||||||
|
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
|
||||||
|
"priv_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||||
|
},
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
||||||
|
}
|
||||||
|
}`
|
|
@ -1,14 +1,17 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
cmn "github.com/tendermint/go-common"
|
cmn "github.com/tendermint/go-common"
|
||||||
"github.com/tendermint/go-crypto"
|
"github.com/tendermint/go-crypto"
|
||||||
"github.com/tendermint/go-wire"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,18 +34,36 @@ var (
|
||||||
|
|
||||||
func cmdNewKey(c *cli.Context) error {
|
func cmdNewKey(c *cli.Context) error {
|
||||||
key := genKey()
|
key := genKey()
|
||||||
keyJSON := wire.JSONBytesPretty(key)
|
keyJSON, err := json.MarshalIndent(key, "", "\t")
|
||||||
fmt.Println(string(keyJSON))
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(keyJSON)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// simple implementation of a key
|
// simple implementation of a key
|
||||||
|
|
||||||
|
type Address [20]byte
|
||||||
|
|
||||||
|
func (a Address) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(fmt.Sprintf(`"%x"`, a[:])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Address) UnmarshalJSON(addrHex []byte) error {
|
||||||
|
addr, err := hex.DecodeString(strings.Trim(string(addrHex), `"`))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
copy(a[:], addr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Key struct {
|
type Key struct {
|
||||||
Address []byte `json:"address"`
|
Address Address `json:"address"`
|
||||||
PubKey crypto.PubKey `json:"pub_key"`
|
PubKey crypto.PubKeyS `json:"pub_key"`
|
||||||
PrivKey crypto.PrivKey `json:"priv_key"`
|
PrivKey crypto.PrivKeyS `json:"priv_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements Signer
|
// Implements Signer
|
||||||
|
@ -53,21 +74,26 @@ func (k *Key) Sign(msg []byte) crypto.Signature {
|
||||||
// Generates a new validator with private key.
|
// Generates a new validator with private key.
|
||||||
func genKey() *Key {
|
func genKey() *Key {
|
||||||
privKey := crypto.GenPrivKeyEd25519()
|
privKey := crypto.GenPrivKeyEd25519()
|
||||||
|
addrBytes := privKey.PubKey().Address()
|
||||||
|
var addr Address
|
||||||
|
copy(addr[:], addrBytes)
|
||||||
return &Key{
|
return &Key{
|
||||||
Address: privKey.PubKey().Address(),
|
Address: addr,
|
||||||
PubKey: privKey.PubKey(),
|
PubKey: crypto.PubKeyS{privKey.PubKey()},
|
||||||
PrivKey: privKey,
|
PrivKey: crypto.PrivKeyS{privKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadKey(filePath string) *Key {
|
func LoadKey(keyFile string) *Key {
|
||||||
|
filePath := path.Join(BasecoinRoot(""), keyFile)
|
||||||
keyJSONBytes, err := ioutil.ReadFile(filePath)
|
keyJSONBytes, err := ioutil.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmn.Exit(err.Error())
|
cmn.Exit(err.Error())
|
||||||
}
|
}
|
||||||
key := wire.ReadJSON(&Key{}, keyJSONBytes, &err).(*Key)
|
key := new(Key)
|
||||||
|
err = json.Unmarshal(keyJSONBytes, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmn.Exit(cmn.Fmt("Error reading PrivValidator from %v: %v\n", filePath, err))
|
cmn.Exit(cmn.Fmt("Error reading key from %v: %v\n", filePath, err))
|
||||||
}
|
}
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/go-logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var log = logger.New("module", "commands")
|
|
@ -0,0 +1,47 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
|
tmcfg "github.com/tendermint/tendermint/config/tendermint"
|
||||||
|
types "github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var UnsafeResetAllCmd = cli.Command{
|
||||||
|
Name: "unsafe_reset_all",
|
||||||
|
Usage: "Reset all blockchain data",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return cmdUnsafeResetAll(c)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdUnsafeResetAll(c *cli.Context) error {
|
||||||
|
basecoinDir := BasecoinRoot("")
|
||||||
|
tmDir := path.Join(basecoinDir)
|
||||||
|
tmConfig := tmcfg.GetConfig(tmDir)
|
||||||
|
|
||||||
|
// Get and Reset PrivValidator
|
||||||
|
var privValidator *types.PrivValidator
|
||||||
|
privValidatorFile := tmConfig.GetString("priv_validator_file")
|
||||||
|
if _, err := os.Stat(privValidatorFile); err == nil {
|
||||||
|
privValidator = types.LoadPrivValidator(privValidatorFile)
|
||||||
|
privValidator.Reset()
|
||||||
|
log.Notice("Reset PrivValidator", "file", privValidatorFile)
|
||||||
|
} else {
|
||||||
|
privValidator = types.GenPrivValidator()
|
||||||
|
privValidator.SetFile(privValidatorFile)
|
||||||
|
privValidator.Save()
|
||||||
|
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all tendermint data
|
||||||
|
tmDataDir := tmConfig.GetString("db_dir")
|
||||||
|
os.RemoveAll(tmDataDir)
|
||||||
|
log.Notice("Removed all data", "dir", tmDataDir)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -10,8 +10,6 @@ import (
|
||||||
|
|
||||||
"github.com/tendermint/abci/server"
|
"github.com/tendermint/abci/server"
|
||||||
cmn "github.com/tendermint/go-common"
|
cmn "github.com/tendermint/go-common"
|
||||||
cfg "github.com/tendermint/go-config"
|
|
||||||
//logger "github.com/tendermint/go-logger"
|
|
||||||
eyes "github.com/tendermint/merkleeyes/client"
|
eyes "github.com/tendermint/merkleeyes/client"
|
||||||
|
|
||||||
tmcfg "github.com/tendermint/tendermint/config/tendermint"
|
tmcfg "github.com/tendermint/tendermint/config/tendermint"
|
||||||
|
@ -23,8 +21,6 @@ import (
|
||||||
"github.com/tendermint/basecoin/types"
|
"github.com/tendermint/basecoin/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var config cfg.Config
|
|
||||||
|
|
||||||
const EyesCacheSize = 10000
|
const EyesCacheSize = 10000
|
||||||
|
|
||||||
var StartCmd = cli.Command{
|
var StartCmd = cli.Command{
|
||||||
|
@ -37,8 +33,7 @@ var StartCmd = cli.Command{
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
AddrFlag,
|
AddrFlag,
|
||||||
EyesFlag,
|
EyesFlag,
|
||||||
DirFlag,
|
WithoutTendermintFlag,
|
||||||
InProcTMFlag,
|
|
||||||
ChainIDFlag,
|
ChainIDFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -56,11 +51,12 @@ func RegisterStartPlugin(name string, newPlugin func() types.Plugin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdStart(c *cli.Context) error {
|
func cmdStart(c *cli.Context) error {
|
||||||
|
basecoinDir := BasecoinRoot("")
|
||||||
|
|
||||||
// Connect to MerkleEyes
|
// Connect to MerkleEyes
|
||||||
var eyesCli *eyes.Client
|
var eyesCli *eyes.Client
|
||||||
if c.String("eyes") == "local" {
|
if c.String("eyes") == "local" {
|
||||||
eyesCli = eyes.NewLocalClient(path.Join(c.String("dir"), "merkleeyes.db"), EyesCacheSize)
|
eyesCli = eyes.NewLocalClient(path.Join(basecoinDir, "data", "merkleeyes.db"), EyesCacheSize)
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
eyesCli, err = eyes.NewClient(c.String("eyes"))
|
eyesCli, err = eyes.NewClient(c.String("eyes"))
|
||||||
|
@ -80,8 +76,11 @@ func cmdStart(c *cli.Context) error {
|
||||||
basecoinApp.RegisterPlugin(p.newPlugin())
|
basecoinApp.RegisterPlugin(p.newPlugin())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if chain_id has not been set yet, load the genesis.
|
||||||
|
// else, assume it's been loaded
|
||||||
|
if basecoinApp.GetState().GetChainID() == "" {
|
||||||
// If genesis file exists, set key-value options
|
// If genesis file exists, set key-value options
|
||||||
genesisFile := path.Join(c.String("dir"), "genesis.json")
|
genesisFile := path.Join(basecoinDir, "genesis.json")
|
||||||
if _, err := os.Stat(genesisFile); err == nil {
|
if _, err := os.Stat(genesisFile); err == nil {
|
||||||
err := basecoinApp.LoadGenesis(genesisFile)
|
err := basecoinApp.LoadGenesis(genesisFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -90,13 +89,17 @@ func cmdStart(c *cli.Context) error {
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("No genesis file at %s, skipping...\n", genesisFile)
|
fmt.Printf("No genesis file at %s, skipping...\n", genesisFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Bool("in-proc") {
|
|
||||||
startTendermint(c, basecoinApp)
|
|
||||||
} else {
|
|
||||||
if err := startBasecoinABCI(c, basecoinApp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chainID := basecoinApp.GetState().GetChainID()
|
||||||
|
if c.Bool("without-tendermint") {
|
||||||
|
log.Notice("Starting Basecoin without Tendermint", "chain_id", chainID)
|
||||||
|
// run just the abci app/server
|
||||||
|
return startBasecoinABCI(c, basecoinApp)
|
||||||
|
} else {
|
||||||
|
log.Notice("Starting Basecoin with Tendermint", "chain_id", chainID)
|
||||||
|
// start the app with tendermint in-process
|
||||||
|
return startTendermint(basecoinDir, basecoinApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -117,23 +120,29 @@ func startBasecoinABCI(c *cli.Context, basecoinApp *app.Basecoin) error {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startTendermint(c *cli.Context, basecoinApp *app.Basecoin) {
|
func startTendermint(dir string, basecoinApp *app.Basecoin) error {
|
||||||
// Get configuration
|
// Get configuration
|
||||||
config = tmcfg.GetConfig("")
|
tmConfig := tmcfg.GetConfig(dir)
|
||||||
|
|
||||||
// logger.SetLogLevel("notice") //config.GetString("log_level"))
|
// logger.SetLogLevel("notice") //config.GetString("log_level"))
|
||||||
|
|
||||||
// parseFlags(config, args[1:]) // Command line overrides
|
// parseFlags(config, args[1:]) // Command line overrides
|
||||||
|
|
||||||
// Create & start tendermint node
|
// Create & start tendermint node
|
||||||
privValidatorFile := config.GetString("priv_validator_file")
|
privValidatorFile := tmConfig.GetString("priv_validator_file")
|
||||||
privValidator := tmtypes.LoadOrGenPrivValidator(privValidatorFile)
|
privValidator := tmtypes.LoadOrGenPrivValidator(privValidatorFile)
|
||||||
n := node.NewNode(config, privValidator, proxy.NewLocalClientCreator(basecoinApp))
|
n := node.NewNode(tmConfig, privValidator, proxy.NewLocalClientCreator(basecoinApp))
|
||||||
|
|
||||||
n.Start()
|
_, err := n.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Wait forever
|
// Wait forever
|
||||||
cmn.TrapSignal(func() {
|
cmn.TrapSignal(func() {
|
||||||
// Cleanup
|
// Cleanup
|
||||||
n.Stop()
|
n.Stop()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
client "github.com/tendermint/go-rpc/client"
|
client "github.com/tendermint/go-rpc/client"
|
||||||
"github.com/tendermint/go-wire"
|
"github.com/tendermint/go-wire"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var TxFlags = []cli.Flag{
|
var TxFlags = []cli.Flag{
|
||||||
|
@ -87,7 +86,7 @@ func cmdSendTx(c *cli.Context) error {
|
||||||
privKey := LoadKey(fromFile)
|
privKey := LoadKey(fromFile)
|
||||||
|
|
||||||
// get the sequence number for the tx
|
// get the sequence number for the tx
|
||||||
sequence, err := getSeq(c, privKey.Address)
|
sequence, err := getSeq(c, privKey.Address[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -144,9 +143,9 @@ func AppTx(c *cli.Context, name string, data []byte) error {
|
||||||
gas := int64(c.Int("gas"))
|
gas := int64(c.Int("gas"))
|
||||||
chainID := c.String("chain_id")
|
chainID := c.String("chain_id")
|
||||||
|
|
||||||
privKey := tmtypes.LoadPrivValidator(fromFile)
|
privKey := LoadKey(fromFile)
|
||||||
|
|
||||||
sequence, err := getSeq(c, privKey.Address)
|
sequence, err := getSeq(c, privKey.Address[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package commands
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -20,6 +21,16 @@ import (
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func BasecoinRoot(rootDir string) string {
|
||||||
|
if rootDir == "" {
|
||||||
|
rootDir = os.Getenv("BCHOME")
|
||||||
|
}
|
||||||
|
if rootDir == "" {
|
||||||
|
rootDir = os.Getenv("HOME") + "/.basecoin"
|
||||||
|
}
|
||||||
|
return rootDir
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true for non-empty hex-string prefixed with "0x"
|
// Returns true for non-empty hex-string prefixed with "0x"
|
||||||
func isHex(s string) bool {
|
func isHex(s string) bool {
|
||||||
if len(s) > 2 && s[:2] == "0x" {
|
if len(s) > 2 && s[:2] == "0x" {
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
[
|
|
||||||
"base/chainID", "test_chain_id",
|
|
||||||
"base/account", {
|
|
||||||
"pub_key": {
|
|
||||||
"type": "ed25519",
|
|
||||||
"data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
|
||||||
},
|
|
||||||
"coins": [
|
|
||||||
{
|
|
||||||
"denom": "mycoin",
|
|
||||||
"amount": 9007199254740992
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"address": "1B1BE55F969F54064628A63B9559E7C21C925165",
|
|
||||||
"priv_key": [
|
|
||||||
1,
|
|
||||||
"C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
|
||||||
],
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090",
|
|
||||||
"priv_key": [
|
|
||||||
1,
|
|
||||||
"34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
|
||||||
],
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,13 +1,10 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
killall -9 basecoin tendermint
|
killall -9 basecoin tendermint
|
||||||
TMROOT=./data/chain1/tendermint tendermint unsafe_reset_all
|
TMROOT=./data/chain1 tendermint unsafe_reset_all
|
||||||
TMROOT=./data/chain2/tendermint tendermint unsafe_reset_all
|
TMROOT=./data/chain2 tendermint unsafe_reset_all
|
||||||
|
|
||||||
rm -rf ./data/chain1/basecoin/merkleeyes.db
|
|
||||||
rm -rf ./data/chain2/basecoin/merkleeyes.db
|
|
||||||
|
|
||||||
rm ./*.log
|
rm ./*.log
|
||||||
|
|
||||||
rm ./data/chain1/tendermint/*.bak
|
rm ./data/chain1/*.bak
|
||||||
rm ./data/chain2/tendermint/*.bak
|
rm ./data/chain2/*.bak
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
[
|
|
||||||
"base/chainID", "test_chain_1",
|
|
||||||
"base/account", {
|
|
||||||
"pub_key": {
|
|
||||||
"type": "ed25519",
|
|
||||||
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
|
||||||
},
|
|
||||||
"coins": [
|
|
||||||
{
|
|
||||||
"denom": "mycoin",
|
|
||||||
"amount": 9007199254740992
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"address": "D397BC62B435F3CF50570FBAB4340FE52C60858F",
|
|
||||||
"priv_key": [
|
|
||||||
1,
|
|
||||||
"39E75AA1CF7BC710585977EFC375CD1730519186BD231478C339F2819C3C26E7B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
|
||||||
],
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"app_hash": "",
|
||||||
|
"chain_id": "test_chain_1",
|
||||||
|
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||||
|
"validators": [
|
||||||
|
{
|
||||||
|
"amount": 10,
|
||||||
|
"name": "",
|
||||||
|
"pub_key": [
|
||||||
|
1,
|
||||||
|
"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_options": {
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
||||||
|
},
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "mycoin",
|
||||||
|
"amount": 9007199254740992
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"address": "D397BC62B435F3CF50570FBAB4340FE52C60858F",
|
||||||
|
"priv_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "39E75AA1CF7BC710585977EFC375CD1730519186BD231478C339F2819C3C26E7B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
||||||
|
},
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"app_hash": "",
|
|
||||||
"chain_id": "test_chain_1",
|
|
||||||
"genesis_time": "0001-01-01T00:00:00.000Z",
|
|
||||||
"validators": [
|
|
||||||
{
|
|
||||||
"amount": 10,
|
|
||||||
"name": "",
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
[
|
|
||||||
"base/chainID", "test_chain_2",
|
|
||||||
"base/account", {
|
|
||||||
"pub_key": {
|
|
||||||
"type": "ed25519",
|
|
||||||
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
|
||||||
},
|
|
||||||
"coins": [
|
|
||||||
{
|
|
||||||
"denom": "mycoin",
|
|
||||||
"amount": 9007199254740992
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"address": "053BA0F19616AFF975C8756A2CBFF04F408B4D47",
|
|
||||||
"priv_key": [
|
|
||||||
1,
|
|
||||||
"22920C428043D869987F253D7C9B2305E7010642C40CE88A52C9F6CE5ACC42080628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
|
||||||
],
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"app_hash": "",
|
||||||
|
"chain_id": "test_chain_2",
|
||||||
|
"genesis_time": "0001-01-01T00:00:00.000Z",
|
||||||
|
"validators": [
|
||||||
|
{
|
||||||
|
"amount": 10,
|
||||||
|
"name": "",
|
||||||
|
"pub_key": [
|
||||||
|
1,
|
||||||
|
"9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_options": {
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
||||||
|
},
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "mycoin",
|
||||||
|
"amount": 9007199254740992
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"address": "053BA0F19616AFF975C8756A2CBFF04F408B4D47",
|
||||||
|
"priv_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "22920C428043D869987F253D7C9B2305E7010642C40CE88A52C9F6CE5ACC42080628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
||||||
|
},
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"app_hash": "",
|
|
||||||
"chain_id": "test_chain_2",
|
|
||||||
"genesis_time": "0001-01-01T00:00:00.000Z",
|
|
||||||
"validators": [
|
|
||||||
{
|
|
||||||
"amount": 10,
|
|
||||||
"name": "",
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -60,29 +60,34 @@ function waitForBlock() {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# make basecoin root vars
|
||||||
|
export BCHOME="."
|
||||||
|
BCHOME1="./data/chain1"
|
||||||
|
BCHOME2="./data/chain2"
|
||||||
|
|
||||||
# grab the chain ids
|
# grab the chain ids
|
||||||
CHAIN_ID1=$(cat ./data/chain1/basecoin/genesis.json | jq .[1])
|
CHAIN_ID1=$(cat $BCHOME1/genesis.json | jq .chain_id)
|
||||||
CHAIN_ID1=$(removeQuotes $CHAIN_ID1)
|
CHAIN_ID1=$(removeQuotes $CHAIN_ID1)
|
||||||
CHAIN_ID2=$(cat ./data/chain2/basecoin/genesis.json | jq .[1])
|
CHAIN_ID2=$(cat $BCHOME2/genesis.json | jq .chain_id)
|
||||||
CHAIN_ID2=$(removeQuotes $CHAIN_ID2)
|
CHAIN_ID2=$(removeQuotes $CHAIN_ID2)
|
||||||
echo "CHAIN_ID1: $CHAIN_ID1"
|
echo "CHAIN_ID1: $CHAIN_ID1"
|
||||||
echo "CHAIN_ID2: $CHAIN_ID2"
|
echo "CHAIN_ID2: $CHAIN_ID2"
|
||||||
|
|
||||||
# make reusable chain flags
|
# make reusable chain flags
|
||||||
CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/basecoin/key.json"
|
CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from $BCHOME1/key.json"
|
||||||
CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/key.json --node tcp://localhost:36657"
|
CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from $BCHOME2/key.json --node tcp://localhost:36657"
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "... starting chains"
|
echo "... starting chains"
|
||||||
echo ""
|
echo ""
|
||||||
# start the first node
|
# start the first node
|
||||||
TMROOT=./data/chain1/tendermint tendermint node --skip_upnp --log_level=info &> $LOG_DIR/chain1_tendermint.log &
|
TMROOT=./data/chain1 tendermint node --skip_upnp --log_level=info &> $LOG_DIR/chain1_tendermint.log &
|
||||||
basecoin start --dir ./data/chain1/basecoin &> $LOG_DIR/chain1_basecoin.log &
|
BCHOME=$BCHOME1 basecoin start --without-tendermint &> $LOG_DIR/chain1_basecoin.log &
|
||||||
|
|
||||||
# start the second node
|
# start the second node
|
||||||
TMROOT=./data/chain2/tendermint tendermint node --skip_upnp --log_level=info --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> $LOG_DIR/chain2_tendermint.log &
|
TMROOT=./data/chain2 tendermint node --skip_upnp --log_level=info --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> $LOG_DIR/chain2_tendermint.log &
|
||||||
basecoin start --address tcp://localhost:36658 --dir ./data/chain2/basecoin &> $LOG_DIR/chain2_basecoin.log &
|
BCHOME=$BCHOME2 basecoin start --address tcp://localhost:36658 --without-tendermint &> $LOG_DIR/chain2_basecoin.log &
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "... waiting for chains to start"
|
echo "... waiting for chains to start"
|
||||||
|
@ -98,7 +103,7 @@ sleep 3
|
||||||
echo "... registering chain1 on chain2"
|
echo "... registering chain1 on chain2"
|
||||||
echo ""
|
echo ""
|
||||||
# register chain1 on chain2
|
# register chain1 on chain2
|
||||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
|
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "... creating egress packet on chain1"
|
echo "... creating egress packet on chain1"
|
||||||
|
|
|
@ -5,77 +5,34 @@ and how to send transactions between accounts using the `basecoin` tool.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Make sure you have [basecoin installed](install.md).
|
Installing basecoin is simple:
|
||||||
You will also need to [install Tendermint](https://tendermint.com/intro/getting-started/download).
|
|
||||||
|
|
||||||
**Note** All code is on the 0.9 pre-release branch, you may have to
|
```
|
||||||
[install Tendermint from source](https://tendermint.com/docs/guides/install)
|
go get -u github.com/tendermint/basecoin/cmd/basecoin
|
||||||
until 0.9 is released. (Make sure to add `git checkout develop` to the linked install instructions)
|
```
|
||||||
|
|
||||||
|
If you have trouble, see the [installation guide](install.md).
|
||||||
|
|
||||||
## Initialization
|
## Initialization
|
||||||
|
|
||||||
Basecoin is an ABCI application that runs on Tendermint, so we first need to initialize Tendermint:
|
To initialize a new Basecoin blockchain, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
tendermint init
|
basecoin init
|
||||||
```
|
```
|
||||||
|
|
||||||
This will create the necessary files for a single Tendermint node in `~/.tendermint`.
|
This will create the necessary files for a Basecoin blockchain with one validator and one account in `~/.basecoin`.
|
||||||
If you had previously run Tendermint, make sure you reset the chain
|
For more options on setup, see the [guide to using the Basecoin tool](/docs/guide/basecoin-tool.md).
|
||||||
(note this will delete all chain data, so back it up if you need it):
|
|
||||||
|
|
||||||
```
|
|
||||||
tendermint unsafe_reset_all
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we need some initialization files for basecoin.
|
|
||||||
We have included some defaults in the basecoin directory, under `data`.
|
|
||||||
For purposes of convenience, change to that directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd $GOPATH/src/github.com/tendermint/basecoin/data
|
|
||||||
```
|
|
||||||
|
|
||||||
The directory contains a genesis file and two private keys.
|
|
||||||
|
|
||||||
You can generate your own private keys with `tendermint gen_validator`,
|
|
||||||
and construct the `genesis.json` as you like.
|
|
||||||
Note, however, that you must be careful with the `chain_id` field,
|
|
||||||
as every transaction must contain the correct `chain_id`
|
|
||||||
(default is `test_chain_id`).
|
|
||||||
|
|
||||||
## Start
|
## Start
|
||||||
|
|
||||||
Now we can start basecoin:
|
Now we can start basecoin:
|
||||||
|
|
||||||
```
|
|
||||||
basecoin start --in-proc
|
|
||||||
```
|
|
||||||
|
|
||||||
This will initialize the chain with the `genesis.json` file from the current directory.
|
|
||||||
If you want to specify another location, you can run:
|
|
||||||
|
|
||||||
```
|
|
||||||
basecoin start --in-proc --dir PATH/TO/CUSTOM/DATA
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that `--in-proc` stands for "in process", which means
|
|
||||||
basecoin will be started with the Tendermint node running in the same process.
|
|
||||||
To start Tendermint in a separate process instead, use:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
basecoin start
|
basecoin start
|
||||||
```
|
```
|
||||||
|
|
||||||
and in another window:
|
You should see blocks start streaming in!
|
||||||
|
|
||||||
```
|
|
||||||
tendermint node
|
|
||||||
```
|
|
||||||
|
|
||||||
In either case, you should see blocks start streaming in!
|
|
||||||
Note, however, that currently basecoin currently requires the
|
|
||||||
`develop` branch of Tendermint for this to work.
|
|
||||||
|
|
||||||
## Send transactions
|
## Send transactions
|
||||||
|
|
||||||
|
@ -98,8 +55,7 @@ Let's send funds from the first account to the second:
|
||||||
basecoin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 10mycoin
|
basecoin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 10mycoin
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, the CLI looks for a `priv_validator.json` to sign the transaction with,
|
By default, the CLI looks for a `key.json` to sign the transaction with.
|
||||||
so this will only work if you are in the `$GOPATH/src/github.com/tendermint/basecoin/data`.
|
|
||||||
To specify a different key, we can use the `--from` flag.
|
To specify a different key, we can use the `--from` flag.
|
||||||
|
|
||||||
Now if we check the second account, it should have `10` 'mycoin' coins!
|
Now if we check the second account, it should have `10` 'mycoin' coins!
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
# The Basecoin Tool
|
||||||
|
|
||||||
|
In previous tutorials we learned the [basics of the `basecoin` CLI](/docs/guides/basecoin-basics)
|
||||||
|
and [how to implement a plugin](/docs/guides/example-plugin).
|
||||||
|
In this tutorial, we provide more details on using the `basecoin` tool.
|
||||||
|
|
||||||
|
# Data Directory
|
||||||
|
|
||||||
|
By default, `basecoin` works out of `~/.basecoin`. To change this, set the `BCHOME` environment variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
export BCHOME=~/.my_basecoin_data
|
||||||
|
basecoin init
|
||||||
|
basecoin start
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
BCHOME=~/.my_basecoin_data basecoin init
|
||||||
|
BCHOME=~/.my_basecoin_data basecoin start
|
||||||
|
```
|
||||||
|
|
||||||
|
# ABCI Server
|
||||||
|
|
||||||
|
So far we have run Basecoin and Tendermint in a single process.
|
||||||
|
However, since we use ABCI, we can actually run them in different processes.
|
||||||
|
First, initialize them:
|
||||||
|
|
||||||
|
```
|
||||||
|
basecoin init
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a single `genesis.json` file in `~/.basecoin` with the information for both Basecoin and Tendermint.
|
||||||
|
|
||||||
|
Now, In one window, run
|
||||||
|
|
||||||
|
```
|
||||||
|
basecoin start --without-tendermint
|
||||||
|
```
|
||||||
|
|
||||||
|
and in another,
|
||||||
|
|
||||||
|
```
|
||||||
|
TMROOT=~/.basecoin tendermint node
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see Tendermint start making blocks!
|
||||||
|
|
||||||
|
Alternatively, you could ignore the Tendermint details in `~/.basecoin/genesis.json` and use a separate directory by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
tendermint init
|
||||||
|
tendermint node
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details on using `tendermint`, see [the guide](https://tendermint.com/docs/guides/using-tendermint).
|
||||||
|
|
||||||
|
# Keys and Genesis
|
||||||
|
|
||||||
|
In previous tutorials we used `basecoin init` to initialize `~/.basecoin` with the default configuration.
|
||||||
|
This command creates files both for Tendermint and for Basecoin, and a single `genesis.json` file for both of them.
|
||||||
|
For more information on these files, see the [guide to using tendermint](https://tendermint.com/docs/guides/using-tendermint).
|
||||||
|
|
||||||
|
Now let's make our own custom Basecoin data.
|
||||||
|
|
||||||
|
First, create a new directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir example-data
|
||||||
|
```
|
||||||
|
|
||||||
|
We can tell `basecoin` to use this directory by exporting the `BCHOME` environment variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
export BCHOME=$(pwd)/example-data
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're going to be using multiple terminal windows, make sure to add this variable to your shell startup scripts (eg. `~/.bashrc`).
|
||||||
|
|
||||||
|
Now, let's create a new private key:
|
||||||
|
|
||||||
|
```
|
||||||
|
basecoin key new > $BCHOME/key.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's what my `key.json looks like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "4EGEhnqOw/gX326c7KARUkY1kic=",
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
|
||||||
|
},
|
||||||
|
"priv_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "654c845f4b36d1a881deb0ff09381165d3ccd156b4aabb5b51267e91f1d024a5a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Yours will look different - each key is randomly derrived.
|
||||||
|
|
||||||
|
Now we can make a `genesis.json` file and add an account with our public key:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"chain_id": "example-chain",
|
||||||
|
"app_options": {
|
||||||
|
"accounts": [{
|
||||||
|
"pub_key": {
|
||||||
|
"type": "ed25519",
|
||||||
|
"data": "a20d48b5caff42892d0ac67ccdeee38c1dcbbe42b15b486057d16244541e8141"
|
||||||
|
},
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "gold",
|
||||||
|
"amount": 1000000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we've granted ourselves `1000000000` units of the `gold` token.
|
||||||
|
Note that we've also set the `chain_id` to be `example-chain`.
|
||||||
|
All transactions must therefore include the `--chain_id example-chain` in order to make sure they are valid for this chain.
|
||||||
|
Previously, we didn't need this flag because we were using the default chain ID ("test_chain_id").
|
||||||
|
Now that we're using a custom chain, we need to specify the chain explicitly on the command line.
|
||||||
|
|
||||||
|
Note we have also left out the details of the tendermint genesis. These are documented in the [tendermint guide](https://tendermint.com/docs/guides/using-tendermint).
|
||||||
|
|
||||||
|
|
||||||
|
# Reset
|
||||||
|
|
||||||
|
You can reset all blockchain data by running:
|
||||||
|
|
||||||
|
```
|
||||||
|
basecoin unsafe_reset_all
|
||||||
|
```
|
|
@ -1,9 +1,8 @@
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
Up until this point, we have only been testing the code as a stand-alone abci app,
|
Up until this point, we have only been testing the code as a blockchain with a single validator node running locally.
|
||||||
which is nice for developing, but it is no blockchain. Just a blockchain-ready application.
|
This is nice for developing, but it's not a real distributed application yet.
|
||||||
|
|
||||||
This section will demonstrate how to launch your basecoin-based application along
|
This section will demonstrate how to launch your basecoin-based application along
|
||||||
with a tendermint testnet and initialize the genesis block for fun and profit.
|
with a tendermint testnet and initialize the genesis block for fun and profit.
|
||||||
|
We do this using the [mintnet-kubernetes tool](https://github.com/tendermint/mintnet-kubernetes).
|
||||||
**TODO** Maybe we link to a blog post for this???
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ main.go
|
||||||
plugin.go
|
plugin.go
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### main.go
|
||||||
|
|
||||||
The `main.go` is very simple and does not need to be changed:
|
The `main.go` is very simple and does not need to be changed:
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
|
@ -45,7 +47,7 @@ In addition, if we want to send transactions to our plugin,
|
||||||
we need to add a new command to the CLI.
|
we need to add a new command to the CLI.
|
||||||
This is where the `cmd.go` comes in.
|
This is where the `cmd.go` comes in.
|
||||||
|
|
||||||
## Commands
|
### cmd.go
|
||||||
|
|
||||||
First, we register the plugin:
|
First, we register the plugin:
|
||||||
|
|
||||||
|
@ -157,7 +159,7 @@ All plugin data must be serialized (ie. encoded as a byte-array)
|
||||||
and sent as data in an `AppTx`. The `commands.AppTx` function does this for us -
|
and sent as data in an `AppTx`. The `commands.AppTx` function does this for us -
|
||||||
it creates an `AppTx` with the corresponding data, signs it, and sends it on to the blockchain.
|
it creates an `AppTx` with the corresponding data, signs it, and sends it on to the blockchain.
|
||||||
|
|
||||||
## RunTx
|
### plugin.go
|
||||||
|
|
||||||
Ok, now we're ready to actually look at the implementation of the plugin in `plugin.go`.
|
Ok, now we're ready to actually look at the implementation of the plugin in `plugin.go`.
|
||||||
Note I'll leave out some of the methods as they don't serve any purpose for this example,
|
Note I'll leave out some of the methods as they don't serve any purpose for this example,
|
||||||
|
@ -296,94 +298,42 @@ And that's it! Now that we have a simple plugin, let's see how to run it.
|
||||||
|
|
||||||
## Running your plugin
|
## Running your plugin
|
||||||
|
|
||||||
In the [previous tutorial](basecoin-basics.md),
|
First, initialize the new blockchain with
|
||||||
we used a pre-generated `genesis.json` and `priv_validator.json` for the application.
|
|
||||||
This time, let's make our own.
|
|
||||||
|
|
||||||
First, let's create a new directory and change into it:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
mkdir example-data
|
basecoin init
|
||||||
cd example-data
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, let's create a new private key:
|
If you've already run a basecoin blockchain, reset the data with
|
||||||
|
|
||||||
```
|
```
|
||||||
example-plugin key new > key.json
|
basecoin unsafe_reset_all
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's what my `key.json looks like:
|
To start the blockchain with your new plugin, simply run
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"address": "15F591CA434CFCCBDEC1D206F3ED3EBA207BFE7D",
|
|
||||||
"priv_key": [
|
|
||||||
1,
|
|
||||||
"737C629667A9EAADBB8E7CF792D5A8F63AA4BB51E06457DDD7FDCC6D7412AAAD43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"
|
|
||||||
],
|
|
||||||
"pub_key": [
|
|
||||||
1,
|
|
||||||
"43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we can make a `genesis.json` file and add an account with out public key:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
"base/chainID", "example-chain",
|
|
||||||
"base/account", {
|
|
||||||
"pub_key": [1, "43AA6C88034F9EB8D2717CA4BBFCBA745EFF19B13EFCD6F339EDBAAAFCD2F7B3"],
|
|
||||||
"coins": [
|
|
||||||
{
|
|
||||||
"denom": "gold",
|
|
||||||
"amount": 1000000000,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Here we've granted ourselves `1000000000` units of the `gold` token.
|
|
||||||
|
|
||||||
Before we can start the blockchain, we must initialize and/or reset the Tendermint state for a new blockchain:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
tendermint init
|
example-plugin start
|
||||||
tendermint unsafe_reset_all
|
|
||||||
```
|
|
||||||
|
|
||||||
Great, now we're ready to go.
|
|
||||||
To start the blockchain, simply run
|
|
||||||
|
|
||||||
```
|
|
||||||
example-plugin start --in-proc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In another window, we can try sending some transactions:
|
In another window, we can try sending some transactions:
|
||||||
|
|
||||||
```
|
```
|
||||||
example-plugin tx send --to 0x1B1BE55F969F54064628A63B9559E7C21C925165 --amount 100gold --chain_id example-chain
|
example-plugin tx send --to 0x1DA7C74F9C219229FD54CC9F7386D5A3839F0090 --amount 100mycoin
|
||||||
```
|
```
|
||||||
|
|
||||||
Note the `--chain_id` flag. In the [previous tutorial](basecoin-basics.md),
|
|
||||||
we didn't include it because we were using the default chain ID ("test_chain_id").
|
|
||||||
Now that we're using a custom chain, we need to specify the chain explicitly on the command line.
|
|
||||||
|
|
||||||
Ok, so that's how we can send a `SendTx` transaction using our `example-plugin` CLI,
|
Ok, so that's how we can send a `SendTx` transaction using our `example-plugin` CLI,
|
||||||
but we were already able to do that with the `basecoin` CLI.
|
but we were already able to do that with the `basecoin` CLI.
|
||||||
With our new CLI, however, we can also send an `ExamplePluginTx`:
|
With our new CLI, however, we can also send an `ExamplePluginTx`:
|
||||||
|
|
||||||
```
|
```
|
||||||
example-plugin tx example --amount 1gold --chain_id example-chain
|
example-plugin tx example --amount 1mycoin
|
||||||
```
|
```
|
||||||
|
|
||||||
The transaction is invalid! That's because we didn't specify the `--valid` flag:
|
The transaction is invalid! That's because we didn't specify the `--valid` flag:
|
||||||
|
|
||||||
```
|
```
|
||||||
example-plugin tx example --valid --amount 1gold --chain_id example-chain
|
example-plugin tx example --valid --amount 1mycoin
|
||||||
```
|
```
|
||||||
|
|
||||||
Tada! We successfuly created, signed, broadcast, and processed our custom transaction type.
|
Tada! We successfuly created, signed, broadcast, and processed our custom transaction type.
|
||||||
|
@ -403,13 +353,13 @@ which contains only an integer.
|
||||||
If we send another transaction, and then query again, we'll see the value increment:
|
If we send another transaction, and then query again, we'll see the value increment:
|
||||||
|
|
||||||
```
|
```
|
||||||
example-plugin tx example --valid --amount 1gold --chain_id example-chain
|
example-plugin tx example --valid --amount 1mycoin
|
||||||
example-plugin query ExamplePlugin.State
|
example-plugin query ExamplePlugin.State
|
||||||
```
|
```
|
||||||
|
|
||||||
Neat, right? Notice how the result of the query comes with a proof.
|
Neat, right? Notice how the result of the query comes with a proof.
|
||||||
This is a Merkle proof that the state is what we say it is.
|
This is a Merkle proof that the state is what we say it is.
|
||||||
In a latter [tutorial on Interblockchain Communication](ibc.md),
|
In a latter [tutorial on InterBlockchain Communication](ibc.md),
|
||||||
we'll put this proof to work!
|
we'll put this proof to work!
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
@ -419,5 +369,5 @@ basecoin CLI to activate the plugin on the blockchain and to send transactions t
|
||||||
Hopefully by now you have some ideas for your own plugin, and feel comfortable implementing them.
|
Hopefully by now you have some ideas for your own plugin, and feel comfortable implementing them.
|
||||||
|
|
||||||
In the [next tutorial](more-examples.md), we tour through some other plugin examples,
|
In the [next tutorial](more-examples.md), we tour through some other plugin examples,
|
||||||
adding features for minting new coins, voting, and changin the Tendermint validator set.
|
adding features for minting new coins, voting, and changing the Tendermint validator set.
|
||||||
But first, you may want to learn a bit more about [the design of the plugin system](plugin-design.md)
|
But first, you may want to learn a bit more about [the design of the plugin system](plugin-design.md)
|
||||||
|
|
|
@ -194,15 +194,15 @@ The relevant data is now in the `data` directory.
|
||||||
We can start the two chains as follows:
|
We can start the two chains as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
TMROOT=./data/chain1/tendermint tendermint node &> chain1_tendermint.log &
|
TMROOT=./data/chain1 tendermint node &> chain1_tendermint.log &
|
||||||
basecoin start --dir ./data/chain1/basecoin &> chain1_basecoin.log &
|
BCHOME=./data/chain1 basecoin start --without-tendermint &> chain1_basecoin.log &
|
||||||
```
|
```
|
||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
```
|
```
|
||||||
TMROOT=./data/chain2/tendermint tendermint node --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> chain2_tendermint.log &
|
TMROOT=./data/chain2 tendermint node --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> chain2_tendermint.log &
|
||||||
basecoin start --address tcp://localhost:36658 --dir ./data/chain2/basecoin &> chain2_basecoin.log &
|
BCHOME=./data/chain2 basecoin start --without-tendermint --address tcp://localhost:36658 &> chain2_basecoin.log &
|
||||||
```
|
```
|
||||||
|
|
||||||
Note how we refer to the relevant data directories. Also note how we have to set the various addresses for the second node so as not to conflict with the first.
|
Note how we refer to the relevant data directories. Also note how we have to set the various addresses for the second node so as not to conflict with the first.
|
||||||
|
@ -224,14 +224,16 @@ For the sake of convenience, let's first set some environment variables:
|
||||||
export CHAIN_ID1=test_chain_1
|
export CHAIN_ID1=test_chain_1
|
||||||
export CHAIN_ID2=test_chain_2
|
export CHAIN_ID2=test_chain_2
|
||||||
|
|
||||||
export CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/basecoin/key.json"
|
export CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/key.json"
|
||||||
export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/key.json --node tcp://localhost:36657"
|
export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/key.json --node tcp://localhost:36657"
|
||||||
|
|
||||||
|
export BCHOME="."
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's start by registering `test_chain_1` on `test_chain_2`:
|
Let's start by registering `test_chain_1` on `test_chain_2`:
|
||||||
|
|
||||||
```
|
```
|
||||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
|
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/genesis.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we can create the outgoing packet on `test_chain_1`:
|
Now we can create the outgoing packet on `test_chain_1`:
|
||||||
|
@ -275,10 +277,10 @@ along with proof the packet was committed on `test_chain_1`. Since `test_chain_2
|
||||||
of `test_chain_1`, it will be able to verify the proof!
|
of `test_chain_1`, it will be able to verify the proof!
|
||||||
|
|
||||||
```
|
```
|
||||||
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height + 1> --packet 0x<packet> --proof 0x<proof>
|
basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height> --packet 0x<packet> --proof 0x<proof>
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, `<height + 1>` is one greater than the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
|
Here, `<height>` is the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
|
||||||
`value` and `proof` returned in that same query.
|
`value` and `proof` returned in that same query.
|
||||||
|
|
||||||
Tada!
|
Tada!
|
||||||
|
|
|
@ -8,16 +8,17 @@ go get -u github.com/tendermint/basecoin/cmd/basecoin
|
||||||
|
|
||||||
In some cases, if that fails, or if another branch is required,
|
In some cases, if that fails, or if another branch is required,
|
||||||
we use `glide` for dependency management.
|
we use `glide` for dependency management.
|
||||||
|
Thus, assuming you've already run `go get` or otherwise cloned the repo,
|
||||||
The correct way of compiling from source, assuming you've already
|
the correct way to install is:
|
||||||
run `go get` or otherwise cloned the repo, is:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
cd $GOPATH/src/github.com/tendermint/basecoin
|
cd $GOPATH/src/github.com/tendermint/basecoin
|
||||||
git checkout develop # (until we release v0.9)
|
|
||||||
make get_vendor_deps
|
make get_vendor_deps
|
||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
This will create the `basecoin` binary in `$GOPATH/bin`.
|
This will create the `basecoin` binary in `$GOPATH/bin`.
|
||||||
|
Note the `make get_vendor_deps` command will install `glide` and the correct version of all dependencies.
|
||||||
|
|
||||||
|
If you need another branch, make sure to run `git checkout <branch>` before the `make` commands.
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
# Plugin Examples
|
# Plugin Examples
|
||||||
|
|
||||||
Now that we've seen [how to write a simple plugin](example-plugin.md)
|
Now that we've seen [how to write a simple plugin](/docs/guide/example-plugin.md)
|
||||||
and taken a look at [how the plugin system is designed](plugin-design.md),
|
and taken a look at [how the plugin system is designed](/docs/guide/plugin-design.md),
|
||||||
it's time for some more advanced examples.
|
it's time for some more advanced examples.
|
||||||
|
|
||||||
For now, most examples are contained in the `github.com/tendermint/basecoin-examples` repository.
|
For now, most examples are contained in the `github.com/tendermint/basecoin-examples` repository.
|
||||||
In particular, we have the following:
|
In particular, we have the following:
|
||||||
|
|
||||||
1. [Mintcoin][0] - a plugin for issuing new Basecoin tokens
|
1. [Mintcoin](https://github.com/tendermint/basecoin-examples/tree/develop/mintcoin) - a plugin for issuing new Basecoin tokens
|
||||||
2. [Trader][1] - a plugin for adding escrow and options features to Basecoin
|
2. [Trader](https://github.com/tendermint/basecoin-examples/tree/develop/trader) - a plugin for adding escrow and options features to Basecoin
|
||||||
3. [Stakecoin][2] - a plugin for bonding and unbonding Tendermint validators and updating the validator set accordingly
|
3. [Stakecoin](https://github.com/tendermint/basecoin-examples/tree/develop/stake) - a plugin for bonding and unbonding Tendermint validators and updating the validator set accordingly
|
||||||
4. [PayToVote][3] - a plugin for creating issues and voting on them
|
4. [PayToVote](https://github.com/tendermint/basecoin-examples/tree/develop/paytovote) - a plugin for creating issues and voting on them
|
||||||
5. [IBC][4] - a plugin for facilitating InterBlockchain Communication
|
5. [IBC](/docs/guide/ibc.md) - a plugin for facilitating InterBlockchain Communication
|
||||||
[0]: https://github.com/tendermint/basecoin-examples/tree/develop/mintcoin
|
|
||||||
[1]: https://github.com/tendermint/basecoin-examples/tree/develop/trader
|
|
||||||
[2]: https://github.com/tendermint/basecoin-examples/tree/develop/stake
|
|
||||||
[3]: https://github.com/tendermint/basecoin-examples/tree/develop/paytovote
|
|
||||||
[4]: ibc.md
|
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
hash: 3869944d14a8df914ffcad02c2ef3548173daba51c5ea697767f8af77c07b348
|
hash: c71c0d6c409bfddb4c4b471d8445f59cebd2cd41e1635a90d6facd81bd09a5e0
|
||||||
updated: 2017-03-06T05:37:03.828355251-05:00
|
updated: 2017-03-14T17:02:44.512359631-04:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/btcsuite/btcd
|
- name: github.com/btcsuite/btcd
|
||||||
version: d06c0bb181529331be8f8d9350288c420d9e60e4
|
version: 583684b21bfbde9b5fc4403916fd7c807feb0289
|
||||||
subpackages:
|
subpackages:
|
||||||
- btcec
|
- btcec
|
||||||
- name: github.com/BurntSushi/toml
|
- name: github.com/BurntSushi/toml
|
||||||
version: 99064174e013895bbd9b025c31100bd1d9b590ca
|
version: e643e9ef00b049d75de26e61109c5ea01885cd21
|
||||||
- name: github.com/ebuchman/fail-test
|
- name: github.com/ebuchman/fail-test
|
||||||
version: 13f91f14c826314205cdbed1ec8ac8bf08e03381
|
version: 95f809107225be108efcf10a3509e4ea6ceef3c4
|
||||||
- name: github.com/go-stack/stack
|
- name: github.com/go-stack/stack
|
||||||
version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82
|
version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82
|
||||||
- name: github.com/golang/protobuf
|
- name: github.com/golang/protobuf
|
||||||
version: 8ee79997227bf9b34611aee7946ae64735e6fd93
|
version: c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
|
||||||
subpackages:
|
subpackages:
|
||||||
- proto
|
- proto
|
||||||
- name: github.com/golang/snappy
|
- name: github.com/golang/snappy
|
||||||
version: d9eb7a3d35ec988b8585d4a0068e462c27d28380
|
version: 553a641470496b2327abcac10b36396bd98e45c9
|
||||||
- name: github.com/gorilla/websocket
|
- name: github.com/gorilla/websocket
|
||||||
version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
|
version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
|
||||||
- name: github.com/jmhodges/levigo
|
- name: github.com/jmhodges/levigo
|
||||||
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
|
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
|
||||||
- name: github.com/mattn/go-colorable
|
- name: github.com/mattn/go-colorable
|
||||||
version: d228849504861217f796da67fae4f6e347643f15
|
version: a392f450ea64cee2b268dfaacdc2502b50a22b18
|
||||||
- name: github.com/mattn/go-isatty
|
- name: github.com/mattn/go-isatty
|
||||||
version: 30a891c33c7cde7b02a981314b4228ec99380cca
|
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
|
||||||
- name: github.com/pkg/errors
|
- name: github.com/pkg/errors
|
||||||
version: 645ef00459ed84a119197bfb8d8205042c6df63d
|
version: bfd5150e4e41705ded2129ec33379de1cb90b513
|
||||||
- name: github.com/syndtr/goleveldb
|
- name: github.com/syndtr/goleveldb
|
||||||
version: 23851d93a2292dcc56e71a18ec9e0624d84a0f65
|
version: 3c5717caf1475fd25964109a0fc640bd150fce43
|
||||||
subpackages:
|
subpackages:
|
||||||
- leveldb
|
- leveldb
|
||||||
- leveldb/cache
|
- leveldb/cache
|
||||||
|
@ -43,7 +43,7 @@ imports:
|
||||||
- leveldb/table
|
- leveldb/table
|
||||||
- leveldb/util
|
- leveldb/util
|
||||||
- name: github.com/tendermint/abci
|
- name: github.com/tendermint/abci
|
||||||
version: 1236e8fb6eee3a63909f4014a8e84385ead7933d
|
version: af792eac777de757cd496349a5f6b5313738fcbc
|
||||||
subpackages:
|
subpackages:
|
||||||
- client
|
- client
|
||||||
- example/dummy
|
- example/dummy
|
||||||
|
@ -117,7 +117,7 @@ imports:
|
||||||
- name: github.com/urfave/cli
|
- name: github.com/urfave/cli
|
||||||
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
|
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
|
||||||
- name: golang.org/x/crypto
|
- name: golang.org/x/crypto
|
||||||
version: 7c6cc321c680f03b9ef0764448e780704f486b51
|
version: 728b753d0135da6801d45a38e6f43ff55779c5c2
|
||||||
subpackages:
|
subpackages:
|
||||||
- curve25519
|
- curve25519
|
||||||
- nacl/box
|
- nacl/box
|
||||||
|
@ -128,7 +128,7 @@ imports:
|
||||||
- ripemd160
|
- ripemd160
|
||||||
- salsa20/salsa
|
- salsa20/salsa
|
||||||
- name: golang.org/x/net
|
- name: golang.org/x/net
|
||||||
version: 61557ac0112b576429a0df080e1c2cef5dfbb642
|
version: a6577fac2d73be281a500b310739095313165611
|
||||||
subpackages:
|
subpackages:
|
||||||
- context
|
- context
|
||||||
- http2
|
- http2
|
||||||
|
@ -138,16 +138,17 @@ imports:
|
||||||
- lex/httplex
|
- lex/httplex
|
||||||
- trace
|
- trace
|
||||||
- name: golang.org/x/sys
|
- name: golang.org/x/sys
|
||||||
version: d75a52659825e75fff6158388dddc6a5b04f9ba5
|
version: 99f16d856c9836c42d24e7ab64ea72916925fa97
|
||||||
subpackages:
|
subpackages:
|
||||||
- unix
|
- unix
|
||||||
- name: google.golang.org/grpc
|
- name: google.golang.org/grpc
|
||||||
version: cbcceb2942a489498cf22b2f918536e819d33f0a
|
version: 0713829b980f4ddd276689a36235c5fcc82a21bf
|
||||||
subpackages:
|
subpackages:
|
||||||
- codes
|
- codes
|
||||||
- credentials
|
- credentials
|
||||||
- grpclog
|
- grpclog
|
||||||
- internal
|
- internal
|
||||||
|
- keepalive
|
||||||
- metadata
|
- metadata
|
||||||
- naming
|
- naming
|
||||||
- peer
|
- peer
|
||||||
|
|
18
glide.yaml
18
glide.yaml
|
@ -1,22 +1,22 @@
|
||||||
package: github.com/tendermint/basecoin
|
package: github.com/tendermint/basecoin
|
||||||
import:
|
import:
|
||||||
- package: github.com/tendermint/go-common
|
- package: github.com/tendermint/go-common
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/go-crypto
|
- package: github.com/tendermint/go-crypto
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/go-events
|
- package: github.com/tendermint/go-events
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/go-logger
|
- package: github.com/tendermint/go-logger
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/go-rpc
|
- package: github.com/tendermint/go-rpc
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/go-wire
|
- package: github.com/tendermint/go-wire
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/merkleeyes
|
- package: github.com/tendermint/merkleeyes
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/tendermint
|
- package: github.com/tendermint/tendermint
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/tendermint/abci
|
- package: github.com/tendermint/abci
|
||||||
version: develop
|
version: master
|
||||||
- package: github.com/gorilla/websocket
|
- package: github.com/gorilla/websocket
|
||||||
version: v1.1.0
|
version: v1.1.0
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestCounterPlugin(t *testing.T) {
|
||||||
eyesCli := eyescli.NewLocalClient("", 0)
|
eyesCli := eyescli.NewLocalClient("", 0)
|
||||||
chainID := "test_chain_id"
|
chainID := "test_chain_id"
|
||||||
bcApp := app.NewBasecoin(eyesCli)
|
bcApp := app.NewBasecoin(eyesCli)
|
||||||
bcApp.SetOption("base/chainID", chainID)
|
bcApp.SetOption("base/chain_id", chainID)
|
||||||
// t.Log(bcApp.Info())
|
// t.Log(bcApp.Info())
|
||||||
|
|
||||||
// Add Counter plugin
|
// Add Counter plugin
|
||||||
|
|
|
@ -28,12 +28,14 @@ func NewState(store types.KVStore) *State {
|
||||||
|
|
||||||
func (s *State) SetChainID(chainID string) {
|
func (s *State) SetChainID(chainID string) {
|
||||||
s.chainID = chainID
|
s.chainID = chainID
|
||||||
|
s.store.Set([]byte("base/chain_id"), []byte(chainID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) GetChainID() string {
|
func (s *State) GetChainID() string {
|
||||||
if s.chainID == "" {
|
if s.chainID != "" {
|
||||||
PanicSanity("Expected to have set SetChainID")
|
return s.chainID
|
||||||
}
|
}
|
||||||
|
s.chainID = string(s.store.Get([]byte("base/chain_id")))
|
||||||
return s.chainID
|
return s.chainID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ func TestSendTx(t *testing.T) {
|
||||||
eyesCli := eyescli.NewLocalClient("", 0)
|
eyesCli := eyescli.NewLocalClient("", 0)
|
||||||
chainID := "test_chain_id"
|
chainID := "test_chain_id"
|
||||||
bcApp := app.NewBasecoin(eyesCli)
|
bcApp := app.NewBasecoin(eyesCli)
|
||||||
bcApp.SetOption("base/chainID", chainID)
|
bcApp.SetOption("base/chain_id", chainID)
|
||||||
// t.Log(bcApp.Info())
|
// t.Log(bcApp.Info())
|
||||||
|
|
||||||
test1PrivAcc := types.PrivAccountFromSecret("test1")
|
test1PrivAcc := types.PrivAccountFromSecret("test1")
|
||||||
|
@ -64,7 +64,7 @@ func TestSequence(t *testing.T) {
|
||||||
eyesCli := eyescli.NewLocalClient("", 0)
|
eyesCli := eyescli.NewLocalClient("", 0)
|
||||||
chainID := "test_chain_id"
|
chainID := "test_chain_id"
|
||||||
bcApp := app.NewBasecoin(eyesCli)
|
bcApp := app.NewBasecoin(eyesCli)
|
||||||
bcApp.SetOption("base/chainID", chainID)
|
bcApp.SetOption("base/chain_id", chainID)
|
||||||
// t.Log(bcApp.Info())
|
// t.Log(bcApp.Info())
|
||||||
|
|
||||||
// Get the test account
|
// Get the test account
|
||||||
|
|
|
@ -152,7 +152,7 @@ func (tx *SendTx) SignBytes(chainID string) []byte {
|
||||||
signBytes := wire.BinaryBytes(chainID)
|
signBytes := wire.BinaryBytes(chainID)
|
||||||
sigz := make([]crypto.Signature, len(tx.Inputs))
|
sigz := make([]crypto.Signature, len(tx.Inputs))
|
||||||
for i, input := range tx.Inputs {
|
for i, input := range tx.Inputs {
|
||||||
sigz[i] = input.Signature
|
sigz[i] = input.Signature.Signature
|
||||||
tx.Inputs[i].Signature.Signature = nil
|
tx.Inputs[i].Signature.Signature = nil
|
||||||
}
|
}
|
||||||
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
|
signBytes = append(signBytes, wire.BinaryBytes(tx)...)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package version
|
package version
|
||||||
|
|
||||||
const Maj = "0"
|
const Maj = "0"
|
||||||
const Min = "2"
|
const Min = "3"
|
||||||
const Fix = "0"
|
const Fix = "0"
|
||||||
|
|
||||||
const Version = Maj + "." + Min + "." + Fix
|
const Version = Maj + "." + Min + "." + Fix
|
||||||
|
|
Loading…
Reference in New Issue