lntest+itest: expore method createSimpleNetwork

So it can be used via `ht.CreateSimpleNetwork`.
This commit is contained in:
yyforyongyu
2024-10-18 02:59:46 +08:00
parent 9682aa7a78
commit 35992e1503
5 changed files with 179 additions and 74 deletions

View File

@@ -2209,3 +2209,155 @@ func (h *HarnessTest) SendCoins(a, b *node.HarnessNode,
return tx
}
// CreateSimpleNetwork creates the number of nodes specified by the number of
// configs and makes a topology of `node1 -> node2 -> node3...`. Each node is
// created using the specified config, the neighbors are connected, and the
// channels are opened. Each node will be funded with a single UTXO of 1 BTC
// except the last one.
//
// For instance, to create a network with 2 nodes that share the same node
// config,
//
// cfg := []string{"--protocol.anchors"}
// cfgs := [][]string{cfg, cfg}
// params := OpenChannelParams{...}
// chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, params)
//
// This will create two nodes and open an anchor channel between them.
func (h *HarnessTest) CreateSimpleNetwork(nodeCfgs [][]string,
p OpenChannelParams) ([]*lnrpc.ChannelPoint, []*node.HarnessNode) {
// Create new nodes.
nodes := h.createNodes(nodeCfgs)
var resp []*lnrpc.ChannelPoint
// Open zero-conf channels if specified.
if p.ZeroConf {
resp = h.openZeroConfChannelsForNodes(nodes, p)
} else {
// Open channels between the nodes.
resp = h.openChannelsForNodes(nodes, p)
}
return resp, nodes
}
// acceptChannel is used to accept a single channel that comes across. This
// should be run in a goroutine and is used to test nodes with the zero-conf
// feature bit.
func acceptChannel(t *testing.T, zeroConf bool, stream rpc.AcceptorClient) {
req, err := stream.Recv()
require.NoError(t, err)
resp := &lnrpc.ChannelAcceptResponse{
Accept: true,
PendingChanId: req.PendingChanId,
ZeroConf: zeroConf,
}
err = stream.Send(resp)
require.NoError(t, err)
}
// createNodes creates the number of nodes specified by the number of configs.
// Each node is created using the specified config, the neighbors are
// connected.
func (h *HarnessTest) createNodes(nodeCfgs [][]string) []*node.HarnessNode {
// Get the number of nodes.
numNodes := len(nodeCfgs)
// Make a slice of nodes.
nodes := make([]*node.HarnessNode, numNodes)
// Create new nodes.
for i, nodeCfg := range nodeCfgs {
nodeName := fmt.Sprintf("Node%q", string(rune('A'+i)))
n := h.NewNode(nodeName, nodeCfg)
nodes[i] = n
}
// Connect the nodes in a chain.
for i := 1; i < len(nodes); i++ {
nodeA := nodes[i-1]
nodeB := nodes[i]
h.EnsureConnected(nodeA, nodeB)
}
// Fund all the nodes expect the last one.
for i := 0; i < len(nodes)-1; i++ {
node := nodes[i]
h.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, node)
}
// Mine 1 block to get the above coins confirmed.
h.MineBlocksAndAssertNumTxes(1, numNodes-1)
return nodes
}
// openChannelsForNodes takes a list of nodes and makes a topology of `node1 ->
// node2 -> node3...`.
func (h *HarnessTest) openChannelsForNodes(nodes []*node.HarnessNode,
p OpenChannelParams) []*lnrpc.ChannelPoint {
// Sanity check the params.
require.False(h, p.ZeroConf, "zero-conf channels must be disabled")
require.Greater(h, len(nodes), 1, "need at least 2 nodes")
// Open channels in batch to save blocks mined.
reqs := make([]*OpenChannelRequest, 0, len(nodes)-1)
for i := 0; i < len(nodes)-1; i++ {
nodeA := nodes[i]
nodeB := nodes[i+1]
req := &OpenChannelRequest{
Local: nodeA,
Remote: nodeB,
Param: p,
}
reqs = append(reqs, req)
}
resp := h.OpenMultiChannelsAsync(reqs)
// Make sure the nodes know each other's channels if they are public.
if !p.Private {
for _, node := range nodes {
for _, chanPoint := range resp {
h.AssertTopologyChannelOpen(node, chanPoint)
}
}
}
return resp
}
// openZeroConfChannelsForNodes takes a list of nodes and makes a topology of
// `node1 -> node2 -> node3...` with zero-conf channels.
func (h *HarnessTest) openZeroConfChannelsForNodes(nodes []*node.HarnessNode,
p OpenChannelParams) []*lnrpc.ChannelPoint {
// Sanity check the params.
require.True(h, p.ZeroConf, "zero-conf channels must be enabled")
require.Greater(h, len(nodes), 1, "need at least 2 nodes")
// We are opening numNodes-1 channels.
cancels := make([]context.CancelFunc, 0, len(nodes)-1)
// Create the channel acceptors.
for _, node := range nodes[1:] {
acceptor, cancel := node.RPC.ChannelAcceptor()
go acceptChannel(h.T, true, acceptor)
cancels = append(cancels, cancel)
}
// Open channels between the nodes.
resp := h.openChannelsForNodes(nodes, p)
for _, cancel := range cancels {
cancel()
}
return resp
}