Skip to content

Commit

Permalink
Added inactivity operator notifier
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaszslabon committed Apr 19, 2024
1 parent 6c57105 commit ca9ba4e
Show file tree
Hide file tree
Showing 14 changed files with 768 additions and 16 deletions.
11 changes: 11 additions & 0 deletions pkg/chain/ethereum/tbtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/keep-network/keep-core/pkg/subscription"
"github.com/keep-network/keep-core/pkg/tbtc"
"github.com/keep-network/keep-core/pkg/tecdsa/dkg"
"github.com/keep-network/keep-core/pkg/tecdsa/inactivity"
)

// Definitions of contract names.
Expand Down Expand Up @@ -993,6 +994,16 @@ func (tc *TbtcChain) DKGParameters() (*tbtc.DKGParameters, error) {
}, nil
}

func (tc *TbtcChain) CalculateInactivityClaimSignatureHash(
nonce *big.Int,
walletPublicKey *ecdsa.PublicKey,
inactiveMembersIndexes []group.MemberIndex,
heartbeatFailed bool,
) (inactivity.ClaimSignatureHash, error) {
// TODO: Implement
return inactivity.ClaimSignatureHash{}, nil
}

func (tc *TbtcChain) PastDepositRevealedEvents(
filter *tbtc.DepositRevealedEventFilter,
) ([]*tbtc.DepositRevealedEvent, error) {
Expand Down
8 changes: 8 additions & 0 deletions pkg/tbtc/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/keep-network/keep-core/pkg/sortition"
"github.com/keep-network/keep-core/pkg/subscription"
"github.com/keep-network/keep-core/pkg/tecdsa/dkg"
"github.com/keep-network/keep-core/pkg/tecdsa/inactivity"
)

type DKGState int
Expand Down Expand Up @@ -106,6 +107,13 @@ type DistributedKeyGenerationChain interface {
startBlock uint64,
) (dkg.ResultSignatureHash, error)

CalculateInactivityClaimSignatureHash(
nonce *big.Int,
walletPublicKey *ecdsa.PublicKey,
inactiveMembersIndexes []group.MemberIndex,
heartbeatFailed bool,
) (inactivity.ClaimSignatureHash, error)

// IsDKGResultValid checks whether the submitted DKG result is valid from
// the on-chain contract standpoint.
IsDKGResultValid(dkgResult *DKGChainResult) (bool, error)
Expand Down
10 changes: 10 additions & 0 deletions pkg/tbtc/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/keep-network/keep-core/pkg/protocol/group"
"github.com/keep-network/keep-core/pkg/subscription"
"github.com/keep-network/keep-core/pkg/tecdsa/dkg"
"github.com/keep-network/keep-core/pkg/tecdsa/inactivity"
)

const localChainOperatorID = chain.OperatorID(1)
Expand Down Expand Up @@ -551,6 +552,15 @@ func (lc *localChain) DKGParameters() (*DKGParameters, error) {
}, nil
}

func (lc *localChain) CalculateInactivityClaimSignatureHash(
nonce *big.Int,
walletPublicKey *ecdsa.PublicKey,
inactiveMembersIndexes []group.MemberIndex,
heartbeatFailed bool,
) (inactivity.ClaimSignatureHash, error) {
panic("unsupported")
}

func (lc *localChain) PastDepositRevealedEvents(
filter *DepositRevealedEventFilter,
) ([]*DepositRevealedEvent, error) {
Expand Down
35 changes: 19 additions & 16 deletions pkg/tbtc/heartbeat.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/ipfs/go-log/v2"
"github.com/keep-network/keep-core/pkg/bitcoin"
"github.com/keep-network/keep-core/pkg/protocol/group"
"github.com/keep-network/keep-core/pkg/tecdsa"
)

