Add functions for Lease & Release output functions (#3677)

* Add functions for Lease & Release output functions

* Add test
This commit is contained in:
benthecarman 2021-09-19 07:20:39 -05:00 committed by GitHub
parent 132479d271
commit b6f28456e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 3 deletions

View File

@ -52,4 +52,10 @@ case class TxDetails(
destAddresses: Vector[BitcoinAddress], destAddresses: Vector[BitcoinAddress],
tx: Transaction, tx: Transaction,
label: String label: String
) ) extends LndModel
case class UTXOLease(
id: ByteVector,
outPoint: TransactionOutPoint,
expiration: Long
) extends LndModel

View File

@ -7,6 +7,8 @@ import org.bitcoins.core.protocol.ln.currency._
import org.bitcoins.core.protocol.script.P2WPKHWitnessSPKV0 import org.bitcoins.core.protocol.script.P2WPKHWitnessSPKV0
import org.bitcoins.testkit.fixtures.LndFixture import org.bitcoins.testkit.fixtures.LndFixture
import scala.concurrent.Future
class LndRpcClientTest extends LndFixture { class LndRpcClientTest extends LndFixture {
it must "get info from lnd" in { lnd => it must "get info from lnd" in { lnd =>
@ -99,4 +101,19 @@ class LndRpcClientTest extends LndFixture {
assert(balances.unsettledRemoteBalance == Satoshis.zero) assert(balances.unsettledRemoteBalance == Satoshis.zero)
} }
} }
it must "lease and release an output" in { lnd =>
for {
utxos <- lnd.listUnspent
leaseFs = utxos.map(u => lnd.leaseOutput(u.outPointOpt.get, 100))
_ <- Future.sequence(leaseFs)
leases <- lnd.listLeases()
_ = assert(leases.size == utxos.size)
releaseFs = utxos.map(u => lnd.releaseOutput(u.outPointOpt.get))
_ <- Future.sequence(releaseFs)
leases <- lnd.listLeases()
} yield assert(leases.isEmpty)
}
} }

View File

@ -29,9 +29,16 @@ import org.bitcoins.crypto._
import org.bitcoins.lnd.rpc.LndRpcClient._ import org.bitcoins.lnd.rpc.LndRpcClient._
import org.bitcoins.lnd.rpc.LndUtils._ import org.bitcoins.lnd.rpc.LndUtils._
import org.bitcoins.lnd.rpc.config.{LndInstance, LndInstanceLocal} import org.bitcoins.lnd.rpc.config.{LndInstance, LndInstanceLocal}
import scodec.bits.ByteVector import scodec.bits._
import signrpc._ import signrpc._
import walletrpc.{FinalizePsbtRequest, SendOutputsRequest, WalletKitClient} import walletrpc.{
FinalizePsbtRequest,
LeaseOutputRequest,
ListLeasesRequest,
ReleaseOutputRequest,
SendOutputsRequest,
WalletKitClient
}
import java.io.{File, FileInputStream} import java.io.{File, FileInputStream}
import java.net.InetSocketAddress import java.net.InetSocketAddress
@ -474,6 +481,64 @@ class LndRpcClient(val instance: LndInstance, binaryOpt: Option[File] = None)(
} }
} }
def listLeases(): Future[Vector[UTXOLease]] = {
listLeases(ListLeasesRequest())
}
def listLeases(request: ListLeasesRequest): Future[Vector[UTXOLease]] = {
logger.trace("lnd calling listleases")
wallet
.listLeases(request)
.map(_.lockedUtxos.toVector.map { lease =>
val txId = DoubleSha256DigestBE(lease.outpoint.get.txidBytes)
val vout = UInt32(lease.outpoint.get.outputIndex)
val outPoint = TransactionOutPoint(txId, vout)
UTXOLease(lease.id, outPoint, lease.expiration)
})
}
def leaseOutput(
outpoint: TransactionOutPoint,
leaseSeconds: Long): Future[Long] = {
val outPoint =
OutPoint(outpoint.txId.bytes, outputIndex = outpoint.vout.toInt)
val request = LeaseOutputRequest(id = LndRpcClient.leaseId,
outpoint = Some(outPoint),
expirationSeconds = leaseSeconds)
leaseOutput(request)
}
/** LeaseOutput locks an output to the given ID, preventing it from being available for any future coin selection attempts.
* The absolute time of the lock's expiration is returned.
* The expiration of the lock can be extended by successive invocations of this RPC.
* @param request LeaseOutputRequest
* @return Unix timestamp for when the lease expires
*/
def leaseOutput(request: LeaseOutputRequest): Future[Long] = {
logger.trace("lnd calling leaseoutput")
wallet.leaseOutput(request).map(_.expiration)
}
def releaseOutput(outpoint: TransactionOutPoint): Future[Unit] = {
val outPoint =
OutPoint(outpoint.txId.bytes, outputIndex = outpoint.vout.toInt)
val request =
ReleaseOutputRequest(id = LndRpcClient.leaseId, outpoint = Some(outPoint))
releaseOutput(request)
}
def releaseOutput(request: ReleaseOutputRequest): Future[Unit] = {
logger.trace("lnd calling releaseoutput")
wallet.releaseOutput(request).map(_ => ())
}
/** Broadcasts the given transaction /** Broadcasts the given transaction
* @return None if no error, otherwise the error string * @return None if no error, otherwise the error string
*/ */
@ -639,6 +704,12 @@ class LndRpcClient(val instance: LndInstance, binaryOpt: Option[File] = None)(
object LndRpcClient { object LndRpcClient {
/** Lease id should be unique per application
* this is the sha256 of "lnd bitcoin-s"
*/
val leaseId: ByteString =
hex"8c45ee0b90e3afd0fb4d6f39afa3c5d551ee5f2c7ac2d06820ed3d16582186d2"
/** The current version we support of Lnd */ /** The current version we support of Lnd */
private[bitcoins] val version = "0.13.1" private[bitcoins] val version = "0.13.1"