1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-03-12 19:01:39 +01:00

Check that the xpub used to generated multisig addresses matches our chain

This commit is contained in:
sstone 2023-06-26 15:28:21 +02:00
parent 372a0c25d7
commit e65b261835
No known key found for this signature in database
GPG key ID: 7A73FE77DE2C4027
2 changed files with 26 additions and 2 deletions

View file

@ -183,7 +183,12 @@ class LocalKeyManager(seed: ByteVector, chainHash: ByteVector32) extends KeyMana
}
private def deriveSwapInServerPublicKey(localNodeId: PublicKey, serverExtendedPublicKey: String): PublicKey = {
val (_, xpub) = DeterministicWallet.ExtendedPublicKey.decode(serverExtendedPublicKey)
val (prefix, xpub) = DeterministicWallet.ExtendedPublicKey.decode(serverExtendedPublicKey)
val expectedPrefix = chainHash match {
case Block.LivenetGenesisBlock.hash => DeterministicWallet.xpub
case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash => DeterministicWallet.tpub
}
require(prefix == expectedPrefix, "server xpub chain is on the wrong chain")
val h = Crypto.sha256(localNodeId.value)
val path = h.bits.grouped(16).toSeq.map(uint16.decode(_).require.value.toLong)
DeterministicWallet.derivePublicKey(xpub, path).publicKey

View file

@ -19,7 +19,7 @@ package fr.acinq.eclair.crypto
import fr.acinq.bitcoin.scala.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.scala.DeterministicWallet.KeyPath
import fr.acinq.bitcoin.scala.{Block, ByteVector32, DeterministicWallet, MnemonicCode}
import fr.acinq.eclair.TestConstants
import fr.acinq.eclair.{TestConstants, randomKey}
import fr.acinq.eclair.channel.ChannelVersion
import org.scalatest.funsuite.AnyFunSuite
import scodec.bits._
@ -168,5 +168,24 @@ class LocalKeyManagerSpec extends AnyFunSuite {
val aliceSwapInServerXpub = "tpubDCvYeHUZisCMVTSfWDa1yevTf89NeF6TWxXUQwqkcmFrNvNdNvZQh1j4m4uTA4QcmPEwcrKVF8bJih1v16zDZacRr4j9MCAFQoSydKKy66q"
val swapInAddressBob = bobKeyManager.multisigSwapInAddress(bobKeyManager.kmpNodeKey.publicKey, aliceSwapInServerXpub, swapInRefundDelay)
assert(swapInAddressBob == "bcrt1qjs2l2ey9rk742hvv25kjghqvqdyhvf7vshwesgflzch9kcq2c8lqh60h44")
// check that the provided server xpub matches our chain
val mainnetKeyManager = {
val entropy = ByteVector32.fromValidHex("0101010101010101010101010101010101010101010101010101010101010101")
val seed = MnemonicCode.toSeed(MnemonicCode.toMnemonics(entropy), "").take(32)
new LocalKeyManager(seed, Block.LivenetGenesisBlock.hash)
}
intercept[IllegalArgumentException] {
mainnetKeyManager.multisigSwapInAddress(randomKey.publicKey, "tpubDDt5vQap1awkyDXx1z1cP7QFKSZHDCCpbU8nSq9jy7X2grTjUVZDePexf6gc6AHtRRzkgfPW87K6EKUVV6t3Hu2hg7YkHkmMeLSfrP85x41", swapInRefundDelay)
}
val testnetKeyManager = {
val entropy = ByteVector32.fromValidHex("0101010101010101010101010101010101010101010101010101010101010101")
val seed = MnemonicCode.toSeed(MnemonicCode.toMnemonics(entropy), "").take(32)
new LocalKeyManager(seed, Block.TestnetGenesisBlock.hash)
}
intercept[IllegalArgumentException] {
testnetKeyManager.multisigSwapInAddress(randomKey.publicKey, "xpub6DWTQAm8JJzJhRM6Zo2XBC4szKTdDohm3qYV6H6bdCm8wZo2QGi8Vwz8R4bpZfLedXTr55sdb1V3Y8yt6F2oQTaQcWoScE784NrG6Jd5gAo", swapInRefundDelay)
}
}
}