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

Enable automatic viewchange #2438

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 42 additions & 2 deletions byzcoin/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"crypto/sha256"
"encoding/binary"
"fmt"
"go.dedis.ch/kyber/v3/sign/schnorr"
"go.dedis.ch/onet/v3/log"
"net/url"
"strconv"
"strings"
Expand Down Expand Up @@ -548,15 +550,52 @@ func (c *contractConfig) Invoke(rst ReadOnlyStateTrie, inst Instruction, coins [
fmt.Errorf("couldn't get latest skipblock: %v", err)
}

if rst.GetVersion() < VersionViewchange {
leaderRotation := len(req.Proof) == 1 &&
req.Proof[0].View.ID.IsNull()
switch v := rst.GetVersion(); {
case v < VersionViewchange:
// If everything is correctly signed, then we trust it, no need
// to do additional verification.
sigBuf := inst.Invoke.Args.Search("multisig")
err = protocol.BlsSignature(sigBuf).Verify(pairingSuite, req.Hash(), req.Roster.ServicePublics(ServiceName))
if err != nil {
return nil, nil, xerrors.Errorf("invalid signature: %v", err)
}
} else {

case leaderRotation && v >= VersionAutoViewchange:
// Do leader rotation
if c.LeaderRotation == 0 {
return nil, nil, xerrors.Errorf(
"auto-viewchange is not enabled in genesis-config")
}
autoLeader :=
((rst.GetIndex() - c.LastViewchange) / c.LeaderRotation) %
len(c.Roster.List)
if autoLeader <= 0 {
return nil, nil, xerrors.New(
"cannot auto-viewchange current leader")
}
signedLeader := req.Proof[0].View.LeaderIndex
if autoLeader != signedLeader {
return nil, nil, xerrors.Errorf(
"new leader request from wrong leader:"+
"required: %d - signed: %d", autoLeader, signedLeader)
}

// Verify signature
err := schnorr.Verify(cothority.Suite, c.Roster.List[autoLeader].
Public, []byte{}, req.Proof[0].Signature)
if err != nil {
return nil, nil, xerrors.Errorf(
"wronng signature for new leader")
}

// Rotate roster, don't trust what the client sent
newRoster := onet.NewRoster(append(c.Roster.List[autoLeader:],
c.Roster.List[:autoLeader]...))
req.Roster = *newRoster

default:
// For byzcoin version >= VersionViewchange,
// the contract has to verify all the proofs.
// But it avoids having to do a BLS signature.
Expand All @@ -572,6 +611,7 @@ func (c *contractConfig) Invoke(rst ReadOnlyStateTrie, inst Instruction, coins [
}
}

log.LLvl2("Accepting new roster", req.Roster)
sc, err := updateRosterScs(rst, darcID, req.Roster)
return sc, coins, cothority.ErrorOrNil(err, "roster scs")
default:
Expand Down
6 changes: 5 additions & 1 deletion byzcoin/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func init() {
type Version int

// CurrentVersion is what we're running now
const CurrentVersion Version = VersionRollup
const CurrentVersion Version = VersionAutoViewchange

const (
// VersionInstructionHash is the first version and indicates that a new,
Expand All @@ -44,4 +44,8 @@ const (
// VersionRollup indicates that the followers send their transactions to
// the leader, instead of polling by the leader.
VersionRollup = 7
// VersionAutoViewchange allows the nodes to propose themselves as a new
// leader after some interval that can be configured in the genesis
// configuration.
VersionAutoViewchange = 8
)
7 changes: 7 additions & 0 deletions byzcoin/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ type ChainConfig struct {
Roster onet.Roster
MaxBlockSize int
DarcContractIDs []string
// LeaderRotation indicates how many seconds the next node in the roster
// must wait before it's allowed to request a leader-rotation.
// If it's 0 or not given, auto leader rotation is not allowed.
LeaderRotation int `proto:"opt"`
// LastViewchange holds the index of the last successful viewchange.
// Either because of a failing leader, or because of an auto viewchange.
LastViewchange int `proto:"opt"`
}

// Proof represents everything necessary to verify a given
Expand Down