@@ -1223,6 +1223,113 @@ func TestSupplyCommitInsertPendingUpdate(t *testing.T) {
12231223 assertEqualEvents (t , event3 , deserializedDangling )
12241224}
12251225
1226+ // TestBindDanglingUpdatesToTransition tests the logic for binding dangling
1227+ // updates to a new transition.
1228+ func TestBindDanglingUpdatesToTransition (t * testing.T ) {
1229+ t .Parallel ()
1230+
1231+ h := newSupplyCommitTestHarness (t )
1232+
1233+ // If no dangling updates exist, the method should be a no-op.
1234+ boundEvents , err := h .commitMachine .BindDanglingUpdatesToTransition (
1235+ h .ctx , h .assetSpec ,
1236+ )
1237+ require .NoError (t , err )
1238+ require .Empty (t , boundEvents )
1239+ h .assertNoPendingTransition ()
1240+
1241+ // To create dangling updates, we first need a state machine and a
1242+ // finalized transition.
1243+ updates1 := []supplycommit.SupplyUpdateEvent {h .randMintEvent ()}
1244+ stateTransition1 := h .performSingleTransition (updates1 )
1245+ h .assertTransitionApplied (stateTransition1 )
1246+
1247+ // Now, with the machine in DefaultState, we'll manually insert some
1248+ // dangling events into the DB. This simulates events arriving while a
1249+ // transition was in flight and frozen.
1250+ danglingEvent1 := h .randBurnEvent ()
1251+ danglingEvent2 := h .randIgnoreEvent ()
1252+ danglingEventsToInsert := []supplycommit.SupplyUpdateEvent {
1253+ danglingEvent1 , danglingEvent2 ,
1254+ }
1255+
1256+ // We use a custom transaction to short circuit some of the logic in the
1257+ // public API.
1258+ var writeTx SupplyCommitTxOptions
1259+ err = h .commitMachine .db .ExecTx (
1260+ h .ctx , & writeTx , func (db SupplyCommitStore ) error {
1261+ for _ , event := range danglingEventsToInsert {
1262+ var b bytes.Buffer
1263+ err := serializeSupplyUpdateEvent (& b , event )
1264+ require .NoError (t , err )
1265+ updateTypeID , err := updateTypeToInt (
1266+ event .SupplySubTreeType (),
1267+ )
1268+ require .NoError (t , err )
1269+
1270+ err = db .InsertSupplyUpdateEvent (
1271+ h .ctx , InsertSupplyUpdateEvent {
1272+ GroupKey : h .groupKeyBytes ,
1273+ TransitionID : sql.NullInt64 {},
1274+ UpdateTypeID : updateTypeID ,
1275+ EventData : b .Bytes (),
1276+ },
1277+ )
1278+ require .NoError (t , err )
1279+ }
1280+
1281+ return nil
1282+ },
1283+ )
1284+ require .NoError (t , err )
1285+
1286+ // We should now that that updates are properly dangling.
1287+ require .Len (t , h .fetchDanglingUpdates (), 2 )
1288+
1289+ // Now we'll bind the set of dangling updates, this should create a new
1290+ // state transition and associate the events with it.
1291+ boundEvents , err = h .commitMachine .BindDanglingUpdatesToTransition (
1292+ h .ctx , h .assetSpec ,
1293+ )
1294+ require .NoError (t , err )
1295+
1296+ // Assert that the returned events match what we inserted. We'll sort
1297+ // first to ensure a deterministic comparison.
1298+ sorter := func (events []supplycommit.SupplyUpdateEvent ) {
1299+ sort .SliceStable (events , func (i , j int ) bool {
1300+ keyI := events [i ].UniverseLeafKey ().UniverseKey ()
1301+ keyJ := events [j ].UniverseLeafKey ().UniverseKey ()
1302+ return bytes .Compare (keyI [:], keyJ [:]) < 0
1303+ })
1304+ }
1305+ sorter (danglingEventsToInsert )
1306+ sorter (boundEvents )
1307+ require .Len (t , boundEvents , 2 )
1308+
1309+ // The dangling events read out should now match what we inserted.
1310+ assertEqualEvents (t , danglingEventsToInsert [0 ], boundEvents [0 ])
1311+ assertEqualEvents (t , danglingEventsToInsert [1 ], boundEvents [1 ])
1312+
1313+ // A new state transition should have been created, and there should be
1314+ // no dangling updates.
1315+ dbTransition := h .assertPendingTransitionExists ()
1316+ require .Empty (t , h .fetchDanglingUpdates ())
1317+
1318+ // The state transition should also now include the set of dangling
1319+ // updates.
1320+ h .assertPendingUpdates (danglingEventsToInsert )
1321+
1322+ // The new transition's old_commitment_id should point to the one from
1323+ // the finalized transition.
1324+ stateMachine , err := h .fetchStateMachine ()
1325+ require .NoError (t , err )
1326+ require .True (t , stateMachine .LatestCommitmentID .Valid )
1327+ require .Equal (
1328+ t , stateMachine .LatestCommitmentID ,
1329+ dbTransition .OldCommitmentID ,
1330+ )
1331+ }
1332+
12261333// TestSupplyCommitInsertSignedCommitTx tests associating a signed commit tx
12271334// with a transition.
12281335func TestSupplyCommitInsertSignedCommitTx (t * testing.T ) {
@@ -1819,10 +1926,13 @@ func encodeTx(tx *wire.MsgTx) ([]byte, error) {
18191926// comparing the resulting bytes.
18201927func assertEqualEvents (t * testing.T , expected , actual supplycommit.SupplyUpdateEvent ) {
18211928 t .Helper ()
1929+
18221930 var expectedBytes , actualBytes bytes.Buffer
18231931 err := serializeSupplyUpdateEvent (& expectedBytes , expected )
18241932 require .NoError (t , err )
1933+
18251934 err = serializeSupplyUpdateEvent (& actualBytes , actual )
18261935 require .NoError (t , err )
1936+
18271937 require .Equal (t , expectedBytes .String (), actualBytes .String ())
18281938}
0 commit comments