Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Bazo Blockchain truly permissionless #26

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d870851
simplify start with --dataDir parameter
rmnblm Nov 18, 2018
2d4ee4b
r/w storage functions for accounts
rmnblm Nov 18, 2018
48dd545
refactor 32 byte hash to 64 byte pub key
rmnblm Nov 19, 2018
76ee283
store accounts by address
rmnblm Nov 20, 2018
eb5d70c
fix VM tests for updated addreses
rmnblm Nov 20, 2018
db81727
accounts are created if they do not exist yet
rmnblm Nov 20, 2018
2084b63
Update .gitignore
rmnblm Nov 20, 2018
e99df63
remove root* parameters
rmnblm Nov 20, 2018
286c72f
Merge branch 'aduno_copy-cherry-picks' into no-root
rmnblm Nov 20, 2018
92e7030
Fix failing tests after merge
rmnblm Nov 20, 2018
a218984
WIP: make setting up nodes easier
rmnblm Nov 20, 2018
1ef6a98
format CLI output
rmnblm Nov 21, 2018
8a428c4
remove named paramters in struct
rmnblm Nov 21, 2018
8b47a19
cleanup duplicated code :sparkles:
rmnblm Nov 21, 2018
9e6690b
beautify and cleanup storage code :nail_care:
rmnblm Nov 21, 2018
56fb685
verifying funds now jsut uses the sender's and receiver's PubKey
rmnblm Nov 21, 2018
0cb8623
rolling back the state deletes created accounts
rmnblm Nov 21, 2018
ad3058c
add non-existing accounts found in FundsTx to state
rmnblm Nov 21, 2018
ba253b7
do not remove any accounts in state rollback validation
rmnblm Nov 21, 2018
f3ab42e
add new accounts to StateCopy
rmnblm Nov 21, 2018
b6235e1
refactor reading accounts from storage
rmnblm Nov 22, 2018
d27e317
implement Genesis struct
rmnblm Nov 22, 2018
cbc7f09
update storage to r/w Genesis
rmnblm Nov 22, 2018
5b9e882
implement Genesis req/res in p2p
rmnblm Nov 22, 2018
5ffb53c
refactor duplicated code :sparkles:
rmnblm Nov 23, 2018
935b01d
change property order
rmnblm Nov 23, 2018
9c5dffc
rename variable
rmnblm Nov 23, 2018
3ffc89a
forward genesis requests to miner
rmnblm Nov 23, 2018
46716dc
fix missing return statement
rmnblm Nov 23, 2018
7381735
initialize state with Genesis
rmnblm Nov 23, 2018
48865e4
add String() method
rmnblm Nov 23, 2018
05ad0c8
improve cli and make startup easier
rmnblm Nov 23, 2018
9ef66f3
improve error message
rmnblm Nov 23, 2018
7a38485
fix verifyStakeTx when account does not exist in state
rmnblm Nov 23, 2018
1bd2674
timeout when new miner is not part of the state
rmnblm Nov 23, 2018
a446797
Update README.md
rmnblm Nov 23, 2018
6e7a0f3
Update README.md
rmnblm Nov 24, 2018
c8050af
fix failing tests pt. 1 :white_check_mark:
rmnblm Nov 27, 2018
96094e4
delete accounts with balance zero
rmnblm Nov 27, 2018
2d79f6c
remove multisig :bomb:
rmnblm Nov 27, 2018
7e1e61f
Oops, fix erroneous if-Statement
rmnblm Nov 28, 2018
19d17b2
remove Accounts bucket (not needed anymore)
rmnblm Nov 28, 2018
586b0ee
rename AccTx to ContractTx
rmnblm Nov 28, 2018
fb9ac01
rename ACCTX_RES/REQ to CONTRACTTX_RES/REQ
rmnblm Nov 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@

