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

Roothash processing fees #2504

Merged
merged 10 commits into from
Jan 15, 2020
9 changes: 9 additions & 0 deletions .changelog/2504.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Charge gas for runtime transactions and suspend runtimes which do not pay periodic maintenance fees.

This introduces gas fees for submitting roothash commitments from runtime nodes. Since periodic
maintenance work must be performed on each epoch transition (e.g., electing runtime committees),
fees for that maintenance are paid by any nodes that register to perform work for a specific
runtime. Fees are pre-paid for the number of epochs a node registers for.

If the maintenance fees are not paid, the runtime gets suspended (so periodic work is not needed)
and must be resumed by registering nodes.
2 changes: 1 addition & 1 deletion go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fmt:
# Lint.
lint:
@$(ECHO) "$(CYAN)*** Running Go linters...$(OFF)"
@env -u GOPATH golangci-lint run
@env -u GOPATH golangci-lint run --deadline 2m

# Test.
test:
Expand Down
16 changes: 16 additions & 0 deletions go/common/crypto/signature/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ func (r RawSignature) String() string {
return string(data)
}

// Equal compares vs another public key for equality.
func (r RawSignature) Equal(cmp RawSignature) bool {
return bytes.Equal(r[:], cmp[:])
}

// MarshalBinary encodes a signature into binary form.
func (r RawSignature) MarshalBinary() (data []byte, err error) {
data = append([]byte{}, r[:]...)
Expand Down Expand Up @@ -279,6 +284,17 @@ type Signature struct {
Signature RawSignature `json:"signature"`
}

// Equal compares vs another signature for equality.
func (s *Signature) Equal(cmp *Signature) bool {
if !s.PublicKey.Equal(cmp.PublicKey) {
return false
}
if !s.Signature.Equal(cmp.Signature) {
return false
}
return true
}

// Sign generates a signature with the private key over the context and
// message.
func Sign(signer Signer, context Context, message []byte) (*Signature, error) {
Expand Down
4 changes: 3 additions & 1 deletion go/consensus/tendermint/abci/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,9 @@ func (sc *StateCheckpoint) Rollback() {
if sc.ctx == nil {
return
}
sc.ctx.State().ImmutableTree = &sc.ImmutableTree
st := sc.ctx.State()
st.Rollback()
st.ImmutableTree = &sc.ImmutableTree
}

// BlockContextKey is an interface for a block context key.
Expand Down
2 changes: 1 addition & 1 deletion go/consensus/tendermint/apps/beacon/beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (app *beaconApplication) onBeaconEpochChange(ctx *abci.Context, epoch epoch
case true:
// UNSAFE/DEBUG - Deterministic beacon.
entropyCtx = debugEntropyCtx
entropy = []byte("If you change this, you will fuck up the byzantine tests!!")
entropy = []byte("If you change this, you will fuck up the byzantine tests!!!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point we should probably just add in hacks to the scheduler that just schedules things "correctly" for the byzantine tests.

}

b := getBeacon(epoch, entropyCtx, entropy)
Expand Down
34 changes: 29 additions & 5 deletions go/consensus/tendermint/apps/registry/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,25 @@ func (app *registryApplication) InitChain(ctx *abci.Context, request types.Reque
}
}
}
for _, v := range st.SuspendedRuntimes {
app.logger.Debug("InitChain: Registering genesis suspended runtime",
"runtime_owner", v.Signature.PublicKey,
)
if err := app.registerRuntime(ctx, state, v); err != nil {
app.logger.Error("InitChain: failed to register runtime",
"err", err,
"runtime", v,
)
return errors.Wrap(err, "registry: genesis suspended runtime registration failure")
}
var rt registry.Runtime
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this, just make app.registerRuntime return (*registry.Runtime, error)?

Otherwise, the cbor.Unmarshal call failing is a sign that something when absolutely horrifically wrong since the runtime registration does an Unmarshal.

if err := cbor.Unmarshal(v.Blob, &rt); err != nil {
return errors.Wrap(err, "registry: malformed genesis suspended runtime")
}
if err := state.SuspendRuntime(rt.ID); err != nil {
return errors.Wrap(err, "registry: failed to suspend runtime at genesis")
}
}
for _, v := range st.Nodes {
app.logger.Debug("InitChain: Registering genesis node",
"node_owner", v.Signature.PublicKey,
Expand Down Expand Up @@ -120,6 +139,10 @@ func (rq *registryQuerier) Genesis(ctx context.Context) (*registry.Genesis, erro
if err != nil {
return nil, err
}
suspendedRuntimes, err := rq.state.SuspendedRuntimes()
if err != nil {
return nil, err
}
signedNodes, err := rq.state.SignedNodes()
if err != nil {
return nil, err
Expand Down Expand Up @@ -149,11 +172,12 @@ func (rq *registryQuerier) Genesis(ctx context.Context) (*registry.Genesis, erro
}

gen := registry.Genesis{
Parameters: *params,
Entities: signedEntities,
Runtimes: signedRuntimes,
Nodes: validatorNodes,
NodeStatuses: nodeStatuses,
Parameters: *params,
Entities: signedEntities,
Runtimes: signedRuntimes,
SuspendedRuntimes: suspendedRuntimes,
Nodes: validatorNodes,
NodeStatuses: nodeStatuses,
}
return &gen, nil
}
Loading