1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 18:10:42 +01:00

Add tx signing metrics (#1659)

Monitor the rate at which we sign channel txs and the duration of the
signing operations.
This commit is contained in:
Bastien Teinturier 2021-02-12 12:10:56 +01:00 committed by GitHub
parent 5d3958dd03
commit 15c1837d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 25 deletions

View File

@ -22,10 +22,21 @@ object Monitoring {
object Metrics {
val OnionPayloadFormat = Kamon.counter("crypto.sphinx.onion-payload-format")
val SignTxCount = Kamon.counter("crypto.keymanager.sign.count")
val SignTxDuration = Kamon.timer("crypto.keymanager.sign.duration")
}
object Tags {
val LegacyOnion = "legacy"
val TxOwner = "txOwner"
val TxType = "txType"
object TxTypes {
val CommitTx = "commit"
val HtlcTx = "htlc"
val RevokedTx = "revoked"
}
}
}

View File

@ -16,9 +16,6 @@
package fr.acinq.eclair.crypto.keymanager
import java.io.ByteArrayInputStream
import java.nio.ByteOrder
import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.DeterministicWallet.ExtendedPublicKey
import fr.acinq.bitcoin.{ByteVector64, Crypto, DeterministicWallet, Protocol}
@ -26,6 +23,9 @@ import fr.acinq.eclair.channel.{ChannelVersion, LocalParams}
import fr.acinq.eclair.transactions.Transactions.{CommitmentFormat, TransactionWithInputInfo, TxOwner}
import scodec.bits.ByteVector
import java.io.ByteArrayInputStream
import java.nio.ByteOrder
trait ChannelKeyManager {
def fundingPublicKey(keyPath: DeterministicWallet.KeyPath): ExtendedPublicKey
@ -62,8 +62,7 @@ trait ChannelKeyManager {
* @param publicKey extended public key
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with the private key that matches the input
* extended public key
* @return a signature generated with the private key that matches the input extended public key
*/
def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64
@ -75,8 +74,7 @@ trait ChannelKeyManager {
* @param remotePoint remote point
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with a private key generated from the input keys's matching
* private key and the remote point.
* @return a signature generated with a private key generated from the input key's matching private key and the remote point.
*/
def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, remotePoint: PublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64
@ -88,8 +86,7 @@ trait ChannelKeyManager {
* @param remoteSecret remote secret
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with a private key generated from the input keys's matching
* private key and the remote secret.
* @return a signature generated with a private key generated from the input key's matching private key and the remote secret.
*/
def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, remoteSecret: PrivateKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64
@ -105,7 +102,7 @@ trait ChannelKeyManager {
object ChannelKeyManager {
/**
* Create a BIP32 path from a public key. This path will be used to derive channel keys.
* Having channel keys derived from the funding public keys makes it very easy to retrieve your funds when've you've lost your data:
* Having channel keys derived from the funding public keys makes it very easy to retrieve your funds when you've lost your data:
* - connect to your peer and use DLP to get them to publish their remote commit tx
* - retrieve the commit tx from the bitcoin network, extract your funding pubkey from its witness data
* - recompute your channel keys and spend your output

View File

@ -21,11 +21,13 @@ import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.DeterministicWallet.{derivePrivateKey, _}
import fr.acinq.bitcoin.{Block, ByteVector32, ByteVector64, Crypto, DeterministicWallet}
import fr.acinq.eclair.crypto.Generators
import fr.acinq.eclair.crypto.Monitoring.{Metrics, Tags}
import fr.acinq.eclair.router.Announcements
import fr.acinq.eclair.secureRandom
import fr.acinq.eclair.transactions.Transactions
import fr.acinq.eclair.transactions.Transactions.{CommitmentFormat, TransactionWithInputInfo, TxOwner}
import fr.acinq.eclair.{KamonExt, secureRandom}
import grizzled.slf4j.Logging
import kamon.tag.TagSet
import scodec.bits.ByteVector
object LocalChannelKeyManager {
@ -97,12 +99,16 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: ByteVector32) extends
* @param publicKey extended public key
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with the private key that matches the input
* extended public key
* @return a signature generated with the private key that matches the input extended public key
*/
override def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64 = {
val privateKey = privateKeys.get(publicKey.path)
Transactions.sign(tx, privateKey.privateKey, txOwner, commitmentFormat)
// NB: not all those transactions are actually commit txs (especially during closing), but this is good enough for monitoring purposes
val tags = TagSet.Empty.withTag(Tags.TxOwner, txOwner.toString).withTag(Tags.TxType, Tags.TxTypes.CommitTx)
Metrics.SignTxCount.withTags(tags).increment()
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
val privateKey = privateKeys.get(publicKey.path)
Transactions.sign(tx, privateKey.privateKey, txOwner, commitmentFormat)
}
}
/**
@ -113,13 +119,17 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: ByteVector32) extends
* @param remotePoint remote point
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with a private key generated from the input keys's matching
* private key and the remote point.
* @return a signature generated with a private key generated from the input key's matching private key and the remote point.
*/
override def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, remotePoint: PublicKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64 = {
val privateKey = privateKeys.get(publicKey.path)
val currentKey = Generators.derivePrivKey(privateKey.privateKey, remotePoint)
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
// NB: not all those transactions are actually htlc txs (especially during closing), but this is good enough for monitoring purposes
val tags = TagSet.Empty.withTag(Tags.TxOwner, txOwner.toString).withTag(Tags.TxType, Tags.TxTypes.HtlcTx)
Metrics.SignTxCount.withTags(tags).increment()
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
val privateKey = privateKeys.get(publicKey.path)
val currentKey = Generators.derivePrivKey(privateKey.privateKey, remotePoint)
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
}
}
/**
@ -130,13 +140,16 @@ class LocalChannelKeyManager(seed: ByteVector, chainHash: ByteVector32) extends
* @param remoteSecret remote secret
* @param txOwner owner of the transaction (local/remote)
* @param commitmentFormat format of the commitment tx
* @return a signature generated with a private key generated from the input keys's matching
* private key and the remote secret.
* @return a signature generated with a private key generated from the input key's matching private key and the remote secret.
*/
override def sign(tx: TransactionWithInputInfo, publicKey: ExtendedPublicKey, remoteSecret: PrivateKey, txOwner: TxOwner, commitmentFormat: CommitmentFormat): ByteVector64 = {
val privateKey = privateKeys.get(publicKey.path)
val currentKey = Generators.revocationPrivKey(privateKey.privateKey, remoteSecret)
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
val tags = TagSet.Empty.withTag(Tags.TxOwner, txOwner.toString).withTag(Tags.TxType, Tags.TxTypes.RevokedTx)
Metrics.SignTxCount.withTags(tags).increment()
KamonExt.time(Metrics.SignTxDuration.withTags(tags)) {
val privateKey = privateKeys.get(publicKey.path)
val currentKey = Generators.revocationPrivKey(privateKey.privateKey, remoteSecret)
Transactions.sign(tx, currentKey, txOwner, commitmentFormat)
}
}
override def signChannelAnnouncement(witness: ByteVector, fundingKeyPath: KeyPath): ByteVector64 =