Expand Down Expand Up @@ -66,6 +67,8 @@ type heartbeatAction struct {
proposal *HeartbeatProposal
failureCounter *uint

inactivityClaimExecutor *inactivityClaimExecutor

startBlock uint64
expiryBlock uint64

Expand All @@ -79,20 +82,22 @@ func newHeartbeatAction(
signingExecutor heartbeatSigningExecutor,
proposal *HeartbeatProposal,
failureCounter *uint,
inactivityClaimExecutor *inactivityClaimExecutor,
startBlock uint64,
expiryBlock uint64,
waitForBlockFn waitForBlockFn,
) *heartbeatAction {
return &heartbeatAction{
logger: logger,
chain: chain,
executingWallet: executingWallet,
signingExecutor: signingExecutor,
proposal: proposal,
failureCounter: failureCounter,
startBlock: startBlock,
expiryBlock: expiryBlock,
waitForBlockFn: waitForBlockFn,
logger: logger,
chain: chain,
executingWallet: executingWallet,
signingExecutor: signingExecutor,
proposal: proposal,
failureCounter: failureCounter,
inactivityClaimExecutor: inactivityClaimExecutor,
startBlock: startBlock,
expiryBlock: expiryBlock,
waitForBlockFn: waitForBlockFn,
}
}

Expand All @@ -104,7 +109,7 @@ func (ha *heartbeatAction) execute() error {
}

if isUnstaking {
logger.Info(
logger.Warn(
"quitting the heartbeat action without signing because the " +
"operator is unstaking",
)
Expand Down Expand Up @@ -183,7 +188,10 @@ func (ha *heartbeatAction) execute() error {

// The value of consecutive heartbeat failures exceeds the threshold.
// Proceed with operator inactivity notification.
err = ha.notifyOperatorInactivity()
err = ha.inactivityClaimExecutor.publishClaim(
[]group.MemberIndex{},
true,
)
if err != nil {
return fmt.Errorf(
"error while notifying about operator inactivity [%v]]",
Expand All @@ -194,11 +202,6 @@ func (ha *heartbeatAction) execute() error {
return nil
}

func (ha *heartbeatAction) notifyOperatorInactivity() error {
// TODO: Implement
return nil
}

func (ha *heartbeatAction) wallet() wallet {
return ha.executingWallet
}
Expand Down
11 changes: 11 additions & 0 deletions pkg/tbtc/heartbeat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func TestHeartbeatAction_HappyPath(t *testing.T) {
hostChain.setHeartbeatProposalValidationResult(proposal, true)

mockExecutor := &mockHeartbeatSigningExecutor{}
inactivityNotifier := newInactivityClaimExecutor(
hostChain,
[]*signer{},
)
action := newHeartbeatAction(
logger,
hostChain,
Expand All @@ -51,6 +55,7 @@ func TestHeartbeatAction_HappyPath(t *testing.T) {
mockExecutor,
proposal,
&heartbeatFailureCounter,
inactivityNotifier,
startBlock,
expiryBlock,
func(ctx context.Context, blockHeight uint64) error {
Expand Down Expand Up @@ -104,6 +109,11 @@ func TestHeartbeatAction_SigningError(t *testing.T) {
mockExecutor := &mockHeartbeatSigningExecutor{}
mockExecutor.shouldFail = true

inactivityNotifier := newInactivityClaimExecutor(
hostChain,
[]*signer{},
)

action := newHeartbeatAction(
logger,
hostChain,
Expand All @@ -113,6 +123,7 @@ func TestHeartbeatAction_SigningError(t *testing.T) {
mockExecutor,
proposal,
&heartbeatFailureCounter,
inactivityNotifier,
startBlock,
expiryBlock,
func(ctx context.Context, blockHeight uint64) error {
Expand Down
80 changes: 80 additions & 0 deletions pkg/tbtc/inactivity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package tbtc

import (
"context"
"math/big"
"sync"

"github.com/ipfs/go-log/v2"
"github.com/keep-network/keep-core/pkg/generator"
"github.com/keep-network/keep-core/pkg/net"
"github.com/keep-network/keep-core/pkg/protocol/group"
"github.com/keep-network/keep-core/pkg/tecdsa/inactivity"
)

type inactivityClaimExecutor struct {
chain Chain
signers []*signer

protocolLatch *generator.ProtocolLatch
}

// TODO Consider moving all inactivity-related code to pkg/protocol/inactivity.
func newInactivityClaimExecutor(
chain Chain,
signers []*signer,
) *inactivityClaimExecutor {
return &inactivityClaimExecutor{
chain: chain,
signers: signers,
}
}

func (ice *inactivityClaimExecutor) publishClaim(
inactiveMembersIndexes []group.MemberIndex,
heartbeatFailed bool,
) error {
// TODO: Build a claim and launch the publish function for all
// the signers. The value of `heartbeat` should be true and
// `inactiveMembersIndices` should be empty.

wg := sync.WaitGroup{}
wg.Add(len(ice.signers))

for _, currentSigner := range ice.signers {
ice.protocolLatch.Lock()
defer ice.protocolLatch.Unlock()

go func(signer *signer) {
// TODO: Launch claim publishing for members.
}(currentSigner)
}

return nil
}

func (ice *inactivityClaimExecutor) publish(

Check failure on line 56 in pkg/tbtc/inactivity.go

View workflow job for this annotation

GitHub Actions / client-lint

func (*inactivityClaimExecutor).publish is unused (U1000)
ctx context.Context,
inactivityLogger log.StandardLogger,
seed *big.Int,
memberIndex group.MemberIndex,
broadcastChannel net.BroadcastChannel,
groupSize int,
dishonestThreshold int,
membershipValidator *group.MembershipValidator,
inactivityClaim *inactivity.Claim,
) error {
return inactivity.Publish(
ctx,
inactivityLogger,
seed.Text(16),
memberIndex,
broadcastChannel,
groupSize,
dishonestThreshold,
membershipValidator,
newInactivityClaimSigner(ice.chain),
newInactivityClaimSubmitter(),
inactivityClaim,
)
}
95 changes: 95 additions & 0 deletions pkg/tbtc/inactivity_submit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package tbtc

import (
"context"
"fmt"

"github.com/keep-network/keep-core/pkg/protocol/group"
"github.com/keep-network/keep-core/pkg/tecdsa/inactivity"
)

// inactivityClaimSigner is responsible for signing the inactivity claim and
// verification of signatures generated by other group members.
type inactivityClaimSigner struct {

Check failure on line 13 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

type inactivityClaimSigner is unused (U1000)
chain Chain
}

func newInactivityClaimSigner(

Check failure on line 17 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

func newInactivityClaimSigner is unused (U1000)
chain Chain,
) *inactivityClaimSigner {
return &inactivityClaimSigner{
chain: chain,
}
}

func (ics *inactivityClaimSigner) SignClaim(claim *inactivity.Claim) (

Check failure on line 25 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

func (*inactivityClaimSigner).SignClaim is unused (U1000)
*inactivity.SignedClaim,
error,
) {
if claim == nil {
return nil, fmt.Errorf("result is nil")
}

claimHash, err := ics.chain.CalculateInactivityClaimSignatureHash(
claim.Nonce,
claim.WalletPublicKey,
claim.InactiveMembersIndexes,
claim.HeartbeatFailed,
)
if err != nil {
return nil, fmt.Errorf(
"inactivity claim hash calculation failed [%w]",
err,
)
}

signing := ics.chain.Signing()

signature, err := signing.Sign(claimHash[:])
if err != nil {
return nil, fmt.Errorf(
"inactivity claim hash signing failed [%w]",
err,
)
}

return &inactivity.SignedClaim{
PublicKey: signing.PublicKey(),
Signature: signature,
ClaimHash: claimHash,
}, nil
}

// VerifySignature verifies if the signature was generated from the provided
// inactivity claim using the provided public key.
func (ics *inactivityClaimSigner) VerifySignature(

Check failure on line 65 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

func (*inactivityClaimSigner).VerifySignature is unused (U1000)
signedClaim *inactivity.SignedClaim,
) (
bool,
error,
) {
return ics.chain.Signing().VerifyWithPublicKey(
signedClaim.ClaimHash[:],
signedClaim.Signature,
signedClaim.PublicKey,
)
}

type inactivityClaimSubmitter struct {

Check failure on line 78 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

type inactivityClaimSubmitter is unused (U1000)
// TODO: Implement
}

func newInactivityClaimSubmitter() *inactivityClaimSubmitter {

Check failure on line 82 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

func newInactivityClaimSubmitter is unused (U1000)
// TODO: Implement
return &inactivityClaimSubmitter{}
}

func (ics *inactivityClaimSubmitter) SubmitClaim(

Check failure on line 87 in pkg/tbtc/inactivity_submit.go

View workflow job for this annotation

GitHub Actions / client-lint

func (*inactivityClaimSubmitter).SubmitClaim is unused (U1000)
ctx context.Context,
memberIndex group.MemberIndex,
claim *inactivity.Claim,
signatures map[group.MemberIndex][]byte,
) error {
// TODO: Implement
return nil
}
Loading

0 comments on commit ca9ba4e

Please sign in to comment.