# Put commitment key, miner databases and other stuff that should not be visible
# to others into the folder tmp.
keystore/
Node*/
bazo-miner
71 changes: 42 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,9 @@ bazo-miner start [command options] [arguments...]
```

Options
* `--database`: (default store.db) Specify where to load database of the disk-based key/value store from. The database is created if it does not exist yet.
* `--address`: (default: localhost:8000) Specify starting address and port, in format `IP:PORT`
* `--bootstrap`: (default: localhost:8000) Specify the address and port of the boostrapping node. Note that when this option is not specified, the miner connects to itself.
* `--wallet`: (default: wallet.txt) Load the public key from this file. A new private key is generated if it does not exist yet. Note that only the public key is required.
* `--multisig`: (optional) The file to load the multisig's private key from.
* `--commitment`: The file to load the validator's commitment key from (will be created if it does not exist)
* `--rootkey`: (default: key.txt) The file to load root's public key from this file. A new public private key is generated if it does not exist yet. Note that only the public key is required.
* `--rootcommitment`: The file to load root's commitment key from. A new commitment key is generated if it does not exist yet.
* `--dataDir`: (default: bazodata) Data directory for the database (store.db) and keystore (wallet.key, commitment.key). Database and keys are generated if they do not exist yet.
* `--confirm`: In order to review the miner startup options, the user must press Enter before the miner starts.

Example
Expand All @@ -46,62 +41,80 @@ Let's assume we want to start two miners, miner `A` and miner `B`, whereas miner
Further assume that we start from scratch and no key files have been created yet.

Miner A (Root)
* Database: `StoreA.db`
* Data Directory: `NodeA`, contains `wallet.key`, `commitment.key` and `store.db`
* Address: `localhost:8000`
* Bootstrap Address: `localhost:8000`
* Wallet: `WalletA.txt`
* Commitment: `CommitmentA.txt`
* Root Wallet: `WalletA.txt`
* Root Commitment: `CommitmentA.txt`


Miner B
* Database: `StoreB.db`
* Data Directory: `NodeB`, contains `wallet.key`, `commitment.key` and `store.db`
* Address: `localhost:8001`
* Bootstrap Address: `localhost:8000`
* Wallet: `WalletB.txt`
* Commitment: `CommitmentB.txt`

Commands

```bash
./bazo-miner start --database StoreA.db --address localhost:8000 --bootstrap localhost:8000 --wallet WalletA.txt --commitment CommitmentA.txt --multisig WalletA.txt --rootwallet WalletA.txt --rootcommitment CommitmentA.txt
./bazo-miner start --dataDir NodeA --address localhost:8000 --bootstrap localhost:8000
```

We start miner A at address and port `localhost:8000` and connect to itself by setting the bootstrap address to the same address.
Note that we could have omitted these two options since they are passed by default with these values.
Wallet and commitment keys are automatically created. Using this command, we define miner A as the root.

Starting miner B requires more work since new accounts have to be registered by a root account.
In our case, we can use miner's A `WalletA.txt` (e.g. copy the file to the Bazo client directory) to create and add a new account to the network.
Using the [Bazo client](https://github.com/bazo-blockchain/bazo-client), we create a new account:
In a second terminal, run

```bash
./bazo-client account create --rootwallet WalletA.txt --wallet WalletB.txt
./bazo-miner start --dataDir NodeB --address localhost:8001 --bootstrap localhost:8000
```

The minimum amount of coins required for staking is defined in the configuration of Bazo.
Thus, miner B first needs Bazo coins to start mining and we must first send coins to miner B's account.
Notice how miner B ist started at address and port `localhost:8001` but bootstraps to miner A.
Running this command will give you an error message, i.e.,

```bash
./bazo-client funds --from WalletA.txt --to WalletB.txt --txcount 0 --amount 2000 --multisig WalletA.txt
Acc (...) not in the state.
```

Then, miner B has to join the pool of validators (enable staking):
Starting miner B requires more work since every miner must have sufficient funds and be part of the set of validators.
The minimum amount of coins required for staking is defined in the configuration of Bazo.

Our current Bazo miner directory should look like this:

```
bazo-miner (root folder)
-- NodeA
---- wallet.key
---- commitment.key
---- store.db
-- NodeB
---- wallet.key
---- commitment.key
---- store.db
-- bazo-miner (executable)
```

In our case, we can use the wallet of miner A wallet to move funds to miner B.
* Copy `wallet.key` from the directory `NodeA` to the Bazo client directory and rename the file to `WalletA.key`.
* Copy `wallet.key` and `commitment.key` from the directory `NodeB` to the Bazo client directory and rename the file to `WalletB.key` and `CommitmentB.key` respectively.

Using the [Bazo client](https://github.com/bazo-blockchain/bazo-client), we transfer 2000 coins from A to B:

```bash
./bazo-client staking enable --wallet WalletB.txt --commitment CommitmentB.txt
./bazo-client funds --from WalletA.key --to WalletB.key --txcount 0 --amount 2000
```

Start miner B, using the generated `WalletB.txt` and `CommitmentB.txt` (e.g. copy the files to the Bazo miner directory):
Check the terminal of miner B. The error message should change to (may need some time until the FundsTx is validated)

```bash
./bazo-miner start --database StoreB.db --address localhost:8001 --bootstrap localhost:8000 --wallet WalletB.txt --commitment CommitmentB.txt --rootwallet WalletA.txt --rootcommitment CommitmentA.txt
Validator (...) is not part of the validator set.
```

Note that both files specified for `--rootwallet` and `--rootcommitment` only require to contain the wallet and commitemt public key respectively.
Now, miner B has to join the pool of validators (enable staking):

```bash
./bazo-client staking enable --wallet WalletB.key --commitment CommitmentB.key
```

We start miner B at address and port `localhost:8001` and connect to miner A (which is the boostrap node).
Wallet and commitment keys are automatically created.
Again, check miner B's terminal. After some time, miner B should validate and create blocks automatically.

### Generate a wallet

Expand Down
187 changes: 61 additions & 126 deletions cli/start.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
package cli

import (
"crypto/ecdsa"
"fmt"
"os"

"github.com/bazo-blockchain/bazo-miner/crypto"
"github.com/bazo-blockchain/bazo-miner/miner"
"github.com/bazo-blockchain/bazo-miner/p2p"
"github.com/bazo-blockchain/bazo-miner/storage"
"github.com/pkg/errors"
"github.com/urfave/cli"
"log"
)

type startArgs struct {
dbname string
myNodeAddress string
bootstrapNodeAddress string
walletFile string
multisigFile string
commitmentFile string
rootKeyFile string
rootCommitmentFile string
dataDirectory string
myNodeAddress string
bootstrapNodeAddress string
}

func GetStartCommand(logger *log.Logger) cli.Command {
return cli.Command {
Name: "start",
Usage: "start the miner",
Action: func(c *cli.Context) error {
args := &startArgs {
dbname: c.String("database"),
myNodeAddress: c.String("address"),
func GetStartCommand() cli.Command {
return cli.Command{
Name: "start",
Usage: "start the miner",
Action: func(c *cli.Context) error {
args := &startArgs{
dataDirectory: c.String("dataDir"),
myNodeAddress: c.String("address"),
bootstrapNodeAddress: c.String("bootstrap"),
walletFile: c.String("wallet"),
multisigFile: c.String("multisig"),
commitmentFile: c.String("commitment"),
rootKeyFile: c.String("rootwallet"),
rootCommitmentFile: c.String("rootcommitment"),
}

if !c.IsSet("bootstrap") {
Expand All @@ -54,102 +44,74 @@ func GetStartCommand(logger *log.Logger) cli.Command {
fmt.Scanf("\n")
}

return Start(args, logger)
return Start(args)
},
Flags: []cli.Flag {
cli.StringFlag {
Name: "database, d",
Usage: "load database of the disk-based key/value store from `FILE`",
Value: "store.db",
},
cli.StringFlag {
Name: "address, a",
Usage: "start node at `IP:PORT`",
Value: "localhost:8000",
},
cli.StringFlag {
Name: "bootstrap, b",
Usage: "connect to bootstrap node at `IP:PORT`",
Value: "localhost:8000",
},
cli.StringFlag {
Name: "wallet, w",
Usage: "load validator's public key from `FILE`",
Value: "wallet.txt",
},
cli.StringFlag {
Name: "multisig, m",
Usage: "load multi-signature server’s public key from `FILE`",
Flags: []cli.Flag{
cli.StringFlag{
Name: "dataDir, d",
Usage: "Data directory for the database and keystore",
Value: "NodeA",
},
cli.StringFlag {
Name: "commitment, c",
Usage: "load validator's RSA public-private key from `FILE`",
Value: "commitment.txt",
cli.StringFlag{
Name: "address, a",
Usage: "Start node at `IP:PORT`",
Value: "localhost:8000",
},
cli.StringFlag {
Name: "rootwallet",
Usage: "load root's public key from `FILE`",
Value: "wallet.txt",
cli.StringFlag{
Name: "bootstrap, b",
Usage: "Connect to bootstrap node at `IP:PORT`",
Value: "localhost:8000",
},
cli.StringFlag {
Name: "rootcommitment",
Usage: "load root's RSA public-private key from `FILE`",
Value: "commitment.txt",
},
cli.BoolFlag {
Name: "confirm",
Usage: "user must press enter before starting the miner",
cli.BoolFlag{
Name: "confirm",
Usage: "User must press enter before starting the miner",
},
},
}
}

func Start(args *startArgs, logger *log.Logger) error {
storage.Init(args.dbname, args.bootstrapNodeAddress)
p2p.Init(args.myNodeAddress)

validatorPubKey, err := crypto.ExtractECDSAPublicKeyFromFile(args.walletFile)
if err != nil {
logger.Printf("%v\n", err)
return err
}

rootPrivKey, err := crypto.ExtractECDSAKeyFromFile(args.rootKeyFile)
if err != nil {
logger.Printf("%v\n", err)
return err
}

var multisigPubKey *ecdsa.PublicKey
if len(args.multisigFile) > 0 {
multisigPubKey, err = crypto.ExtractECDSAPublicKeyFromFile(args.multisigFile)
func Start(args *startArgs) error {
var firstStart = false
if _, err := os.Stat(args.dataDirectory); os.IsNotExist(err) {
err = os.MkdirAll(args.dataDirectory, 0755)
if err != nil {
logger.Printf("%v\n", err)
return err
}
} else {
multisigPubKey = &rootPrivKey.PublicKey
firstStart = true
}

commPrivKey, err := crypto.ExtractRSAKeyFromFile(args.commitmentFile)
const (
database = "store.db"
wallet = "wallet.key"
commitment = "commitment.key"
)

storage.Init(args.dataDirectory+"/" + database, args.bootstrapNodeAddress)
p2p.Init(args.myNodeAddress)

validatorPubKey, err := crypto.ExtractECDSAPublicKeyFromFile(args.dataDirectory + "/" + wallet)
if err != nil {
logger.Printf("%v\n", err)
return err
}

rootCommPrivKey, err := crypto.ExtractRSAKeyFromFile(args.rootCommitmentFile)
commPrivKey, err := crypto.ExtractRSAKeyFromFile(args.dataDirectory + "/" + commitment)
if err != nil {
logger.Printf("%v\n", err)
return err
}

miner.Init(validatorPubKey, multisigPubKey, &rootPrivKey.PublicKey, commPrivKey, rootCommPrivKey)
// Check if executor is root and if it's the first start
if p2p.IsBootstrap() && firstStart {
return miner.InitFirstStart(validatorPubKey, commPrivKey)
} else {
return miner.Init(validatorPubKey, commPrivKey)
}

return nil
}

func (args startArgs) ValidateInput() error {
if len(args.dbname) == 0 {
return errors.New("argument missing: dbname")
if len(args.dataDirectory) == 0 {
return errors.New("argument missing: dataDir")
}

if len(args.myNodeAddress) == 0 {
Expand All @@ -159,42 +121,15 @@ func (args startArgs) ValidateInput() error {
if len(args.bootstrapNodeAddress) == 0 {
return errors.New("argument missing: bootstrapNodeAddress")
}

if len(args.walletFile) == 0 {
return errors.New("argument missing: keyFile")
}

if len(args.commitmentFile) == 0 {
return errors.New("argument missing: commitmentFile")
}

if len(args.rootKeyFile) == 0 {
return errors.New("argument missing: rootKeyFile")
}

if len(args.rootCommitmentFile) == 0 {
return errors.New("argument missing: rootCommitmentFile")
}

return nil
}

func (args startArgs) String() string {
return fmt.Sprintf("Starting bazo miner with arguments \n" +
"- Database Name:\t\t %v\n" +
"- My Address:\t\t\t %v\n" +
"- Bootstrap Address:\t\t %v\n" +
"- Wallet File:\t\t\t %v\n" +
"- Multisig File:\t\t %v\n" +
"- Commitment File:\t\t %v\n" +
"- Root Wallet File:\t\t %v\n" +
"- Root Commitment File:\t %v\n",
args.dbname,
return fmt.Sprintf("Starting bazo miner with arguments \n"+
"- My Address:\t\t\t %v\n"+
"- Bootstrap Address:\t\t %v\n"+
"- Data Directory:\t\t %v\n",
args.myNodeAddress,
args.bootstrapNodeAddress,
args.walletFile,
args.multisigFile,
args.commitmentFile,
args.rootKeyFile,
args.rootCommitmentFile)
}
args.dataDirectory)
}
Loading