mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 14:33:06 +01:00
2021 12 08 block parsing bug caused by 65 byte taproot signatures (#3887)
* Add block 0000000000000000000593310d3b0cdc082af49f38b8a1611239072aef8433a8 test vector * Add test cases * wip * Fix bug where we were classifying taproot txs as P2WPKHWitnessV0 * revert logging level * Some cleanup * Add logback.xml for scripts, remove scheduler in scan bitcoind * Fix imports * Take ben's suggestion and add check to CryptoUtil.isValidPubKey
This commit is contained in:
parent
cb704da927
commit
0d37c4b54f
5 changed files with 143 additions and 22 deletions
109
app/scripts/src/main/resources/logback.xml
Normal file
109
app/scripts/src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,109 @@
|
|||
<configuration scan="true" scanPeriod="15 seconds" >
|
||||
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%date{yyyy-MM-dd'T'HH:mm:ss,SSXXX, UTC}UTC %level [%logger{0}] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<queueSize>8192</queueSize>
|
||||
<neverBlock>true</neverBlock>
|
||||
<appender-ref ref="STDOUT" />
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>bitcoin-s-scan-bitcoind.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- hourly rollover -->
|
||||
<fileNamePattern>${bitcoins.log.location}/logs/bitcoin-s-%d{yyyy-MM-dd_HH}.%i.log</fileNamePattern>
|
||||
|
||||
<!-- each file should be at most 100MB, keep 2 days of history, and at most 2GB in the archive -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>48</maxHistory>
|
||||
<totalSizeCap>2GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%date{yyyy-MM-dd'T'HH:mm:ss,SSXXX, UTC}UTC %level [%logger{0}] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="ASYNC"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
|
||||
<!-- ╔═══════════════════════╗ -->
|
||||
<!-- ║ Bitcoin-S logging ║-->
|
||||
<!-- ╚═══════════════════════╝ -->
|
||||
|
||||
<!-- ╔═══════════════════╗ -->
|
||||
<!-- ║ Configuration ║ -->
|
||||
<!-- ╚═══════════════════╝ -->
|
||||
|
||||
<!-- inspect resolved DB connection -->
|
||||
<logger name="org.bitcoins.db.SafeDatabase" level="WARN"/>
|
||||
|
||||
<!-- inspect resolved config -->
|
||||
<logger name="org.bitcoins.chain.config" level="WARN"/>
|
||||
<logger name="org.bitcoins.node.config" level="WARN"/>
|
||||
<logger name="org.bitcoins.wallet.config" level="WARN"/>
|
||||
|
||||
<!-- inspect table creation, etc -->
|
||||
<logger name="org.bitcoins.chain.db" level="WARN" />
|
||||
<logger name="org.bitcoins.node.db" level="WARN" />
|
||||
<logger name="org.bitcoins.wallet.db" level="WARN" />
|
||||
|
||||
<!-- ╔═════════════════╗ -->
|
||||
<!-- ║ Node module ║ -->
|
||||
<!-- ╚═════════════════╝ -->
|
||||
|
||||
<!-- See incoming message names and the peer it's sent from -->
|
||||
<logger name="org.bitcoins.node.networking.peer.PeerMessageReceiver" level="INFO"/>
|
||||
|
||||
<!-- See outgoing message names and the peer it's sent to -->
|
||||
<logger name="org.bitcoins.node.networking.peer.PeerMessageSender" level="INFO"/>
|
||||
|
||||
<!-- Inspect handling of headers and inventory messages -->
|
||||
<logger name="org.bitcoins.node.networking.peer.DataMessageHandler" level="INFO"/>
|
||||
|
||||
<!-- inspect TCP details -->
|
||||
<logger name="org.bitcoins.node.networking.P2PClientActor" level="INFO"/>
|
||||
|
||||
<!-- ╔════════════════════╗ -->
|
||||
<!-- ║ Chain module ║ -->
|
||||
<!-- ╚════════════════════╝ -->
|
||||
|
||||
<!-- See queries received by chain handler, as well as result of -->
|
||||
<!-- connecting new block headers to chain -->
|
||||
<logger name="org.bitcoins.chain.blockchain.ChainHandler" level="WARN"/>
|
||||
|
||||
<logger name="org.bitcoins.chain.validation" level="WARN"/>
|
||||
|
||||
<!-- ╔═════════════════════╗ -->
|
||||
<!-- ║ Wallet module ║ -->
|
||||
<!-- ╚═════════════════════╝ -->
|
||||
|
||||
<!-- ╔═══════════════════════════╗ -->
|
||||
<!-- ║ Bitcoin-S logging end ║-->
|
||||
<!-- ╚═══════════════════════════╝ -->
|
||||
|
||||
<!-- ╔═════════════════════════╗ -->
|
||||
<!-- ║ External libraries ║ -->
|
||||
<!-- ╚═════════════════════════╝ -->
|
||||
|
||||
<!-- Disable slick logging in server -->
|
||||
<logger name="slick" level="OFF"/>
|
||||
<logger name="com.zaxxer" level="INFO"/>
|
||||
|
||||
<!-- Get rid of messages like this:
|
||||
Connection attempt failed. Backing off new connection
|
||||
attempts for at least 800 milliseconds. -->
|
||||
<logger name="akka.http.impl.engine.client.PoolGateway" level="OFF"/>
|
||||
|
||||
<!-- get rid of "Slf4jLogger started" messages -->
|
||||
<logger name="akka.event.slf4j.Slf4jLogger" level="OFF"/>
|
||||
|
||||
<!-- get rid of "Running CoordinatedShutdown Phase" messages -->
|
||||
<logger name="akka.actor.slf4j.CoordinatedShutdown" level="OFF"/>
|
||||
|
||||
</configuration>
|
1
app/scripts/src/main/resources/reference.conf
Normal file
1
app/scripts/src/main/resources/reference.conf
Normal file
|
@ -0,0 +1 @@
|
|||
akka.http.host-connection-pool.max-connections=128
|
|
@ -3,8 +3,6 @@ package org.bitcoins.scripts
|
|||
import akka.NotUsed
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.scaladsl.{Keep, Sink, Source}
|
||||
import org.bitcoins.core.config.MainNet
|
||||
import org.bitcoins.core.protocol.Bech32mAddress
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
import org.bitcoins.core.protocol.script._
|
||||
import org.bitcoins.core.protocol.transaction.{Transaction, WitnessTransaction}
|
||||
|
@ -16,7 +14,6 @@ import org.bitcoins.server.util.BitcoinSAppScalaDaemon
|
|||
|
||||
import java.time.Instant
|
||||
import scala.concurrent.Future
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
||||
/** Useful script for scanning bitcoind
|
||||
* This file assumes you have pre-configured the connection
|
||||
|
@ -35,17 +32,14 @@ class ScanBitcoind()(implicit
|
|||
// val startHeight = 675000
|
||||
val endHeightF: Future[Int] = bitcoindF.flatMap(_.getBlockCount)
|
||||
|
||||
system.scheduler.scheduleAtFixedRate(0.seconds, 1.minutes) { () =>
|
||||
val f = for {
|
||||
bitcoind <- bitcoindF
|
||||
endHeight <- endHeightF
|
||||
_ <- countWitV1MempoolTxs(bitcoind)
|
||||
_ <- countTaprootTxsInBlocks(endHeight, 6, bitcoind)
|
||||
} yield ()
|
||||
f.failed.foreach(err =>
|
||||
logger.error(s"Failed to count witnes v1 mempool txs", err))
|
||||
()
|
||||
}
|
||||
val f = for {
|
||||
bitcoind <- bitcoindF
|
||||
endHeight <- endHeightF
|
||||
//_ <- countWitV1MempoolTxs(bitcoind)
|
||||
_ <- countTaprootTxsInBlocks(endHeight, 10000, bitcoind)
|
||||
} yield ()
|
||||
f.failed.foreach(err =>
|
||||
logger.error(s"Failed to count witness v1 mempool txs", err))
|
||||
Future.unit
|
||||
}
|
||||
|
||||
|
@ -60,8 +54,8 @@ class ScanBitcoind()(implicit
|
|||
bitcoind: BitcoindRpcClient,
|
||||
source: Source[Int, NotUsed],
|
||||
f: Block => T,
|
||||
numParallelism: Int =
|
||||
Runtime.getRuntime.availableProcessors() * 2): Future[Seq[T]] = {
|
||||
numParallelism: Int = Runtime.getRuntime.availableProcessors()): Future[
|
||||
Seq[T]] = {
|
||||
source
|
||||
.mapAsync(parallelism = numParallelism) { height =>
|
||||
bitcoind
|
||||
|
@ -116,9 +110,6 @@ class ScanBitcoind()(implicit
|
|||
val outputs = block.transactions
|
||||
.flatMap(_.outputs)
|
||||
.filter(_.scriptPubKey.isInstanceOf[WitnessScriptPubKeyV1])
|
||||
|
||||
logger.info(
|
||||
s"addresses=${outputs.map(_.scriptPubKey).map(spk => Bech32mAddress(spk.asInstanceOf[WitnessScriptPubKeyV1], MainNet))}")
|
||||
outputs.length
|
||||
}
|
||||
|
||||
|
|
|
@ -349,6 +349,25 @@ class TransactionTest extends BitcoinSUnitTest {
|
|||
assert(WitnessTransaction.fromHex(wtx.hex) == wtx)
|
||||
}
|
||||
|
||||
it must "parse 66cc4de192001d970244ffe32896282a1994fef80f01d35b216033aeacac1651" in {
|
||||
val hex =
|
||||
"01000000000101d498f5f6e3a4f04e88170c4dfaa8acef0cf9b949086c15e23d75d98a5d516ec50000000000ffffffff02b6ca050000000000225120af68875a973914dd815fff548a9104eeb9e44bee55b2b1a7428bab71ef33bd362b0103000000000017a914f92c8425eb54c3ef38e507a786297d2648441c0e87" +
|
||||
"014104720fcb29324a375b02b26c30cd45526dc7bdf668a59a4340f8bcf89275fafac91d0f763945373d17210650d717f5a1c465046c44c0ba2da74d6a76f61d1c370100000000"
|
||||
val tx = Transaction.fromHex(hex)
|
||||
assert(
|
||||
tx.txIdBE.hex == "66cc4de192001d970244ffe32896282a1994fef80f01d35b216033aeacac1651")
|
||||
assert(tx.hex == hex)
|
||||
}
|
||||
|
||||
it must "parse e597ad88c1366e53743ac201d0156abda38cde9720b80baf7328ce9fa677772d" in {
|
||||
val hex =
|
||||
"02000000000102d003fe1e06554e70a8e6a7026407c54f9ad1c3ca29a5486fd9825c74534cf338070000006a47304402200fa8b5e8d4b32aaf060ceb1de381d2cb9481b95591ac086f548869dabe2b625402207e347389e0a92f48c3f7fd3f4ae0e05878c7fa55584941dec3f347fa9c87ea8c0121039766e910a95b9be9b6504bfc1585c1c739a295f29099c9ee20d8fd91f58191bfffffffff22c93527a49ee479e05fb00023430f519402ee70c1d1871c5df0f896be70bb1f0000000000ffffffff02fd423800000000001976a91425ff4d7161289d9950d332a93b226abf429ff97188ac62060000000000001600144b109941eba2e10e5feb034342e9124c9edf9d310002473044022034b207e3008680ca7e3785d1a4fcbbd4f167ee8dad86a506ef886928f5072ce3022055647f8a2352e1c09fd9127fffc91c7918f90c5a8870e07760a744a4412df701012102dfac2fa93040d21e83c98f3b2d6b0a1dc95921c301118a6597e373d5ba6bc08300000000"
|
||||
val tx = Transaction.fromHex(hex)
|
||||
assert(
|
||||
tx.txIdBE.hex == "e597ad88c1366e53743ac201d0156abda38cde9720b80baf7328ce9fa677772d")
|
||||
assert(tx.hex == hex)
|
||||
}
|
||||
|
||||
private def findInput(
|
||||
tx: Transaction,
|
||||
outPoint: TransactionOutPoint): Option[(TransactionInput, Int)] = {
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.bitcoins.core.serializers.script.{
|
|||
}
|
||||
import org.bitcoins.core.util.{BitcoinScriptUtil, BytesUtil}
|
||||
import org.bitcoins.crypto.{
|
||||
CryptoUtil,
|
||||
ECDigitalSignature,
|
||||
ECPublicKey,
|
||||
ECPublicKeyBytes,
|
||||
|
@ -180,9 +181,9 @@ object ScriptWitness extends Factory[ScriptWitness] {
|
|||
//TODO: eventually only compressed public keys will be allowed in v0 scripts
|
||||
//https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#restrictions-on-public-key-type
|
||||
val isPubKey = {
|
||||
stack.nonEmpty &&
|
||||
((stack.head.size == 33 && (stack.head.head == 0x02 || stack.head.head == 0x03))
|
||||
|| (stack.head.size == 65 && stack.head.head == 0x04))
|
||||
stack.nonEmpty && (stack.head.size == 33 && (stack.head.head == 0x02 || stack.head.head == 0x03)
|
||||
|| (stack.head.size == 65 && stack.head.head == 0x04 && CryptoUtil
|
||||
.isValidPubKey(ECPublicKeyBytes(stack.head))))
|
||||
}
|
||||
if (stack.isEmpty) {
|
||||
EmptyScriptWitness
|
||||
|
|
Loading…
Add table
Reference in a new issue