Skip to content

Commit

Permalink
go/roothash/tester: add submit equivocation evidence test
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus authored and kostko committed Feb 8, 2021
1 parent 61794e1 commit c9526ce
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 17 deletions.
2 changes: 1 addition & 1 deletion go/genesis/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func TestGenesisChainContext(t *testing.T) {

// Having to update this every single time the genesis structure
// changes isn't annoying at all.
require.Equal(t, "190c33831058e1f850a1528da9892259c4d86538f4524c561a93505fe41c4d83", stableDoc.ChainContext())
require.Equal(t, "c7ca04c2279b2df5773258fda6a7ff9e473fe648eb7616e1be6474308e9174e8", stableDoc.ChainContext())
}

func TestGenesisSanityCheck(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions go/registry/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto"
"errors"
"fmt"
"math"
"net"
"testing"
"time"
Expand Down Expand Up @@ -1732,6 +1733,13 @@ func NewTestRuntime(seed []byte, ent *TestEntity, isKeyManager bool) (*TestRunti
AnyNode: &api.AnyNodeRuntimeAdmissionPolicy{},
},
GovernanceModel: api.GovernanceEntity,
Staking: api.RuntimeStakingParameters{
Slashing: map[staking.SlashReason]staking.Slash{
staking.SlashRuntimeEquivocation: {
Amount: *quantity.NewFromUint64(math.MaxInt64),
},
},
},
}
// TODO: Test with non-empty state root when enabled.
rt.Runtime.Genesis.StateRoot.Empty()
Expand Down
94 changes: 94 additions & 0 deletions go/roothash/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ import (
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/identity"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
consensusAPI "github.com/oasisprotocol/oasis-core/go/consensus/api"
registryTests "github.com/oasisprotocol/oasis-core/go/registry/tests"
"github.com/oasisprotocol/oasis-core/go/roothash/api"
"github.com/oasisprotocol/oasis-core/go/roothash/api/block"
"github.com/oasisprotocol/oasis-core/go/roothash/api/commitment"
"github.com/oasisprotocol/oasis-core/go/runtime/transaction"
scheduler "github.com/oasisprotocol/oasis-core/go/scheduler/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
stakingTests "github.com/oasisprotocol/oasis-core/go/staking/tests"
storageAPI "github.com/oasisprotocol/oasis-core/go/storage/api"
"github.com/oasisprotocol/oasis-core/go/worker/storage"
)
Expand Down Expand Up @@ -110,6 +113,10 @@ func RootHashImplementationTests(t *testing.T, backend api.Backend, consensus co
t.Run("RoundTimeoutWithEpochTransition", func(t *testing.T) {
testRoundTimeoutWithEpochTransition(t, backend, consensus, identity, rtStates)
})

t.Run("EquivocationEvidence", func(t *testing.T) {
testSubmitEquivocationEvidence(t, backend, consensus, identity, rtStates)
})
}

func testGenesisBlock(t *testing.T, backend api.Backend, state *runtimeState) {
Expand Down Expand Up @@ -814,3 +821,90 @@ func MustTransitionEpoch(
}
}
}

