mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-22 14:22:39 +01:00
Electrum: do not persist transaction locks (#953)
Locks held on utxos that are used in unpublished funding transactions should not be persisted. If the app is stopped before the funding transaction has been published the channel is forgotten and so should be locks on its funding tx utxos.
This commit is contained in:
parent
9032da5326
commit
6afe28d147
2 changed files with 63 additions and 36 deletions
|
@ -211,7 +211,7 @@ object SqliteWalletDb {
|
|||
("history" | historyCodec) ::
|
||||
("proofs" | proofsCodec) ::
|
||||
("pendingTransactions" | listOfN(uint16, txCodec)) ::
|
||||
("locks" | setCodec(txCodec))).as[PersistentData]
|
||||
("locks" | provide(Set.empty[Transaction]))).as[PersistentData]
|
||||
|
||||
def serialize(data: PersistentData): Array[Byte] = persistentDataCodec.encode(data).require.toByteArray
|
||||
|
||||
|
|
|
@ -17,11 +17,16 @@
|
|||
package fr.acinq.eclair.blockchain.electrum.db.sqlite
|
||||
|
||||
import fr.acinq.bitcoin.{Block, BlockHeader, OutPoint, Satoshi, Transaction, TxIn, TxOut}
|
||||
import fr.acinq.eclair.TestConstants
|
||||
import fr.acinq.eclair.{TestConstants, randomBytes, randomBytes32}
|
||||
import fr.acinq.eclair.blockchain.electrum.ElectrumClient
|
||||
import fr.acinq.eclair.blockchain.electrum.ElectrumClient.GetMerkleResponse
|
||||
import fr.acinq.eclair.blockchain.electrum.ElectrumWallet.PersistentData
|
||||
import fr.acinq.eclair.blockchain.electrum.db.sqlite.SqliteWalletDb.version
|
||||
import fr.acinq.eclair.wire.ChannelCodecs.txCodec
|
||||
import org.scalatest.FunSuite
|
||||
import scodec.Codec
|
||||
import scodec.bits.BitVector
|
||||
import scodec.codecs.{constant, listOfN, provide, uint16}
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
|
@ -34,34 +39,6 @@ class SqliteWalletDbSpec extends FunSuite {
|
|||
if (acc.size == n) acc else makeHeaders(n, acc :+ makeChildHeader(acc.last))
|
||||
}
|
||||
|
||||
test("add/get/list headers") {
|
||||
val db = new SqliteWalletDb(TestConstants.sqliteInMemory())
|
||||
val headers = makeHeaders(100)
|
||||
db.addHeaders(2016, headers)
|
||||
|
||||
val headers1 = db.getHeaders(2016, None)
|
||||
assert(headers1 === headers)
|
||||
|
||||
val headers2 = db.getHeaders(2016, Some(50))
|
||||
assert(headers2 === headers.take(50))
|
||||
|
||||
var height = 2016
|
||||
headers.foreach(header => {
|
||||
val Some((height1, header1)) = db.getHeader(header.hash)
|
||||
assert(height1 == height)
|
||||
assert(header1 == header)
|
||||
|
||||
val Some(header2) = db.getHeader(height1)
|
||||
assert(header2 == header)
|
||||
height = height + 1
|
||||
})
|
||||
}
|
||||
|
||||
test("serialize persistent data") {
|
||||
val db = new SqliteWalletDb(TestConstants.sqliteInMemory())
|
||||
|
||||
import fr.acinq.eclair.{randomBytes, randomBytes32}
|
||||
|
||||
def randomTransaction = Transaction(version = 2,
|
||||
txIn = TxIn(OutPoint(randomBytes32, random.nextInt(100)), signatureScript = Nil, sequence = TxIn.SEQUENCE_FINAL) :: Nil,
|
||||
txOut = TxOut(Satoshi(random.nextInt(10000000)), randomBytes(20)) :: Nil,
|
||||
|
@ -92,13 +69,63 @@ class SqliteWalletDbSpec extends FunSuite {
|
|||
)
|
||||
}
|
||||
|
||||
test("add/get/list headers") {
|
||||
val db = new SqliteWalletDb(TestConstants.sqliteInMemory())
|
||||
val headers = makeHeaders(100)
|
||||
db.addHeaders(2016, headers)
|
||||
|
||||
val headers1 = db.getHeaders(2016, None)
|
||||
assert(headers1 === headers)
|
||||
|
||||
val headers2 = db.getHeaders(2016, Some(50))
|
||||
assert(headers2 === headers.take(50))
|
||||
|
||||
var height = 2016
|
||||
headers.foreach(header => {
|
||||
val Some((height1, header1)) = db.getHeader(header.hash)
|
||||
assert(height1 == height)
|
||||
assert(header1 == header)
|
||||
|
||||
val Some(header2) = db.getHeader(height1)
|
||||
assert(header2 == header)
|
||||
height = height + 1
|
||||
})
|
||||
}
|
||||
|
||||
test("serialize persistent data") {
|
||||
val db = new SqliteWalletDb(TestConstants.sqliteInMemory())
|
||||
assert(db.readPersistentData() == None)
|
||||
|
||||
for (i <- 0 until 50) {
|
||||
val data = randomPersistentData
|
||||
db.persist(data)
|
||||
val Some(check) = db.readPersistentData()
|
||||
assert(check === data)
|
||||
assert(check === data.copy(locks = Set.empty[Transaction]))
|
||||
}
|
||||
}
|
||||
|
||||
test("read old persistent data") {
|
||||
import scodec.codecs._
|
||||
import SqliteWalletDb._
|
||||
import fr.acinq.eclair.wire.ChannelCodecs._
|
||||
|
||||
val oldPersistentDataCodec: Codec[PersistentData] = (
|
||||
("version" | constant(BitVector.fromInt(version))) ::
|
||||
("accountKeysCount" | int32) ::
|
||||
("changeKeysCount" | int32) ::
|
||||
("status" | statusCodec) ::
|
||||
("transactions" | transactionsCodec) ::
|
||||
("heights" | heightsCodec) ::
|
||||
("history" | historyCodec) ::
|
||||
("proofs" | proofsCodec) ::
|
||||
("pendingTransactions" | listOfN(uint16, txCodec)) ::
|
||||
("locks" | setCodec(txCodec))).as[PersistentData]
|
||||
|
||||
for (i <- 0 until 50) {
|
||||
val data = randomPersistentData
|
||||
val encoded = oldPersistentDataCodec.encode(data).require
|
||||
val decoded = persistentDataCodec.decode(encoded).require.value
|
||||
assert(decoded === data.copy(locks = Set.empty[Transaction]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue