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 16, 2024
1 parent 6c57105 commit 5c7b2ca
Show file tree
Hide file tree
Showing 14 changed files with 744 additions and 15 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
33 changes: 18 additions & 15 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

inactivityNotifier *operatorInactivityNotifier

startBlock uint64
expiryBlock uint64

Expand All @@ -79,20 +82,22 @@ func newHeartbeatAction(
signingExecutor heartbeatSigningExecutor,
proposal *HeartbeatProposal,
failureCounter *uint,
inactivityNotifier *operatorInactivityNotifier,
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,
inactivityNotifier: inactivityNotifier,
startBlock: startBlock,
expiryBlock: expiryBlock,
waitForBlockFn: waitForBlockFn,
}
}

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.inactivityNotifier.publishInactivityClaim(
[]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 := newOperatorInactivityNotifier(
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 := newOperatorInactivityNotifier(
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
62 changes: 62 additions & 0 deletions pkg/tbtc/inactivity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package tbtc

import (
"context"
"math/big"

"github.com/ipfs/go-log/v2"
"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 operatorInactivityNotifier struct {
chain Chain
signers []*signer
}

func newOperatorInactivityNotifier(
chain Chain,
signers []*signer,
) *operatorInactivityNotifier {
return &operatorInactivityNotifier{
chain: chain,
signers: signers,
}
}

func (oin *operatorInactivityNotifier) publishInactivityClaim(
inactiveMembersIndexes []group.MemberIndex,
heartbeatFailed bool,
) error {
// TODO: Build a claim and launch the publish function for all
// the signers.

return nil
}

func (oin *operatorInactivityNotifier) publish(

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

View workflow job for this annotation

GitHub Actions / client-lint

func (*operatorInactivityNotifier).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(oin.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
}
26 changes: 26 additions & 0 deletions pkg/tbtc/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,25 @@ func (n *node) getCoordinationExecutor(
return executor, true, nil
}

func (n *node) getInactivityNotifier(
walletPublicKey *ecdsa.PublicKey,
) (*operatorInactivityNotifier, error) {
signers := n.walletRegistry.getSigners(walletPublicKey)
if len(signers) == 0 {
// This is not an error because the node simply does not control
// the given wallet.
return nil, nil
}

inactivityNotifier := newOperatorInactivityNotifier(
n.chain,
signers,
)

// TODO: Continue with the implementation.
return inactivityNotifier, nil
}

// handleHeartbeatProposal handles an incoming heartbeat proposal by
// orchestrating and dispatching an appropriate wallet action.
func (n *node) handleHeartbeatProposal(
Expand Down Expand Up @@ -442,6 +461,12 @@ func (n *node) handleHeartbeatProposal(
return
}

inactivityNotifier, err := n.getInactivityNotifier(wallet.publicKey)
if err != nil {
logger.Errorf("cannot get inactivity operator: [%v]", err)
return
}

logger.Infof(
"starting orchestration of the heartbeat action for wallet [0x%x]; "+
"20-byte public key hash of that wallet is [0x%x]",
Expand All @@ -464,6 +489,7 @@ func (n *node) handleHeartbeatProposal(
signingExecutor,
proposal,
&n.heartbeatFailureCounter,
inactivityNotifier,
startBlock,
expiryBlock,
n.waitForBlockHeight,
Expand Down
Loading

0 comments on commit 5c7b2ca

Please sign in to comment.