func testSubmitEquivocationEvidence(t *testing.T, backend api.Backend, consensus consensusAPI.Backend, identity *identity.Identity, states []*runtimeState) {
require := require.New(t)

ctx := context.Background()

s := states[0]
child, err := backend.GetLatestBlock(ctx, s.rt.Runtime.ID, consensusAPI.HeightLatest)
require.NoError(err, "GetLatestBlock")

// Generate and submit evidence of executor equivocation.
if len(s.executorCommittee.workers) < 2 {
t.Fatal("not enough executor nodes for running runtime misbehaviour evidence test")
}

// Generate evidence of executor equivocation.
node := s.executorCommittee.workers[0]
batch1 := &commitment.ProposedBatch{
IORoot: child.Header.IORoot,
StorageSignatures: []signature.Signature{},
Header: child.Header,
}
signedBatch1, err := commitment.SignProposedBatch(node.Signer, batch1)
require.NoError(err, "SignProposedBatch")

batch2 := &commitment.ProposedBatch{
IORoot: hash.NewFromBytes([]byte("different root")),
StorageSignatures: []signature.Signature{},
Header: child.Header,
}
signedBatch2, err := commitment.SignProposedBatch(node.Signer, batch2)
require.NoError(err, "SignProposedBatch")

ch, sub, err := consensus.Staking().WatchEvents(ctx)
require.NoError(err, "staking.WatchEvents")
defer sub.Close()

// Ensure misbehaving node entity has some stake.
entityAddress := staking.NewAddress(node.Node.EntityID)
escrow := &staking.Escrow{
Account: entityAddress,
Amount: *quantity.NewFromUint64(100),
}
tx := staking.NewAddEscrowTx(0, nil, escrow)
err = consensusAPI.SignAndSubmitTx(ctx, consensus, stakingTests.SrcSigner, tx)
require.NoError(err, "AddEscrow")

// Submit evidence of executor equivocation.
tx = api.NewEvidenceTx(0, nil, &api.Evidence{
ID: s.rt.Runtime.ID,
EquivocationBatch: &api.EquivocationBatchEvidence{
BatchA: *signedBatch1,
BatchB: *signedBatch2,
},
})
submitter := s.executorCommittee.workers[1]
err = consensusAPI.SignAndSubmitTx(ctx, consensus, submitter.Signer, tx)
require.NoError(err, "SignAndSubmitTx(EvidenceTx)")

// Wait for the node to get slashed.
WaitLoop:
for {
select {
case ev := <-ch:
if ev.Escrow == nil {
continue
}

if e := ev.Escrow.Take; e != nil {
require.EqualValues(entityAddress, e.Owner, "TakeEscrowEvent - owner must be entity's address")
// All stake must be slashed as defined in debugGenesisState.
require.EqualValues(escrow.Amount, e.Amount, "TakeEscrowEvent - all stake slashed")
break WaitLoop
}
case <-time.After(recvTimeout):
t.Fatalf("failed to receive slash event")
}
}

// Ensure runtime acc got the slashed funds.
runtimeAcc, err := consensus.Staking().Account(ctx, &staking.OwnerQuery{
Height: consensusAPI.HeightLatest,
Owner: staking.NewRuntimeAddress(s.rt.Runtime.ID),
})
require.NoError(err, "staking.Account(runtimeAddr)")
require.EqualValues(escrow.Amount, runtimeAcc.General.Balance, "Runtime account expected salshed balance")
}
32 changes: 16 additions & 16 deletions go/staking/tests/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var (

qtyOne = *quantity.NewFromUint64(1)

srcSigner = debug.DebugStateSrcSigner
SrcSigner = debug.DebugStateSrcSigner
SrcAddr = debug.DebugStateSrcAddress
destSigner = debug.DebugStateDestSigner
DestAddr = debug.DebugStateDestAddress
Expand Down Expand Up @@ -208,7 +208,7 @@ func testTransfer(t *testing.T, state *stakingTestsState, backend api.Backend, c
Amount: *quantity.NewFromUint64(math.MaxUint8),
}
tx := api.NewTransferTx(srcAcc.General.Nonce, nil, xfer)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "Transfer")

var gotTransfer bool
Expand Down Expand Up @@ -276,7 +276,7 @@ TransferWaitLoop:
xfer.Amount = newSrcAcc.General.Balance

tx = api.NewTransferTx(newSrcAcc.General.Nonce, nil, xfer)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.Error(err, "Transfer - more than available balance")
}

Expand All @@ -295,7 +295,7 @@ func testSelfTransfer(t *testing.T, state *stakingTestsState, backend api.Backen
Amount: *quantity.NewFromUint64(math.MaxUint8),
}
tx := api.NewTransferTx(srcAcc.General.Nonce, nil, xfer)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "Transfer")

var gotTransfer bool
Expand Down Expand Up @@ -343,7 +343,7 @@ TransferWaitLoop:
xfer.Amount = newSrcAcc.General.Balance

tx = api.NewTransferTx(newSrcAcc.General.Nonce, nil, xfer)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.Error(err, "Transfer - more than available balance")
}

