Skip to content

Commit

Permalink
Merge pull request #1252 from nspcc-dev/fix/voting
Browse files Browse the repository at this point in the history
Implement delegated voting
  • Loading branch information
roman-khimov authored Aug 7, 2020
2 parents e1d3223 + bfda60c commit d571162
Show file tree
Hide file tree
Showing 28 changed files with 553 additions and 236 deletions.
85 changes: 85 additions & 0 deletions cli/wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import (
"github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal"
Expand Down Expand Up @@ -186,6 +190,24 @@ func NewCommands() []cli.Command {
Usage: "work with NEP5 contracts",
Subcommands: newNEP5Commands(),
},
{
Name: "vote",
Usage: "vote for a validator",
UsageText: "vote -w <path> -r <rpc> [-t <timeout>] [-g gas] -a <addr> -k <public key>",
Action: handleVote,
Flags: append([]cli.Flag{
walletPathFlag,
gasFlag,
flags.AddressFlag{
Name: "addr, a",
Usage: "Address to vote from",
},
cli.StringFlag{
Name: "key, k",
Usage: "Public key of candidate to vote for",
},
}, options.RPC...),
},
},
}}
}
Expand Down Expand Up @@ -513,6 +535,69 @@ func createWallet(ctx *cli.Context) error {
return nil
}

func handleVote(ctx *cli.Context) error {
wall, err := openWallet(ctx.String("wallet"))
if err != nil {
return cli.NewExitError(err, 1)
}

addrFlag := ctx.Generic("addr").(*flags.Address)
addr := addrFlag.Uint160()
acc := wall.GetAccount(addr)
if acc == nil {
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", addrFlag), 1)
}

var pub *keys.PublicKey
pubStr := ctx.String("key")
if pubStr != "" {
pub, err = keys.NewPublicKeyFromString(pubStr)
if err != nil {
return cli.NewExitError(fmt.Errorf("invalid public key: '%s'", pubStr), 1)
}
}

gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()

c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return err
}

var pubArg interface{}
if pub != nil {
pubArg = pub.Bytes()
}

gas := flags.Fixed8FromContext(ctx, "gas")
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
emit.Opcode(w.BinWriter, opcode.ASSERT)

tx, err := c.CreateTxFromScript(w.Bytes(), acc, int64(gas))
if err != nil {
return cli.NewExitError(err, 1)
}

if pass, err := readPassword("Password > "); err != nil {
return cli.NewExitError(err, 1)
} else if err := acc.Decrypt(pass); err != nil {
return cli.NewExitError(err, 1)
}

if err = acc.SignTx(tx); err != nil {
return cli.NewExitError(fmt.Errorf("can't sign tx: %v", err), 1)
}

res, err := c.SendRawTransaction(tx)
if err != nil {
return cli.NewExitError(err, 1)
}
fmt.Println(res.StringLE())
return nil
}

