Skip to content

Commit

Permalink
Node/Solana: Shim watcher cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
bruce-riley committed Feb 18, 2025
1 parent 2ea519c commit 6595ed9
Show file tree
Hide file tree
Showing 2 changed files with 1,335 additions and 30 deletions.
52 changes: 40 additions & 12 deletions node/pkg/watchers/solana/shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package solana
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -175,6 +176,9 @@ func (s *SolanaWatcher) shimProcessTopLevelInstruction(
isReobservation bool,
) (bool, error) {
topLevelIdx := uint16(topLevelIndex)
if topLevelIdx >= uint16(len(tx.Message.Instructions)) {
return false, fmt.Errorf("topLevelIndex %d is greater than %d", topLevelIdx, len(tx.Message.Instructions))
}
inst := tx.Message.Instructions[topLevelIdx]

// The only top-level instruction generated by the shim contract is the PostMessage event. Parse that to get
Expand All @@ -192,7 +196,7 @@ func (s *SolanaWatcher) shimProcessTopLevelInstruction(
outerIdx := -1
for idx, inner := range innerInstructions {
if inner.Index == topLevelIdx {
outerIdx = int(idx)
outerIdx = idx
break
}
}
Expand All @@ -202,7 +206,7 @@ func (s *SolanaWatcher) shimProcessTopLevelInstruction(
}

// Process the inner instructions associated with this shim top-level instruction and produce an observation event.
err = s.shimProcessRest(logger, whProgramIndex, shimProgramIndex, tx, innerInstructions[outerIdx].Instructions, outerIdx, 0, postMessage, alreadyProcessed, isReobservation)
err = s.shimProcessRest(logger, whProgramIndex, shimProgramIndex, tx, innerInstructions[outerIdx].Instructions, outerIdx, 0, postMessage, alreadyProcessed, isReobservation, true)
if err != nil {
return false, fmt.Errorf("failed to process inner instructions for top-level shim instruction %d: %w", topLevelIdx, err)
}
Expand All @@ -226,6 +230,10 @@ func (s *SolanaWatcher) shimProcessInnerInstruction(
alreadyProcessed ShimAlreadyProcessed,
isReobservation bool,
) (bool, error) {
if startIdx >= len(innerInstructions) {
return false, fmt.Errorf("startIdx %d is greater than or equal to %d", startIdx, len(innerInstructions))
}

// See if this is a PostMessage event from the shim contract. If so, parse it. If not, bail out now.
postMessage, err := shimParsePostMessage(s.shimPostMessageDiscriminator, innerInstructions[startIdx].Data)
if err != nil {
Expand All @@ -238,7 +246,7 @@ func (s *SolanaWatcher) shimProcessInnerInstruction(

alreadyProcessed.add(outerIdx, startIdx)

err = s.shimProcessRest(logger, whProgramIndex, shimProgramIndex, tx, innerInstructions, outerIdx, startIdx+1, postMessage, alreadyProcessed, isReobservation)
err = s.shimProcessRest(logger, whProgramIndex, shimProgramIndex, tx, innerInstructions, outerIdx, startIdx+1, postMessage, alreadyProcessed, isReobservation, false)
if err != nil {
return false, fmt.Errorf("failed to process inner instructions for inner shim instruction %d: %w", outerIdx, err)
}
Expand All @@ -260,7 +268,12 @@ func (s *SolanaWatcher) shimProcessRest(
postMessage *ShimPostMessageData,
alreadyProcessed ShimAlreadyProcessed,
isReobservation bool,
isTopLevel bool,
) error {
if postMessage == nil {
return errors.New("postMessage is nil")
}

// Loop through the inner instructions after the shim PostMessage and do the following:
// 1) Find the core event and verify it is unreliable with an empty payload.
// 2) Find the shim MessageEvent to get the rest of the fields we need for the observation.
Expand All @@ -269,17 +282,25 @@ func (s *SolanaWatcher) shimProcessRest(
var verifiedCoreEvent bool
var messageEvent *ShimMessageEventData
var err error
coreEventFound := false
for idx := startIdx; idx < len(innerInstructions); idx++ {
inst := innerInstructions[idx]
if inst.ProgramIDIndex == whProgramIndex {
if verifiedCoreEvent, err = shimVerifyCoreMessage(inst.Data); err != nil {
if verifiedCoreEvent {
return fmt.Errorf("detected multiple inner core instructions when there should not be at instruction %d, %d", outerIdx, idx)
}
foundIt, err := shimVerifyCoreMessage(inst.Data)
if err != nil {
return fmt.Errorf("failed to verify inner core instruction for shim instruction %d, %d: %w", outerIdx, idx, err)
}
alreadyProcessed.add(outerIdx, idx)
coreEventFound = true
if foundIt {
alreadyProcessed.add(outerIdx, idx)
verifiedCoreEvent = true
}
} else if inst.ProgramIDIndex == shimProgramIndex {
if !coreEventFound {
if messageEvent != nil {
return fmt.Errorf("detected multiple shim message event instructions when there should not be at instruction %d, %d", outerIdx, idx)
}
if !verifiedCoreEvent {
return fmt.Errorf("detected an inner shim message event instruction before the core event for shim instruction %d, %d: %w", outerIdx, idx, err)
}
messageEvent, err = shimParseMessageEvent(s.shimMessageEventDiscriminator, inst.Data)
Expand All @@ -290,16 +311,21 @@ func (s *SolanaWatcher) shimProcessRest(
}

if verifiedCoreEvent && messageEvent != nil {
break
if !isTopLevel {
// We found what we are looking for, and additional shim events in the inner instruction case are allowed, so we can stop looking.
break
}

// In the top level instruction case, we should not have any additional shim events in this instruction set.
}
}

if !verifiedCoreEvent {
return fmt.Errorf("failed to find inner core instruction for shim instruction %d", outerIdx)
return fmt.Errorf("failed to find inner core instruction for shim instruction %d, %d", outerIdx, startIdx)
}

if messageEvent == nil {
return fmt.Errorf("failed to find inner shim message event instruction for shim instruction %d", outerIdx)
return fmt.Errorf("failed to find inner shim message event instruction for shim instruction %d, %d", outerIdx, startIdx)
}

commitment, err := postMessage.ConsistencyLevel.Commitment()
Expand Down Expand Up @@ -328,7 +354,9 @@ func (s *SolanaWatcher) shimProcessRest(
Payload: postMessage.Payload,
ConsistencyLevel: uint8(postMessage.ConsistencyLevel),
IsReobservation: isReobservation,
Unreliable: false,

// Shim messages are always reliable.
Unreliable: false,
}

solanaMessagesConfirmed.WithLabelValues(s.networkName).Inc()
Expand Down
Loading

0 comments on commit 6595ed9

Please sign in to comment.