graph/db: support v2 channel proofs in AddEdgeProof
Update AddEdgeProof to handle both v1 (four separate signatures) and v2 (single aggregated signature) channel authentication proofs using the appropriate SQL queries.
This commit is contained in:
2 files changed
+92
-87
No files matched your search
+62
-76
@@ -138,6 +138,10 @@ var versionedTests = []versionedTest{
|
|||||||
name: "alias lookup",
|
name: "alias lookup",
|
||||||
test: testAliasLookup,
|
test: testAliasLookup,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "add edge proof",
|
||||||
|
test: testAddEdgeProof,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestVersionedDBs runs various tests against both v1 and v2 versioned
|
// TestVersionedDBs runs various tests against both v1 and v2 versioned
|
||||||
@@ -644,8 +648,10 @@ func TestEdgeInsertionDeletion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
||||||
txPosition uint16, outPointIndex uint32, node1, node2 *models.Node) (
|
txPosition uint16, outPointIndex uint32, node1, node2 *models.Node,
|
||||||
*models.ChannelEdgeInfo, lnwire.ShortChannelID) {
|
skipProof ...bool) (*models.ChannelEdgeInfo, lnwire.ShortChannelID) {
|
||||||
|
|
||||||
|
shouldSkipProof := len(skipProof) > 0 && skipProof[0]
|
||||||
|
|
||||||
shortChanID := lnwire.ShortChannelID{
|
shortChanID := lnwire.ShortChannelID{
|
||||||
BlockHeight: height,
|
BlockHeight: height,
|
||||||
@@ -677,12 +683,19 @@ func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
|||||||
node2Pub.SerializeCompressed(),
|
node2Pub.SerializeCompressed(),
|
||||||
)
|
)
|
||||||
|
|
||||||
proof := models.NewV1ChannelAuthProof(
|
opts := []models.EdgeModifier{
|
||||||
testSig.Serialize(),
|
models.WithChannelPoint(outpoint),
|
||||||
testSig.Serialize(),
|
models.WithCapacity(9000),
|
||||||
testSig.Serialize(),
|
}
|
||||||
testSig.Serialize(),
|
if !shouldSkipProof {
|
||||||
)
|
proof := models.NewV1ChannelAuthProof(
|
||||||
|
testSig.Serialize(),
|
||||||
|
testSig.Serialize(),
|
||||||
|
testSig.Serialize(),
|
||||||
|
testSig.Serialize(),
|
||||||
|
)
|
||||||
|
opts = append(opts, models.WithChanProof(proof))
|
||||||
|
}
|
||||||
|
|
||||||
edgeInfo, _ = models.NewV1Channel(
|
edgeInfo, _ = models.NewV1Channel(
|
||||||
shortChanID.ToUint64(),
|
shortChanID.ToUint64(),
|
||||||
@@ -694,9 +707,7 @@ func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
|||||||
BitcoinKey2Bytes: btcKey2,
|
BitcoinKey2Bytes: btcKey2,
|
||||||
ExtraOpaqueData: make([]byte, 0),
|
ExtraOpaqueData: make([]byte, 0),
|
||||||
},
|
},
|
||||||
models.WithChanProof(proof),
|
opts...,
|
||||||
models.WithChannelPoint(outpoint),
|
|
||||||
models.WithCapacity(9000),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
case lnwire.GossipVersion2:
|
case lnwire.GossipVersion2:
|
||||||
@@ -717,7 +728,16 @@ func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
|||||||
fundingScript, bytes.Repeat([]byte{0xbb}, 32)...,
|
fundingScript, bytes.Repeat([]byte{0xbb}, 32)...,
|
||||||
)
|
)
|
||||||
|
|
||||||
proof := models.NewV2ChannelAuthProof(testSig.Serialize())
|
opts := []models.EdgeModifier{
|
||||||
|
models.WithChannelPoint(outpoint),
|
||||||
|
models.WithCapacity(9000),
|
||||||
|
}
|
||||||
|
if !shouldSkipProof {
|
||||||
|
proof := models.NewV2ChannelAuthProof(
|
||||||
|
testSig.Serialize(),
|
||||||
|
)
|
||||||
|
opts = append(opts, models.WithChanProof(proof))
|
||||||
|
}
|
||||||
|
|
||||||
edgeInfo, _ = models.NewV2Channel(
|
edgeInfo, _ = models.NewV2Channel(
|
||||||
shortChanID.ToUint64(),
|
shortChanID.ToUint64(),
|
||||||
@@ -731,9 +751,7 @@ func createEdge(version lnwire.GossipVersion, height, txIndex uint32,
|
|||||||
FundingScript: fn.Some(fundingScript),
|
FundingScript: fn.Some(fundingScript),
|
||||||
ExtraSignedFields: make(map[uint64][]byte),
|
ExtraSignedFields: make(map[uint64][]byte),
|
||||||
},
|
},
|
||||||
models.WithChanProof(proof),
|
opts...,
|
||||||
models.WithChannelPoint(outpoint),
|
|
||||||
models.WithCapacity(9000),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -940,29 +958,9 @@ func assertEdgeInfoEqual(t *testing.T, e1 *models.ChannelEdgeInfo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type createEdgeConfig struct {
|
func createChannelEdge(node1, node2 *models.Node) (*models.ChannelEdgeInfo,
|
||||||
skipProofs bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type createEdgeOpt func(*createEdgeConfig)
|
|
||||||
|
|
||||||
// withSkipProofs will let createChannelEdge create an edge without auth
|
|
||||||
// proofs. In this case, createChannelEdge will then also not create policies.
|
|
||||||
func withSkipProofs() createEdgeOpt {
|
|
||||||
return func(cfg *createEdgeConfig) {
|
|
||||||
cfg.skipProofs = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createChannelEdge(node1, node2 *models.Node,
|
|
||||||
options ...createEdgeOpt) (*models.ChannelEdgeInfo,
|
|
||||||
*models.ChannelEdgePolicy, *models.ChannelEdgePolicy) {
|
*models.ChannelEdgePolicy, *models.ChannelEdgePolicy) {
|
||||||
|
|
||||||
var opts createEdgeConfig
|
|
||||||
for _, o := range options {
|
|
||||||
o(&opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
firstNode [33]byte
|
firstNode [33]byte
|
||||||
secondNode [33]byte
|
secondNode [33]byte
|
||||||
@@ -995,21 +993,6 @@ func createChannelEdge(node1, node2 *models.Node,
|
|||||||
3, 3, 3, 3, 3,
|
3, 3, 3, 3, 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
var edgeInfo *models.ChannelEdgeInfo
|
|
||||||
if opts.skipProofs {
|
|
||||||
edgeInfo, _ = models.NewV1Channel(
|
|
||||||
chanID, *chaincfg.MainNetParams.GenesisHash, node1Key,
|
|
||||||
node2Key, &models.ChannelV1Fields{
|
|
||||||
BitcoinKey1Bytes: node1Key,
|
|
||||||
BitcoinKey2Bytes: node2Key,
|
|
||||||
ExtraOpaqueData: extraData,
|
|
||||||
}, models.WithChannelPoint(outpoint),
|
|
||||||
models.WithCapacity(1000),
|
|
||||||
)
|
|
||||||
|
|
||||||
return edgeInfo, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
proof := models.NewV1ChannelAuthProof(
|
proof := models.NewV1ChannelAuthProof(
|
||||||
testSig.Serialize(),
|
testSig.Serialize(),
|
||||||
testSig.Serialize(),
|
testSig.Serialize(),
|
||||||
@@ -1017,7 +1000,7 @@ func createChannelEdge(node1, node2 *models.Node,
|
|||||||
testSig.Serialize(),
|
testSig.Serialize(),
|
||||||
)
|
)
|
||||||
|
|
||||||
edgeInfo, _ = models.NewV1Channel(
|
edgeInfo, _ := models.NewV1Channel(
|
||||||
chanID, *chaincfg.MainNetParams.GenesisHash, node1Key, node2Key,
|
chanID, *chaincfg.MainNetParams.GenesisHash, node1Key, node2Key,
|
||||||
&models.ChannelV1Fields{
|
&models.ChannelV1Fields{
|
||||||
BitcoinKey1Bytes: node1Key,
|
BitcoinKey1Bytes: node1Key,
|
||||||
@@ -1457,42 +1440,48 @@ func newEdgePolicy(chanID uint64, updateTime int64) *models.ChannelEdgePolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestAddEdgeProof tests the ability to add an edge proof to an existing edge.
|
// testAddEdgeProof tests the ability to add an edge proof to an existing edge.
|
||||||
func TestAddEdgeProof(t *testing.T) {
|
func testAddEdgeProof(t *testing.T, v lnwire.GossipVersion) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
ctx := t.Context()
|
ctx := t.Context()
|
||||||
|
|
||||||
graph := MakeTestGraph(t)
|
graph := NewVersionedGraph(MakeTestGraph(t), v)
|
||||||
|
|
||||||
// Add an edge with no proof.
|
// Add an edge with no proof.
|
||||||
node1 := createTestVertex(t, lnwire.GossipVersion1)
|
node1 := createTestVertex(t, v)
|
||||||
node2 := createTestVertex(t, lnwire.GossipVersion1)
|
node2 := createTestVertex(t, v)
|
||||||
edge1, _, _ := createChannelEdge(node1, node2, withSkipProofs())
|
|
||||||
|
// Create edge without proof (skipProof = true).
|
||||||
|
edge1, _ := createEdge(v, 100, 0, 0, 0, node1, node2, true)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, edge1))
|
require.NoError(t, graph.AddChannelEdge(ctx, edge1))
|
||||||
|
|
||||||
// Fetch the edge and assert that the proof is nil and that the rest
|
// Fetch the edge and assert that the proof is nil.
|
||||||
// of the edge info is correct.
|
|
||||||
dbEdge, _, _, err := graph.FetchChannelEdgesByID(edge1.ChannelID)
|
dbEdge, _, _, err := graph.FetchChannelEdgesByID(edge1.ChannelID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Nil(t, dbEdge.AuthProof)
|
require.Nil(t, dbEdge.AuthProof)
|
||||||
require.Equal(t, edge1, dbEdge)
|
|
||||||
|
|
||||||
// Now, add the edge proof.
|
// Create a proof appropriate for the version.
|
||||||
proof := models.NewV1ChannelAuthProof(
|
var proof *models.ChannelAuthProof
|
||||||
testSig.Serialize(),
|
switch v {
|
||||||
testSig.Serialize(),
|
case lnwire.GossipVersion1:
|
||||||
testSig.Serialize(),
|
proof = models.NewV1ChannelAuthProof(
|
||||||
testSig.Serialize(),
|
testSig.Serialize(),
|
||||||
)
|
testSig.Serialize(),
|
||||||
|
testSig.Serialize(),
|
||||||
|
testSig.Serialize(),
|
||||||
|
)
|
||||||
|
case lnwire.GossipVersion2:
|
||||||
|
proof = models.NewV2ChannelAuthProof(testSig.Serialize())
|
||||||
|
}
|
||||||
|
|
||||||
// First, add the proof to the rest of the channel edge info and try
|
// First, add the proof to the rest of the channel edge info and try
|
||||||
// to call AddChannelEdge again - this should fail due to the channel
|
// to call AddChannelEdge again - this should fail due to the channel
|
||||||
// already existing.
|
// already existing.
|
||||||
edge1.AuthProof = proof
|
edge1.AuthProof = proof
|
||||||
err = graph.AddChannelEdge(ctx, edge1)
|
err = graph.AddChannelEdge(ctx, edge1)
|
||||||
require.Error(t, err, ErrEdgeAlreadyExist)
|
require.ErrorIs(t, err, ErrEdgeAlreadyExist)
|
||||||
|
|
||||||
// Now add just the proof.
|
// Now add just the proof via AddEdgeProof.
|
||||||
scid1 := lnwire.NewShortChanIDFromInt(edge1.ChannelID)
|
scid1 := lnwire.NewShortChanIDFromInt(edge1.ChannelID)
|
||||||
require.NoError(t, graph.AddEdgeProof(scid1, proof))
|
require.NoError(t, graph.AddEdgeProof(scid1, proof))
|
||||||
|
|
||||||
@@ -1500,19 +1489,16 @@ func TestAddEdgeProof(t *testing.T) {
|
|||||||
dbEdge, _, _, err = graph.FetchChannelEdgesByID(edge1.ChannelID)
|
dbEdge, _, _, err = graph.FetchChannelEdgesByID(edge1.ChannelID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, dbEdge.AuthProof)
|
require.NotNil(t, dbEdge.AuthProof)
|
||||||
require.Equal(t, edge1, dbEdge)
|
|
||||||
|
|
||||||
// For completeness, also test the case where we insert a new edge with
|
// For completeness, also test the case where we insert a new edge with
|
||||||
// an edge proof. Show that the proof is present from the get go.
|
// an edge proof from the start. Show that the proof is present.
|
||||||
edge2, _, _ := createChannelEdge(node1, node2)
|
edge2, _ := createEdge(v, 200, 0, 0, 1, node1, node2)
|
||||||
require.NoError(t, graph.AddChannelEdge(ctx, edge2))
|
require.NoError(t, graph.AddChannelEdge(ctx, edge2))
|
||||||
|
|
||||||
// Fetch the edge and assert that the proof is nil and that the rest
|
// Fetch the edge and assert that the proof is set.
|
||||||
// of the edge info is correct.
|
|
||||||
dbEdge2, _, _, err := graph.FetchChannelEdgesByID(edge2.ChannelID)
|
dbEdge2, _, _, err := graph.FetchChannelEdgesByID(edge2.ChannelID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, dbEdge2.AuthProof)
|
require.NotNil(t, dbEdge2.AuthProof)
|
||||||
require.Equal(t, edge2, dbEdge2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestForEachSourceNodeChannel tests that the ForEachSourceNodeChannel
|
// TestForEachSourceNodeChannel tests that the ForEachSourceNodeChannel
|
||||||
|
|||||||
+30
-11
@@ -82,6 +82,7 @@ type SQLQueries interface {
|
|||||||
*/
|
*/
|
||||||
CreateChannel(ctx context.Context, arg sqlc.CreateChannelParams) (int64, error)
|
CreateChannel(ctx context.Context, arg sqlc.CreateChannelParams) (int64, error)
|
||||||
AddV1ChannelProof(ctx context.Context, arg sqlc.AddV1ChannelProofParams) (sql.Result, error)
|
AddV1ChannelProof(ctx context.Context, arg sqlc.AddV1ChannelProofParams) (sql.Result, error)
|
||||||
|
AddV2ChannelProof(ctx context.Context, arg sqlc.AddV2ChannelProofParams) (sql.Result, error)
|
||||||
GetChannelBySCID(ctx context.Context, arg sqlc.GetChannelBySCIDParams) (sqlc.GraphChannel, error)
|
GetChannelBySCID(ctx context.Context, arg sqlc.GetChannelBySCIDParams) (sqlc.GraphChannel, error)
|
||||||
GetChannelsBySCIDs(ctx context.Context, arg sqlc.GetChannelsBySCIDsParams) ([]sqlc.GraphChannel, error)
|
GetChannelsBySCIDs(ctx context.Context, arg sqlc.GetChannelsBySCIDsParams) ([]sqlc.GraphChannel, error)
|
||||||
GetChannelsByOutpoints(ctx context.Context, outpoints []string) ([]sqlc.GetChannelsByOutpointsRow, error)
|
GetChannelsByOutpoints(ctx context.Context, outpoints []string) ([]sqlc.GetChannelsByOutpointsRow, error)
|
||||||
@@ -2984,9 +2985,8 @@ func (s *SQLStore) DisconnectBlockAtHeight(height uint32) (
|
|||||||
func (s *SQLStore) AddEdgeProof(scid lnwire.ShortChannelID,
|
func (s *SQLStore) AddEdgeProof(scid lnwire.ShortChannelID,
|
||||||
proof *models.ChannelAuthProof) error {
|
proof *models.ChannelAuthProof) error {
|
||||||
|
|
||||||
// For now, we only support v1 channel proofs.
|
if !isKnownGossipVersion(proof.Version) {
|
||||||
if proof.Version != lnwire.GossipVersion1 {
|
return fmt.Errorf("unsupported gossip version: %d",
|
||||||
return fmt.Errorf("only v1 channel proofs supported, got v%d",
|
|
||||||
proof.Version)
|
proof.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2996,15 +2996,34 @@ func (s *SQLStore) AddEdgeProof(scid lnwire.ShortChannelID,
|
|||||||
)
|
)
|
||||||
|
|
||||||
err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error {
|
err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error {
|
||||||
res, err := db.AddV1ChannelProof(
|
var (
|
||||||
ctx, sqlc.AddV1ChannelProofParams{
|
res sql.Result
|
||||||
Scid: scidBytes,
|
err error
|
||||||
Node1Signature: proof.NodeSig1(),
|
|
||||||
Node2Signature: proof.NodeSig2(),
|
|
||||||
Bitcoin1Signature: proof.BitcoinSig1(),
|
|
||||||
Bitcoin2Signature: proof.BitcoinSig2(),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
switch proof.Version {
|
||||||
|
case lnwire.GossipVersion1:
|
||||||
|
res, err = db.AddV1ChannelProof(
|
||||||
|
ctx, sqlc.AddV1ChannelProofParams{
|
||||||
|
Scid: scidBytes,
|
||||||
|
Node1Signature: proof.NodeSig1(),
|
||||||
|
Node2Signature: proof.NodeSig2(),
|
||||||
|
Bitcoin1Signature: proof.BitcoinSig1(),
|
||||||
|
Bitcoin2Signature: proof.BitcoinSig2(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
case lnwire.GossipVersion2:
|
||||||
|
res, err = db.AddV2ChannelProof(
|
||||||
|
ctx, sqlc.AddV2ChannelProofParams{
|
||||||
|
Scid: scidBytes,
|
||||||
|
Signature: proof.Sig(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported gossip version: %d",
|
||||||
|
proof.Version)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to add edge proof: %w", err)
|
return fmt.Errorf("unable to add edge proof: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user