// SendCoins attemps to send amt satoshis from the internal mining node to the // targetted lightning node. func (n *networkHarness) SendCoins(ctx context.Context, amt btcutil.Amount, target *lightningNode) error { balReq := &lnrpc.WalletBalanceRequest{} initialBalance, err := target.WalletBalance(ctx, balReq) if err != nil { return err } // First, obtain an address from the target lightning node, preferring // to receive a p2wkh address s.t the output can immediately be used as // an input to a funding transaction. addrReq := &lnrpc.NewAddressRequest{ Type: lnrpc.NewAddressRequest_WITNESS_PUBKEY_HASH, } resp, err := target.NewAddress(ctx, addrReq) if err != nil { return err } addr, err := btcutil.DecodeAddress(resp.Address, n.netParams) if err != nil { return err } addrScript, err := txscript.PayToAddrScript(addr) if err != nil { return err } // Generate a transaction which creates an output to the target // pkScript of the desired amount. output := &wire.TxOut{ PkScript: addrScript, Value: int64(amt), } if _, err := n.Miner.CoinbaseSpend([]*wire.TxOut{output}); err != nil { return err } // Finally, generate 6 new blocks to ensure the output gains a // sufficient number of confirmations. if _, err := n.Miner.Node.Generate(6); err != nil { return err } // Pause until the nodes current wallet balances reflects the amount // sent to it above. // TODO(roasbeef): factor out into helper func for { select { case <-time.Tick(time.Millisecond * 50): currentBal, err := target.WalletBalance(ctx, balReq) if err != nil { return err } if currentBal.Balance == initialBalance.Balance+amt.ToBTC() { return nil } case <-time.After(time.Second * 30): return fmt.Errorf("balances not synced after deadline") } } }