func readAccountInfo() (string, string, error) {
buf := bufio.NewReader(os.Stdin)
fmt.Print("Enter the name of the account > ")
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.mainnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ ProtocolConfiguration:
Magic: 5195086
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c
- 02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093
- 03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a
- 02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554
- 024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d
- 02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e
- 02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70
ValidatorsCount: 7
SeedList:
- seed1.neo.org:10333
- seed2.neo.org:10333
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.privnet.docker.four.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
ValidatorsCount: 4
SeedList:
- 172.200.0.1:20333
- 172.200.0.2:20334
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.privnet.docker.one.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
ValidatorsCount: 4
SeedList:
- 172.200.0.1:20333
- 172.200.0.2:20334
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.privnet.docker.single.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 1
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
ValidatorsCount: 1
SeedList:
- 172.200.0.1:20333
VerifyBlocks: true
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.privnet.docker.three.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
ValidatorsCount: 4
SeedList:
- 172.200.0.1:20333
- 172.200.0.2:20334
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.privnet.docker.two.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
ValidatorsCount: 4
SeedList:
- 172.200.0.1:20333
- 172.200.0.2:20334
Expand Down
2 changes: 1 addition & 1 deletion config/protocol.privnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ProtocolConfiguration:
Magic: 56753
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ ProtocolConfiguration:
Magic: 1951352142
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d
- 03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2
- 02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd
- 03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806
- 02a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b
- 0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01
- 030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba
ValidatorsCount: 7
SeedList:
- seed1t.neo.org:20333
- seed2t.neo.org:20333
Expand Down
3 changes: 2 additions & 1 deletion config/protocol.unit_testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ ProtocolConfiguration:
Magic: 42
SecondsPerBlock: 15
MemPoolSize: 50000
StandbyValidators:
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
ValidatorsCount: 4
SeedList:
- 127.0.0.1:20334
- 127.0.0.1:20335
Expand Down
9 changes: 5 additions & 4 deletions pkg/config/protocol_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ type (
Magic netmode.Magic `yaml:"Magic"`
MemPoolSize int `yaml:"MemPoolSize"`
// SaveStorageBatch enables storage batch saving before every persist.
SaveStorageBatch bool `yaml:"SaveStorageBatch"`
SecondsPerBlock int `yaml:"SecondsPerBlock"`
SeedList []string `yaml:"SeedList"`
StandbyValidators []string `yaml:"StandbyValidators"`
SaveStorageBatch bool `yaml:"SaveStorageBatch"`
SecondsPerBlock int `yaml:"SecondsPerBlock"`
SeedList []string `yaml:"SeedList"`
StandbyCommittee []string `yaml:"StandbyCommittee"`
ValidatorsCount int `yaml:"ValidatorsCount"`
// Whether to verify received blocks.
VerifyBlocks bool `yaml:"VerifyBlocks"`
// Whether to verify transactions in received blocks.
Expand Down
15 changes: 10 additions & 5 deletions pkg/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ type Blockchain struct {
// cache for block verification keys.
keyCache map[util.Uint160]map[string]*keys.PublicKey

sbValidators keys.PublicKeys
sbCommittee keys.PublicKeys

log *zap.Logger

Expand Down Expand Up @@ -156,7 +156,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
cfg.MemPoolSize = defaultMemPoolSize
log.Info("mempool size is not set or wrong, setting default value", zap.Int("MemPoolSize", cfg.MemPoolSize))
}
validators, err := validatorsFromConfig(cfg)
committee, err := committeeFromConfig(cfg)
if err != nil {
return nil, err
}
Expand All @@ -169,7 +169,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
runToExitCh: make(chan struct{}),
memPool: mempool.NewMemPool(cfg.MemPoolSize),
keyCache: make(map[util.Uint160]map[string]*keys.PublicKey),
sbValidators: validators,
sbCommittee: committee,
log: log,
events: make(chan bcEvent),
subCh: make(chan interface{}),
Expand Down Expand Up @@ -1393,7 +1393,12 @@ func (bc *Blockchain) PoolTx(t *transaction.Transaction) error {

//GetStandByValidators returns validators from the configuration.
func (bc *Blockchain) GetStandByValidators() keys.PublicKeys {
return bc.sbValidators.Copy()
return bc.sbCommittee[:bc.config.ValidatorsCount].Copy()
}

// GetStandByCommittee returns standby commitee from the configuration.
func (bc *Blockchain) GetStandByCommittee() keys.PublicKeys {
return bc.sbCommittee.Copy()
}

// GetValidators returns current validators.
Expand All @@ -1408,7 +1413,7 @@ func (bc *Blockchain) GetNextBlockValidators() ([]*keys.PublicKey, error) {

// GetEnrollments returns all registered validators.
func (bc *Blockchain) GetEnrollments() ([]state.Validator, error) {
return bc.contracts.NEO.GetRegisteredValidators(bc.dao)
return bc.contracts.NEO.GetCandidates(bc.dao)
}

// GetScriptHashesForVerifying returns all the ScriptHashes of a transaction which will be use
Expand Down
1 change: 1 addition & 0 deletions pkg/core/blockchainer/blockchainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Blockchainer interface {
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog
GetNEP5Balances(util.Uint160) *state.NEP5Balances
GetValidators() ([]*keys.PublicKey, error)
GetStandByCommittee() keys.PublicKeys
GetStandByValidators() keys.PublicKeys
GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error)
GetStateRoot(height uint32) (*state.MPTRootState, error)
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ func addSigners(txs ...*transaction.Transaction) {

func signTx(bc *Blockchain, txs ...*transaction.Transaction) error {
validators := bc.GetStandByValidators()
rawScript, err := smartcontract.CreateMultiSigRedeemScript(len(bc.config.StandbyValidators)/2+1, validators)
rawScript, err := smartcontract.CreateMultiSigRedeemScript(bc.config.ValidatorsCount/2+1, validators)
if err != nil {
return errors.Wrap(err, "fail to sign tx")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/core/native/native_gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (g *GAS) Initialize(ic *interop.Context) error {
if err := g.nep5TokenNative.Initialize(ic); err != nil {
return err
}
if g.nep5TokenNative.getTotalSupply(ic).Sign() != 0 {
if g.nep5TokenNative.getTotalSupply(ic.DAO).Sign() != 0 {
return errors.New("already initialized")
}
h, _, err := getStandbyValidatorsHash(ic)
Expand Down
Loading

0 comments on commit d571162

Please sign in to comment.