Skip to content

Commit d453f81

Browse files
committed
tapdb: update InsertScriptKey to allow flipping known to true
In this commit, we update `InsertScriptKey` to allow flipping known to true, if it was false before. This is useful as at times a script key from a smart contract might have been inserting on disk, but with declared known as false. Then if we tried to insert it again, with known as true, the upsert logic would end up making no change on disk.
1 parent d79e141 commit d453f81

File tree

4 files changed

+132
-2
lines changed

4 files changed

+132
-2
lines changed

tapdb/addrs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ func (t *TapAddressBook) InsertScriptKey(ctx context.Context,
689689
return fmt.Errorf("error inserting internal key: %w",
690690
err)
691691
}
692+
692693
_, err = q.UpsertScriptKey(ctx, NewScriptKey{
693694
InternalKeyID: internalKeyID,
694695
TweakedScriptKey: scriptKey.PubKey.SerializeCompressed(),

tapdb/addrs_test.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tapdb
33
import (
44
"context"
55
"database/sql"
6+
"fmt"
67
"math/rand"
78
"testing"
89
"time"
@@ -11,9 +12,11 @@ import (
1112
"github.com/btcsuite/btcd/wire"
1213
"github.com/lightninglabs/lndclient"
1314
"github.com/lightninglabs/taproot-assets/address"
15+
"github.com/lightninglabs/taproot-assets/asset"
1416
"github.com/lightninglabs/taproot-assets/internal/test"
1517
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
1618
"github.com/lightningnetwork/lnd/clock"
19+
"github.com/lightningnetwork/lnd/keychain"
1720
"github.com/lightningnetwork/lnd/lnrpc"
1821
"github.com/stretchr/testify/require"
1922
)
@@ -644,3 +647,113 @@ func TestAddressEventQuery(t *testing.T) {
644647
})
645648
}
646649
}
650+
651+
// randScriptKey makes a random script key with a tweak.
652+
func randScriptKey(t *testing.T) asset.ScriptKey {
653+
scriptKey := asset.RandScriptKey(t)
654+
scriptKey.TweakedScriptKey = &asset.TweakedScriptKey{
655+
RawKey: keychain.KeyDescriptor{
656+
PubKey: asset.RandScriptKey(t).PubKey,
657+
},
658+
}
659+
660+
return scriptKey
661+
}
662+
663+
// insertScriptKeyWithNull is a helper function that inserts a script key with a
664+
// a NULL value for declared known. We use this so we can insert a NULL vs an
665+
// actual value. It is identical to the InsertScriptKey.
666+
func insertScriptKeyWithNull(ctx context.Context, key asset.ScriptKey,
667+
) func(AddrBook) error {
668+
669+
return func(q AddrBook) error {
670+
internalKeyID, err := insertInternalKey(
671+
ctx, q, key.RawKey,
672+
)
673+
if err != nil {
674+
return fmt.Errorf("error inserting internal key: %w",
675+
err)
676+
}
677+
678+
_, err = q.UpsertScriptKey(ctx, NewScriptKey{
679+
InternalKeyID: internalKeyID,
680+
TweakedScriptKey: key.PubKey.SerializeCompressed(),
681+
Tweak: key.Tweak,
682+
DeclaredKnown: sql.NullBool{
683+
Valid: false,
684+
},
685+
})
686+
return err
687+
}
688+
}
689+
690+
func assertKeyKnowledge(t *testing.T, ctx context.Context,
691+
addrBook *TapAddressBook, scriptKey asset.ScriptKey, known bool) {
692+
693+
dbScriptKey, err := addrBook.FetchScriptKey(ctx, scriptKey.PubKey)
694+
require.NoError(t, err)
695+
require.Equal(t, known, dbScriptKey.DeclaredKnown)
696+
}
697+
698+
// TestScriptKeyKnownUpsert tests that we can insert a script key, then insert
699+
// it again declared as known.
700+
func TestScriptKeyKnownUpsert(t *testing.T) {
701+
t.Parallel()
702+
703+
// First, make a new addr book instance we'll use in the test below.
704+
testClock := clock.NewTestClock(time.Now())
705+
addrBook, _ := newAddrBook(t, testClock)
706+
707+
ctx := context.Background()
708+
709+
// In this test, we insert the known field as false, and make sure we
710+
// can flip it back to true.
711+
t.Run("false_to_true", func(t *testing.T) {
712+
known := false
713+
scriptKey := randScriptKey(t)
714+
715+
// We'll insert a random script key into the database. We won't
716+
// declare it as known though.
717+
err := addrBook.InsertScriptKey(ctx, scriptKey, known)
718+
require.NoError(t, err)
719+
720+
// We'll fetch the script key and confirm that it's not known.
721+
assertKeyKnowledge(t, ctx, addrBook, scriptKey, known)
722+
723+
known = true
724+
725+
// We'll now insert it again, but this time declare it as known.
726+
err = addrBook.InsertScriptKey(ctx, scriptKey, known)
727+
require.NoError(t, err)
728+
729+
// We'll fetch the script key and confirm that it's known.
730+
assertKeyKnowledge(t, ctx, addrBook, scriptKey, known)
731+
})
732+
733+
// In this test, we insert a NULL value, and make sure that it can still
734+
// be set to true.
735+
t.Run("null_to_true", func(t *testing.T) {
736+
known := false
737+
scriptKey := randScriptKey(t)
738+
739+
// We'll lift the internal routine of InsertScriptKey so we can
740+
// insert an actual NULL here.
741+
err := addrBook.db.ExecTx(
742+
ctx, &AddrBookTxOptions{},
743+
insertScriptKeyWithNull(ctx, scriptKey),
744+
)
745+
require.NoError(t, err)
746+
747+
// We'll fetch the script key and confirm that it's not known.
748+
assertKeyKnowledge(t, ctx, addrBook, scriptKey, known)
749+
750+
known = true
751+
752+
// We'll now insert it again, but this time declare it as known.
753+
err = addrBook.InsertScriptKey(ctx, scriptKey, known)
754+
require.NoError(t, err)
755+
756+
// We'll fetch the script key and confirm that it's known.
757+
assertKeyKnowledge(t, ctx, addrBook, scriptKey, known)
758+
})
759+
}

tapdb/sqlc/assets.sql.go

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/sqlc/queries/assets.sql

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,15 @@ INSERT INTO script_keys (
854854
) ON CONFLICT (tweaked_script_key)
855855
-- As a NOP, we just set the script key to the one that triggered the
856856
-- conflict.
857-
DO UPDATE SET tweaked_script_key = EXCLUDED.tweaked_script_key
857+
DO UPDATE SET
858+
tweaked_script_key = EXCLUDED.tweaked_script_key,
859+
-- If the script key was previously unknown, we'll update to the new
860+
-- value.
861+
declared_known = CASE
862+
WHEN script_keys.declared_known IS NULL OR script_keys.declared_known = FALSE
863+
THEN COALESCE(EXCLUDED.declared_known, script_keys.declared_known)
864+
ELSE script_keys.declared_known
865+
END
858866
RETURNING script_key_id;
859867

860868
-- name: FetchScriptKeyIDByTweakedKey :one

0 commit comments

Comments
 (0)