mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-28 14:40:51 +02:00
Merge branch '0-19-2-branch-rc1-9726' into 0-19-2-branch-rc1
This commit is contained in:
@@ -116,6 +116,11 @@ type RegisterConf[Event any] struct {
|
|||||||
// transaction needs to dispatch an event.
|
// transaction needs to dispatch an event.
|
||||||
NumConfs fn.Option[uint32]
|
NumConfs fn.Option[uint32]
|
||||||
|
|
||||||
|
// FullBlock is a boolean that indicates whether we want the full block
|
||||||
|
// in the returned response. This is useful if callers want to create an
|
||||||
|
// SPV proof for the transaction post conf.
|
||||||
|
FullBlock bool
|
||||||
|
|
||||||
// PostConfMapper is a special conf mapper, that if present, will be
|
// PostConfMapper is a special conf mapper, that if present, will be
|
||||||
// used to map the protofsm confirmation event to a custom event.
|
// used to map the protofsm confirmation event to a custom event.
|
||||||
PostConfMapper fn.Option[ConfMapper[Event]]
|
PostConfMapper fn.Option[ConfMapper[Event]]
|
||||||
|
@@ -510,10 +510,15 @@ func (s *StateMachine[Event, Env]) executeDaemonEvent(ctx context.Context,
|
|||||||
s.log.DebugS(ctx, "Registering conf",
|
s.log.DebugS(ctx, "Registering conf",
|
||||||
"txid", daemonEvent.Txid)
|
"txid", daemonEvent.Txid)
|
||||||
|
|
||||||
|
var opts []chainntnfs.NotifierOption
|
||||||
|
if daemonEvent.FullBlock {
|
||||||
|
opts = append(opts, chainntnfs.WithIncludeBlock())
|
||||||
|
}
|
||||||
|
|
||||||
numConfs := daemonEvent.NumConfs.UnwrapOr(1)
|
numConfs := daemonEvent.NumConfs.UnwrapOr(1)
|
||||||
confEvent, err := s.cfg.Daemon.RegisterConfirmationsNtfn(
|
confEvent, err := s.cfg.Daemon.RegisterConfirmationsNtfn(
|
||||||
&daemonEvent.Txid, daemonEvent.PkScript,
|
&daemonEvent.Txid, daemonEvent.PkScript,
|
||||||
numConfs, daemonEvent.HeightHint,
|
numConfs, daemonEvent.HeightHint, opts...,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to register conf: %w", err)
|
return fmt.Errorf("unable to register conf: %w", err)
|
||||||
|
@@ -49,6 +49,7 @@ func (c *confDetailsEvent) dummy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type registerConf struct {
|
type registerConf struct {
|
||||||
|
fullBlock bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *registerConf) dummy() {
|
func (r *registerConf) dummy() {
|
||||||
@@ -173,6 +174,7 @@ func (d *dummyStateStart) ProcessEvent(event dummyEvents, env *dummyEnv,
|
|||||||
Txid: chainhash.Hash{1},
|
Txid: chainhash.Hash{1},
|
||||||
PkScript: []byte{0x01},
|
PkScript: []byte{0x01},
|
||||||
HeightHint: 100,
|
HeightHint: 100,
|
||||||
|
FullBlock: newEvent.fullBlock,
|
||||||
PostConfMapper: fn.Some[ConfMapper[dummyEvents]](
|
PostConfMapper: fn.Some[ConfMapper[dummyEvents]](
|
||||||
confMapper,
|
confMapper,
|
||||||
),
|
),
|
||||||
@@ -383,7 +385,8 @@ func (d *dummyAdapters) RegisterConfirmationsNtfn(txid *chainhash.Hash,
|
|||||||
opts ...chainntnfs.NotifierOption,
|
opts ...chainntnfs.NotifierOption,
|
||||||
) (*chainntnfs.ConfirmationEvent, error) {
|
) (*chainntnfs.ConfirmationEvent, error) {
|
||||||
|
|
||||||
args := d.Called(txid, pkScript, numConfs)
|
// Pass opts as the last argument to the mock call checker.
|
||||||
|
args := d.Called(txid, pkScript, numConfs, heightHint, opts)
|
||||||
|
|
||||||
err := args.Error(0)
|
err := args.Error(0)
|
||||||
|
|
||||||
@@ -589,11 +592,12 @@ func TestStateMachineDaemonEvents(t *testing.T) {
|
|||||||
env.AssertExpectations(t)
|
env.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestStateMachineConfMapper tests that the state machine is able to properly
|
// testStateMachineConfMapperImpl is a helper function that encapsulates the
|
||||||
// map the confirmation event into a custom event that can be used to trigger a
|
// core logic for testing the confirmation mapping functionality of the state
|
||||||
// state transition.
|
// machine. It takes a boolean flag `fullBlock` to determine whether to test the
|
||||||
func TestStateMachineConfMapper(t *testing.T) {
|
// scenario where full block details are requested in the confirmation
|
||||||
t.Parallel()
|
// notification.
|
||||||
|
func testStateMachineConfMapperImpl(t *testing.T, fullBlock bool) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Create the state machine.
|
// Create the state machine.
|
||||||
@@ -614,15 +618,49 @@ func TestStateMachineConfMapper(t *testing.T) {
|
|||||||
stateMachine.Start(ctx)
|
stateMachine.Start(ctx)
|
||||||
defer stateMachine.Stop()
|
defer stateMachine.Stop()
|
||||||
|
|
||||||
// Expect the RegisterConfirmationsNtfn call when we send the event.
|
// Define the expected arguments for the mock call.
|
||||||
// We use NumConfs=1 as the default.
|
expectedTxid := &chainhash.Hash{1}
|
||||||
adapters.On(
|
expectedPkScript := []byte{0x01}
|
||||||
"RegisterConfirmationsNtfn", &chainhash.Hash{1}, []byte{0x01},
|
expectedNumConfs := uint32(1)
|
||||||
uint32(1),
|
expectedHeightHint := uint32(100)
|
||||||
).Return(nil)
|
|
||||||
|
// Set up the mock expectation based on the FullBlock flag. We use
|
||||||
|
// mock.MatchedBy to assert the options passed.
|
||||||
|
if fullBlock {
|
||||||
|
// Expect WithIncludeBlock() option when FullBlock is true.
|
||||||
|
adapters.On(
|
||||||
|
"RegisterConfirmationsNtfn",
|
||||||
|
expectedTxid, expectedPkScript,
|
||||||
|
expectedNumConfs, expectedHeightHint,
|
||||||
|
mock.MatchedBy(
|
||||||
|
func(opts []chainntnfs.NotifierOption) bool {
|
||||||
|
// Check if exactly one option is passed
|
||||||
|
// and it's the correct type. Unless we
|
||||||
|
// use reflect, we can introspect into
|
||||||
|
// the private fields.
|
||||||
|
return len(opts) == 1
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).Return(nil)
|
||||||
|
} else {
|
||||||
|
// Expect no options when FullBlock is false.
|
||||||
|
adapters.On(
|
||||||
|
"RegisterConfirmationsNtfn",
|
||||||
|
expectedTxid, expectedPkScript,
|
||||||
|
expectedNumConfs, expectedHeightHint,
|
||||||
|
mock.MatchedBy(func(opts []chainntnfs.NotifierOption) bool { //nolint:ll
|
||||||
|
return len(opts) == 0
|
||||||
|
}),
|
||||||
|
).Return(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the registerConf event with the specified FullBlock value.
|
||||||
|
regConfEvent := ®isterConf{
|
||||||
|
fullBlock: fullBlock,
|
||||||
|
}
|
||||||
|
|
||||||
// Send the event that triggers RegisterConf emission.
|
// Send the event that triggers RegisterConf emission.
|
||||||
stateMachine.SendEvent(ctx, ®isterConf{})
|
stateMachine.SendEvent(ctx, regConfEvent)
|
||||||
|
|
||||||
// We should transition back to the starting state initially.
|
// We should transition back to the starting state initially.
|
||||||
expectedStates := []State[dummyEvents, *dummyEnv]{
|
expectedStates := []State[dummyEvents, *dummyEnv]{
|
||||||
@@ -630,11 +668,11 @@ func TestStateMachineConfMapper(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assertStateTransitions(t, stateSub, expectedStates)
|
assertStateTransitions(t, stateSub, expectedStates)
|
||||||
|
|
||||||
// Assert the registration call was made.
|
// Assert the registration call was made with the correct arguments
|
||||||
|
// (including options).
|
||||||
adapters.AssertExpectations(t)
|
adapters.AssertExpectations(t)
|
||||||
|
|
||||||
// Now, simulate the confirmation event coming back from the notifier.
|
// Now, simulate the confirmation event coming back from the notifier.
|
||||||
// Populate it with some data to be mapped.
|
|
||||||
simulatedConf := &chainntnfs.TxConfirmation{
|
simulatedConf := &chainntnfs.TxConfirmation{
|
||||||
BlockHash: &chainhash.Hash{2},
|
BlockHash: &chainhash.Hash{2},
|
||||||
BlockHeight: 123,
|
BlockHeight: 123,
|
||||||
@@ -642,7 +680,7 @@ func TestStateMachineConfMapper(t *testing.T) {
|
|||||||
adapters.confChan <- simulatedConf
|
adapters.confChan <- simulatedConf
|
||||||
|
|
||||||
// This should trigger the mapper and send the confDetailsEvent,
|
// This should trigger the mapper and send the confDetailsEvent,
|
||||||
// transitioning us to the final state.
|
// transitioning us to the confirmed state.
|
||||||
expectedStates = []State[dummyEvents, *dummyEnv]{&dummyStateConfirmed{}}
|
expectedStates = []State[dummyEvents, *dummyEnv]{&dummyStateConfirmed{}}
|
||||||
assertStateTransitions(t, stateSub, expectedStates)
|
assertStateTransitions(t, stateSub, expectedStates)
|
||||||
|
|
||||||
@@ -662,6 +700,23 @@ func TestStateMachineConfMapper(t *testing.T) {
|
|||||||
env.AssertExpectations(t)
|
env.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestStateMachineConfMapper tests the confirmation mapping functionality using
|
||||||
|
// subtests driven by the testStateMachineConfMapperImpl helper function. It
|
||||||
|
// covers scenarios both with and without requesting the full block details.
|
||||||
|
func TestStateMachineConfMapper(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
t.Run("full block false", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testStateMachineConfMapperImpl(t, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("full block true", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
testStateMachineConfMapperImpl(t, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestStateMachineSpendMapper tests that the state machine is able to properly
|
// TestStateMachineSpendMapper tests that the state machine is able to properly
|
||||||
// map the spend event into a custom event that can be used to trigger a state
|
// map the spend event into a custom event that can be used to trigger a state
|
||||||
// transition.
|
// transition.
|
||||||
|
Reference in New Issue
Block a user