Expand All @@ -364,7 +364,7 @@ func testBurn(t *testing.T, state *stakingTestsState, backend api.Backend, conse
Amount: *quantity.NewFromUint64(math.MaxUint32),
}
tx := api.NewBurnTx(srcAcc.General.Nonce, nil, burn)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "Burn")

select {
Expand Down Expand Up @@ -407,11 +407,11 @@ func testBurn(t *testing.T, state *stakingTestsState, backend api.Backend, conse
}

func testEscrow(t *testing.T, state *stakingTestsState, backend api.Backend, consensus consensusAPI.Backend) {
testEscrowEx(t, state, backend, consensus, SrcAddr, srcSigner, DestAddr)
testEscrowEx(t, state, backend, consensus, SrcAddr, SrcSigner, DestAddr)
}

func testSelfEscrow(t *testing.T, state *stakingTestsState, backend api.Backend, consensus consensusAPI.Backend) {
testEscrowEx(t, state, backend, consensus, SrcAddr, srcSigner, SrcAddr)
testEscrowEx(t, state, backend, consensus, SrcAddr, SrcSigner, SrcAddr)
}

func testEscrowEx( // nolint: gocyclo
Expand All @@ -420,7 +420,7 @@ func testEscrowEx( // nolint: gocyclo
backend api.Backend,
consensus consensusAPI.Backend,
srcAddr api.Address,
srcSigner signature.Signer,
SrcSigner signature.Signer,
dstAddr api.Address,
) {
require := require.New(t)
Expand Down Expand Up @@ -454,7 +454,7 @@ func testEscrowEx( // nolint: gocyclo
Amount: *quantity.NewFromUint64(math.MaxUint32),
}
tx := api.NewAddEscrowTx(srcAcc.General.Nonce, nil, escrow)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "AddEscrow")
require.NoError(totalEscrowed.Add(&escrow.Amount))

Expand Down Expand Up @@ -521,7 +521,7 @@ func testEscrowEx( // nolint: gocyclo
Amount: *quantity.NewFromUint64(math.MaxUint32),
}
tx = api.NewAddEscrowTx(srcAcc.General.Nonce, nil, escrow)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "AddEscrow")
require.NoError(totalEscrowed.Add(&escrow.Amount))

Expand Down Expand Up @@ -592,7 +592,7 @@ func testEscrowEx( // nolint: gocyclo
Shares: dstAcc.Escrow.Active.TotalShares,
}
tx = api.NewReclaimEscrowTx(srcAcc.General.Nonce, nil, reclaim)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "ReclaimEscrow")

// Query debonding delegations.
Expand Down Expand Up @@ -666,7 +666,7 @@ func testEscrowEx( // nolint: gocyclo
Shares: reclaim.Shares,
}
tx = api.NewReclaimEscrowTx(newSrcAcc.General.Nonce, nil, reclaim)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.Error(err, "ReclaimEscrow")

debs, err = backend.DebondingDelegations(context.Background(), &api.OwnerQuery{Owner: srcAddr, Height: consensusAPI.HeightLatest})
Expand All @@ -679,7 +679,7 @@ func testEscrowEx( // nolint: gocyclo
Amount: *quantity.NewFromUint64(1), // Minimum is 10.
}
tx = api.NewAddEscrowTx(srcAcc.General.Nonce, nil, escrow)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.Error(err, "AddEscrow")
}

Expand All @@ -701,7 +701,7 @@ func testAllowance(t *testing.T, state *stakingTestsState, backend api.Backend,
AmountChange: *quantity.NewFromUint64(math.MaxUint8),
}
tx := api.NewAllowTx(srcAcc.General.Nonce, nil, allow)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "Allow")

// Compute what new the total expected allowance should be.
Expand Down Expand Up @@ -846,7 +846,7 @@ func testSlashConsensusEquivocation(
Amount: *quantity.NewFromUint64(math.MaxUint32),
}
tx := api.NewAddEscrowTx(srcAcc.General.Nonce, nil, escrow)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, srcSigner, tx)
err = consensusAPI.SignAndSubmitTx(context.Background(), consensus, SrcSigner, tx)
require.NoError(err, "AddEscrow")

// Query updated validator account state.
Expand Down

0 comments on commit c9526ce

Please sign in to comment.